Data Exposure in Actix with Jwt Tokens
Data Exposure in Actix with Jwt Tokens — how this specific combination creates or exposes the vulnerability
Data exposure in Actix applications using JWT tokens typically occurs when sensitive payloads, signing keys, or token metadata are unintentionally returned to unauthenticated or low-privilege callers. Because middleBrick performs unauthenticated black-box scanning, it can detect endpoints that reflect JWT contents, leak key material via error messages, or expose introspection results without proper access controls.
One common pattern in Actix is binding JWT claims directly to route extractors without verifying scopes or audience for the requested resource. If an endpoint returns user roles, email, or internal identifiers in the response body and lacks authorization checks, middleBrick may flag this as Data Exposure. For example, a handler that decodes a token and echoes claims can leak PII or role mappings when an attacker supplies a valid but unrelated token:
use actix_web::{web, HttpResponse, Responder};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
async fn profile(token: web::Query) -> impl Responder {
let token = token.token.clone();
let validation = Validation::new(Algorithm::HS256);
// WARNING: no audience or required-claims validation
let token_data = decode::(
&token,
&DecodingKey::from_secret("secret".as_ref()),
&validation,
);
match token_data {
Ok(data) => HttpResponse::Ok().json(data.claims),
Err(_) => HttpResponse::Unauthorized().finish(),
}
}
In this snippet, the decoded claims (which may include email, roles, or tenant IDs) are returned directly. middleBrick’s Data Exposure checks look for such direct reflections in unauthenticated or insufficiently scoped routes. A second exposure vector arises when Actix error handling inadvertently includes JWT-related details in responses. For instance, failing to sanitize validation errors can surface whether a token was malformed, expired, or signed with a different key, aiding enumeration attacks.
Additionally, if an Actix service exposes a debug or health endpoint that reports token metadata (e.g., decoded header or payload) without authentication, middleBrick will identify this as Data Exposure. Real-world payloads may inadvertently include internal route names, version info, or signing algorithm details that should remain internal. The scanner correlates these findings with the JWT Tokens category under the 12 parallel checks, emphasizing the need to restrict what is returned and to whom.
Jwt Tokens-Specific Remediation in Actix — concrete code fixes
Remediation focuses on strict validation, least-privilege claim usage, and avoiding any leakage of token internals. You should validate audience, issuer, and required claims, and never return raw decoded payloads from public or unauthenticated endpoints. Below is a hardened Actix handler that decodes with audience and issuer checks and returns only safe, transformed data:
use actix_web::{web, HttpResponse, Responder};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation, TokenData};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
email: String,
roles: Vec,
exp: usize,
aud: String,
iss: String,
}
async fn profile_secure(
token: web::Query,
) -> impl Responder {
let token = token.token.clone();
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = true;
validation.set_audience(&["my-api-audience"]);
validation.set_issuer(&["https://auth.example.com"]);
validation.required_spec_claims = "exp,iss,aud".split(',').collect();
match decode::(
&token,
&DecodingKey::from_secret("secret".as_ref()),
&validation,
) {
Ok(TokenData { claims, .. }) => {
// Return only what the caller is allowed to see
HttpResponse::Ok().json(UserProfile {
email: claims.email,
roles: claims.roles,
})
}
Err(e) => {
// Avoid leaking token details in error responses
HttpResponse::Unauthorized().json(ErrorResponse {
error: "invalid_token",
message: "authentication failed",
})
}
}
}
#[derive(Serialize)]
struct UserProfile {
email: String,
roles: Vec,
}
#[derive(Serialize)]
struct ErrorResponse {
error: &'static str,
message: &'static str,
}
For endpoints that must introspect token metadata, require an authenticated management scope and avoid echoing raw headers. Never expose a public endpoint that decodes and returns JWT header or payload without strict authorization. If you need key rotation or algorithm agility, centralize validation logic and ensure error paths do not disclose stack traces or token content.
middleBrick’s scans can verify that such refinements are reflected in the runtime behavior. By running the CLI tool locally—middlebrick scan <url>—you can repeatedly validate that sensitive JWT-related data is not surfaced to unauthenticated callers. For CI/CD integration, the GitHub Action can enforce that new routes or changes to token handling do not introduce regressions in data exposure checks.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |