Por que Rust é o novo padrão de segurança na web?
\nQuando se trata de segurança web, muitos desenvolvedores lembram imediatamente de ORM, consultas preparadas e escape HTML. Mas e se eu lhe dissesse que a própria linguagem de programação pode assumir a maior parte desse trabalho? É exatamente isso que o Rust faz — uma linguagem que não perdoa erros, mas também não permite que você os cometa.
\n\nNeste artigo, vamos analisar como a segurança do Rust se manifesta nos dois ataques mais críticos a aplicações web: injeções SQL e XSS (cross-site scripting). Você verá exemplos reais de código, comparação com Python e entenderá por que o Rust está se tornando a escolha número um para projetos onde o preço do erro é a segurança dos usuários.
\n\nComo o Rust previne injeções SQL: da teoria à prática
\nInjeção SQL é um clássico. Todos sabemos que é necessário usar consultas preparadas. Mas no Rust, esse padrão está incorporado na cultura da linguagem no nível dos tipos e do sistema de borrow checker.
\n\nComparação de abordagens: Python vs Rust
\nVeja um código típico em Python que pode ser vulnerável:
\n# Python (perigoso)\nuser_input = "'; DROP TABLE users; --"\nquery = f"SELECT * FROM users WHERE name = '{user_input}'"\ncursor.execute(query)\n\nMesmo usando psycopg2, você pode acidentalmente esquecer o escape. O Rust, por outro lado, força você a pensar de forma diferente.
No Rust, com as bibliotecas sqlx ou diesel, você não consegue simplesmente inserir uma string em uma consulta — o sistema de tipos não permite:
// Rust com sqlx (seguro)\nuse sqlx::PgPool;\n\nlet user_input = "'; DROP TABLE users; --";\nlet user: Option<User> = sqlx::query_as(\n "SELECT * FROM users WHERE name = $1"\n)\n.bind(&user_input) // Vinculação type-safe\n.fetch_optional(&pool)\n.await?;\n\nObserve o $1 e o .bind(). O Rust não permite inserir o valor diretamente na string da consulta. Isso não é apenas uma convenção — é uma condição obrigatória para a compilação. A segurança do Rust aqui se manifesta no fato de que você fisicamente não consegue criar uma injeção SQL se usar as bibliotecas corretas.
Por que isso funciona no nível dos tipos?
\nNo Rust, a string da consulta e os dados são tipos diferentes. Bibliotecas como sqlx verificam as consultas em tempo de compilação (compile-time checked queries). Se você tentar fazer algo perigoso, o código simplesmente não compila:
// Isso não vai compilar!\nlet query = format!("SELECT * FROM users WHERE name = '{}'", user_input);\nsqlx::query(&query); // Erro: espera-se &str, não String com substituição\n\nO sistema de ownership e borrowing não permite que você "engula" dados perigosos acidentalmente. Isso não é mágica — é disciplina de engenharia embutida na linguagem.
\n\nProteção contra XSS: escape e verificação automática
\nXSS é quando um invasor insere scripts no seu HTML. No Rust, você pode se proteger em vários níveis, e algumas verificações ocorrem antes mesmo da execução do programa.
\n\nTemplate engines com escape automático
\nEm Python, você usa jinja2 com autoescape=true. No Rust, existem askama ou maud, que fazem o mesmo, mas com segurança de tipos. Veja um exemplo com askama:
// Rust com askama (template engine)\nuse askama::Template;\n\n#[derive(Template)]\n#[template(source = "<h1>Olá, {{ name }}!</h1>", ext = "html")]\nstruct HelloTemplate {\n name: String,\n}\n\nfn main() {\n let t = HelloTemplate {\n name: "<script>alert('XSS')</script>".to_string(),\n };\n let rendered = t.render().unwrap();\n // Saída: <h1>Olá, <script>...</h1>\n // As tags são escapadas automaticamente!\n}\n\nObserve