Server Side Template Injection in Actix with Jwt Tokens
Server Side Template Injection in Actix with Jwt Tokens
Server Side Template Injection (SSTI) in Actix applications can intersect with JWT token handling in ways that amplify security risks. When an Actix web service parses and reflects JWT claims within server-side templates (for example, rendering user metadata or debug output), unsanitized input derived from the token can become a vector for template injection. SSTI occurs when an attacker can inject template syntax that is then evaluated by the server-side rendering engine, potentially leading to arbitrary code execution or information disclosure.
Consider an endpoint that decodes a JWT, extracts a user-supplied field such as a username or role claim, and passes it directly to a templating engine like Askama or Tera without validation or escaping. If the template includes constructs like {{ user_input }} and the input contains template syntax (e.g., {% include "malicious" %} or {{ config }}), the server may execute unintended logic or read sensitive files. JWT tokens are often trusted because they are cryptographically signed; however, signature verification does not guarantee that claims are safe for template rendering. An attacker who can influence a claim (via a weak iss/aud validation, token replay, or a vulnerable client-side construction) may craft a token whose payload introduces template directives that the server evaluates.
In Actix, this risk is compounded when developers use per-request state derived from tokens to dynamically configure templates. For example, if a JWT’s scope or resource claims are mapped into a template context object without strict allowlisting, an attacker might embed expressions that enumerate environment variables or invoke filesystem helpers. Because Actix is a Rust framework, the impact can vary depending on the template engine’s sandboxing, but the principle remains: trust in the token’s integrity does not equate to safety in the rendering layer. Real-world patterns include logging or error pages that include user claims via templates, or admin dashboards that render token metadata in HTML using server-side logic.
A concrete scenario: an API accepts an Authorization header with a JWT, extracts a custom claim display_name, and passes it to an Askama template. If the claim contains {{ 7 * 7 }} and the template does not autoescape or use strict context isolation, the server might evaluate the expression and reveal internal data or behavior. This pattern maps to OWASP API Top 10 API05:2023 – Security Misconfiguration, and may intersect with Insecure Deserialization or Improper Neutralization of Special Elements used in an API Attack (CWE-74). middleBrick scans detect such mismatches by correlating OpenAPI specifications (where response templates or server-side rendering hints are documented) with runtime outputs that include suspicious variable resolution or unescaped user input.
Jwt Tokens-Specific Remediation in Actix
Remediation focuses on strict separation of authentication data and presentation logic, and rigorous validation of any token-derived input that reaches templates. Do not pass JWT claims directly into server-side template contexts unless they have been validated, normalized, and escaped. Below are concrete steps and code examples for Actix-based Rust services.
1. Validate and Limit Token Claims
Verify the JWT signature and enforce strict claim checks (iss, aud, exp) before using any payload. Only extract specific, allowlisted claims for non-template purposes (e.g., authentication/authorization). If you must pass data to a template, map it through a safe DTO that discards or normalizes dangerous fields.
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation, TokenData};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
exp: usize,
// Only include claims you absolutely need in templates
display_name: Option,
}
fn validate_token(token: &str) -> Result, jsonwebtoken::errors::Error> {
let mut validation = Validation::new(Algorithm::HS256);
validation.set_issuer(&["your-issuer"]);
validation.set_audience(&["your-audience"]);
let key = DecodingKey::from_secret("your-secret".as_ref());
decode::(token, &key, &validation)
}
2. Avoid Passing Raw Claims to Templates
Instead of injecting the whole claims map or struct, construct a minimal view model with escaped or safe values. Use a templating engine that supports autoescaping (e.g., Askama with autoescape) and never concatenate token strings into template source.
use askama::Template;
#[derive(Template)]
#[template(path = "user_profile.html")]
struct UserProfileTemplate {
username: String, // sanitized, not raw JWT claim
is_admin: bool,
}
// In handler
let token_data = validate_token(auth_header)?;
let safe_username = token_data.claims.sub; // or a mapped alias
let display_name = token_data.claims.display_name.unwrap_or_else(|| "Guest".to_string());
let template = UserProfileTemplate {
username: safe_username,
is_admin: check_admin(&display_name),
};
Ok(HttpResponse::Ok().content_type("text/html").body(template.render().unwrap_or_default()))
3. Enforce Context-Aware Escaping
Ensure your template engine applies proper escaping for the target context (HTML, JS, URL). If you must include token-derived strings in JavaScript sections, use strict serialization and avoid inline evaluation.
<!-- user_profile.html (Askama) -->
<div>Welcome, {{ username | e }}</div>
<script>
var username = {{ js_escape(&username) }};
</script>
4. Use Middleware for Token Normalization
Implement an Actix middleware or extractor that normalizes token data into a safe request extension, removing or encoding fields that should never reach templates. This keeps route handlers focused on business logic and prevents accidental leakage of sensitive claims.
struct SafeUser {
pub id: String,
pub display_name: String,
}
fn safe_user_extractor(req: &HttpRequest) -> Option<SafeUser> {
req.extensions().get::().cloned()
}
// In configure_app
App::new()
.wrap(AuthMiddleware)
.route("/profile", web::get().to(profile_handler))
5. Audit and Limit Template Features
Disable or restrict unsafe template functions (e.g., includes, eval-like filters) in your rendering configuration. Prefer compile-time templates with strict schema validation over dynamic template assembly that incorporates token-derived strings.