HIGH llm data leakageactixjwt tokens

Llm Data Leakage in Actix with Jwt Tokens

Llm Data Leakage in Actix with Jwt Tokens — how this specific combination creates or exposes the vulnerability

When an Actix web service exposes an unauthenticated or improperly scoped LLM endpoint and issues JSON Web Tokens (JWT) for authorization, the combination can inadvertently leak sensitive data through model outputs. JWTs often carry user identity, roles, or scopes in their payload; if those tokens are accepted as input to an LLM endpoint without strict validation and redaction, the model may reflect secrets in its responses.

middleBrick detects this risk as part of its LLM/AI Security checks, including unauthenticated LLM endpoint detection and system prompt leakage detection. During a scan, the tool submits active prompt injection probes and analyzes LLM responses for PII, API keys, and executable code. If an Actix endpoint echoes JWT claims or authorization details in prompts or passes them to tool-calling flows, the scan can identify system prompt leakage and excessive agency patterns that expose token-derived data.

Consider an Actix handler that builds an LLM prompt from JWT claims to personalize responses:

use actix_web::{web, HttpResponse, Responder};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};

async fn chat_handler(
    token: String,
    body: web::Json,
) -> impl Responder {
    let token_data = decode::(
        &token,
        &DecodingKey::from_secret(SECRET.as_ref()),
        &Validation::new(Algorithm::HS256),
    )?;
    let user_id = token_data.claims.sub;
    let prompt = format!("User {} asks: {}", user_id, body.question);
    let response = llm_complete(&prompt).await?;
    HttpResponse::Ok().json(Response { answer: response })
}

If llm_complete receives the raw user_id derived from the JWT and the model is not constrained, it may reproduce that identifier in its output, leaking what should be a protected claim. middleBrick’s output scanning would flag PII in the responses, and its system prompt leakage detection would check whether the prompt structure itself reveals token-derived context.

Another scenario involves tool-calling patterns where an Actix service passes JWT-based permissions into function schemas or tool descriptions. The LLM may then reflect those permissions in function calls or explanatory text, creating a data leakage channel. For example, including a scope list in the prompt can expose privileged operations that should remain internal. The scanner’s excessive agency detection identifies when tool_calls or function_call patterns increase the risk of unintended data exposure.

Additionally, if an LLM endpoint is unauthenticated but the surrounding Actix routes expect a valid JWT, misconfiguration can allow public queries that still embed sensitive context in prompts. middleBrick flags unauthenticated LLM endpoints and highlights mismatches between expected authentication and runtime behavior, helping teams spot routes where JWT handling is incomplete.

Jwt Tokens-Specific Remediation in Actix — concrete code fixes

Remediation focuses on preventing JWT-derived data from reaching the LLM and ensuring that authorization context is never reflected in model outputs. Apply the following patterns in your Actix routes.

1) Redact or omit JWT claims from prompts. Instead of injecting raw identifiers, use a generic role or a hashed, non-sensitive reference:

use actix_web::{web, HttpResponse};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};

async fn chat_handler_safe(
    token: String,
    body: web::Json,
) -> impl Responder {
    let token_data = decode::(
        &token,
        &DecodingKey::from_secret(SECRET.as_ref()),
        &Validation::new(Algorithm::HS256),
    )?;
    // Use only non-sensitive role, never user ID or scopes
    let role = token_data.claims.role; // e.g., "user", "admin"
    let prompt = format!("A {} asks: {}", role, body.question);
    let response = llm_complete(&prompt).await?;
    HttpResponse::Ok().json(Response { answer: response })
}

2) Validate and sanitize all inputs that influence prompt construction. Ensure that no JWT claims containing PII or secrets are concatenated into the prompt string. If you must include contextual markers, hash them or replace them with opaque tokens:

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

fn hash_user_id(sub: &str) -> u64 {
    let mut hasher = DefaultHasher::new();
    sub.hash(&mut hasher);
    hasher.finish()
}

// In handler:
let user_fingerprint = hash_user_id(&token_data.claims.sub);
let prompt = format!("User session {} asks: {}", user_fingerprint, body.question);

3) Isolate LLM prompts from authorization logic. Keep JWT validation separate from prompt building, and avoid passing permission lists or scopes into tool schemas. If tool-calling is required, define generic tool descriptions that do not expose role-specific operations:

async fn build_tools() -> Vec {
    vec![
        Tool {
            name: "search".to_string(),
            description: "Search public resources".to_string(),
            parameters: json!({ "type": "object", "properties": { "query": { "type": "string" } } }),
        },
    ]
}

4) Enforce authentication checks before allowing access to routes that invoke LLM endpoints. Use Actix guards or middleware to ensure only requests with valid JWTs reach handlers that call LLM APIs. This prevents unauthenticated exposure of prompts that may embed sensitive context:

use actix_web::dev::ServiceRequest;
use actix_web::Error;
use actix_web_httpauth::extractors::bearer::BearerAuth;

async fn auth_middleware(
    req: ServiceRequest,
    credentials: BearerAuth,
) -> Result {
    // Validate token here; reject if invalid
    decode::(
        credentials.token(),
        &DecodingKey::from_secret(SECRET.as_ref()),
        &Validation::new(Algorithm::HS256),
    )?;
    Ok(req.into_response(req.into_response().map_into_right().unwrap()))
}

By combining these practices—minimal claim usage, hashing for non-sensitive references, isolated tool definitions, and strict authentication—you reduce the risk that JWT-derived data appears in LLM responses or tool behaviors, aligning with the findings that middleBrick reports for LLM/AI Security.

Related CWEs: llmSecurity

CWE IDNameSeverity
CWE-754Improper Check for Unusual or Exceptional Conditions MEDIUM

Frequently Asked Questions

How does middleBrick detect LLM data leakage involving JWT-derived context in Actix services?
middleBrick runs active prompt injection probes and analyzes LLM responses for PII and secrets. It checks for system prompt leakage patterns and output scanning, flagging when JWT claims or authorization details appear in model outputs or tool descriptions.
Can middleBrick integrate into CI/CD to prevent JWT data leakage before deployment?
Yes, via the GitHub Action you can add API security checks to your CI/CD pipeline and fail builds if the security score drops below your threshold, helping catch JWT-related leakage early.