HIGH server side template injectionactixrust

Server Side Template Injection in Actix (Rust)

Server Side Template Injection in Actix with Rust

Server Side Template Injection (SSTI) in Actix using Rust occurs when an application dynamically renders templates with user-controlled data and fails to properly sanitize or isolate template expressions. Actix-web itself does not include a built-in template engine, but it is commonly paired with engines such as Askama, Tera, or Handlebars. These engines support variable substitution, filters, and in some cases, limited expression evaluation. If user input is directly interpolated into template strings or passed into partials without validation, an attacker can inject template code that leads to unintended behavior.

For example, consider an Askama template that includes a user-controlled {{ user_name }}. Askama is compiled to Rust and normally safe, but if the application allows dynamic template selection or passes unsanitized input into a template that supports includes or raw blocks, the attack surface changes. An attacker might supply a payload designed to traverse context or invoke object methods, depending on the engine’s parsing rules. With Tera, which uses a Jinja-like syntax, a malicious input like {% include "secret.html" %} could read files if the engine evaluates includes and the application exposes a filesystem path. In a black-box scan, middleBrick tests for such injection by submitting template-like payloads and observing whether the response contains unexpected data, errors, or code execution indicators.

Because these templates are rendered on the server, injected expressions can read local files, access environment variables, or trigger SSRF depending on the engine and how the application context is structured. The combination of Actix’s async runtime and a permissive template engine configuration means that an unauthenticated attacker can probe endpoints that render dynamic content without needing credentials. middleBrick’s unauthenticated scanning checks for patterns where user input reaches template rendering paths and whether the engine’s behavior allows unauthorized operations, such as variable introspection or inclusion of external resources.

Real-world payloads differ by engine. For Tera, an attacker might try {{ 7*7 }} to test arithmetic evaluation, or {{ config }} to inspect the template context. For Askama, attempts might involve path traversal through object attributes if the context is not carefully limited. Because these tests are performed without authentication, they align with how an external attacker would probe an API. The scanner’s reporting highlights which endpoints render templates, what engine is inferred from responses or spec annotations, and whether findings align with broader categories such as Data Exposure or Unsafe Consumption.

Rust-Specific Remediation in Actix

Remediation focuses on ensuring templates are precompiled, context is strictly typed, and user input never reaches template parsing logic. With Actix-web, prefer compile-time template engines such as Askama, where templates are converted to Rust code during build. This approach eliminates runtime evaluation of user-controlled expressions. Define strict data structures for your context and never construct templates or partials from request parameters.

For Tera, load templates once at startup and avoid dynamic template selection. Configure the engine to disable includes and other potentially dangerous features. In your Actix handler, pass only sanitized, typed data to the render function. Below is an example using Askama where the context is a simple, non-generic struct:

use actix_web::{web, HttpResponse};
use askama::Template;

#[derive(Template)]
#[template(path = "greeting.html")]
struct GreetingTemplate {
    username: String,
}

async fn greet(info: web::Query<GreetingInput>) -> HttpResponse {
    // Validate input length and characters before using
    let safe_username = sanitize_username(&info.username);
    let template = GreetingTemplate { username: safe_username };
    HttpResponse::Ok().content_type("text/html").body(template.render().unwrap_or_else(|_| String::from("Error")))
}

fn sanitize_username(input: &str) -> String {
    input.chars().filter(|c| c.is_alphanumeric() || c.is_whitespace()).take(64).collect()
}

For Tera, initialize the engine in your Actix app data and reuse it across requests. Disable features that enable includes or eval:

use actix_web::{web, App, HttpResponse, HttpServer};
use tera::Tera;

async fn handler(tera: web::Data<Tera>, query: web::Query<serde_json::Value>) -> HttpResponse {
    // Do not use query["template"] to select a template name
    let mut context = tera::Context::new();
    context.insert("username", "trusted_user");
    match tera.render("static_template.html", &context) {
        Ok(html) => HttpResponse::Ok().body(html),
        Err(_) => HttpResponse::InternalServerError().body("Render error"),
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let tera = Tera::new("templates/**/*").expect("Failed to load Tera");
    // Disable includes if your use case does not require them
    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(tera.clone()))
            .route("/greet", actix_web::web::get().to(handler))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Additionally, validate and sanitize all inputs before they reach rendering logic. Reject or encode special characters based on context (HTML, URL, JS). Avoid accepting template names or paths from clients, and enforce allowlists for any dynamic partials. middleBrick’s scans can verify whether endpoints expose template-related errors or data exposure after these controls are applied.

Frequently Asked Questions

Can SSTI in Actix lead to remote code execution in Rust-based APIs?
SSTI in Actix with Rust typically results in data leakage or unintended logic execution rather than direct remote code execution, because Rust templates are compiled and user input is generally confined to rendering. However, if the engine supports dynamic includes or eval features and the application exposes filesystem paths, an attacker may read sensitive data or trigger SSRF. The impact depends on the template engine configuration and whether user input reaches template parsing.
Does middleBrick test for SSTI in Actix APIs using Rust?
Yes, middleBrick runs a series of unauthenticated checks, including input validation and Data Exposure tests, to identify whether user-controlled data reaches template rendering paths. The scanner looks for signs of template-like injections and reports findings with severity and remediation guidance, without making assumptions about the internal Rust tooling.