CodeQL documentation

Cross-site scripting

ID: rust/xss
Kind: path-problem
Security severity: 6.1
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-079
   - external/cwe/cwe-116
Query suites:
   - rust-code-scanning.qls
   - rust-security-extended.qls
   - rust-security-and-quality.qls

Click to see the query in the CodeQL repository

Directly writing user input (for example, an HTTP request parameter) to a webpage, without properly sanitizing the input first, allows for a cross-site scripting vulnerability.

Recommendation

To guard against cross-site scripting, consider encoding/escaping the untrusted input before including it in the HTML.

Example

The following example shows a simple web handler that writes a URL path parameter directly to an HTML response, leaving the website vulnerable to cross-site scripting:

use actix_web::{web, HttpResponse, Result};

// BAD: User input is directly included in HTML response without sanitization
async fn vulnerable_handler(path: web::Path<String>) -> impl Responder {
    let user_input = path.into_inner();

    let html = format!(
        r#"
        <!DOCTYPE html>
        <html>
        <head><title>Welcome</title></head>
        <body>
            <h1>Hello, {}!</h1>
        </body>
        </html>
        "#,
        user_input
    );

    Html::new(html) // Unsafe: User input included directly in the response
}

To fix this vulnerability, the user input should be HTML-encoded before being included in the response. In the following example, encode_text from the html_escape crate is used to achieve this:

use actix_web::{web, HttpResponse, Result};

// GOOD: Manual HTML encoding using an `html_escape::encode_text` function
async fn safe_handler_with_encoding(path: web::Path<String>) -> impl Responder {
    let user_input = path.into_inner();
    let escaped_input = html_escape::encode_text(&user_input);
    let html = format!(
        r#"
        <!DOCTYPE html>
        <html>
        <head><title>Welcome</title></head>
        <body>
            <h1>Hello, {}!</h1>
        </body>
        </html>
        "#,
        escaped_input
    );

    Html::new(html) // Safe: user input is HTML-encoded
}

References

  • © GitHub, Inc.
  • Terms
  • Privacy