Cors Wildcard in Actix with Dynamodb
Cors Wildcard in Actix with Dynamodb — how this specific combination creates or exposes the vulnerability
A CORS wildcard (*) in an Actix web service that also interacts with Amazon DynamoDB can unintentionally expose data and amplify authorization bypass risks. When * is allowed for Access-Control-Allow-Origin, any origin can make requests and read responses. If the Actix handler uses per-request DynamoDB credentials or temporary tokens passed from the browser, the wildcard allows malicious sites to issue queries on behalf of the client and exfiltrate the returned records.
In a typical setup, an Actix route might call DynamoDB to fetch user data after validating a session cookie. The browser sends credentials (cookies or an Authorization header) only to same-origin requests. However, with a wildcard CORS policy, a compromised frontend served from another origin can still trigger preflighted OPTIONS requests that succeed. The attacker’s JavaScript can read the responses if the server does not also validate Origin and does not restrict Access-Control-Allow-Credentials. This turns the DynamoDB read into a data leak channel, effectively bypassing same-origin policy protections.
Moreover, wildcard CORS combined with DynamoDB’s fine-grained IAM policies can lead to privilege escalation if the Actix backend uses a broad IAM role when calling DynamoDB. If the backend does not enforce per-user authorization before constructing the DynamoDB request, an attacker can manipulate parameters (such as the partition key) to access other users’ items. The CORS wildcard makes it easier to chain this by enabling cross-origin requests that the backend mistakenly treats as trusted, since the presence of credentials headers may be misinterpreted as an authenticated session.
Consider an example where the Actix server forwards a DynamoDB query to list user documents. If CORS is misconfigured, an attacker’s page can repeatedly call the endpoint to harvest data. Even if the backend validates session tokens, a missing Vary: Origin header can cause shared caches to serve the response to other origins, further extending the exposure. This is especially dangerous when responses contain sensitive attributes that are not encrypted at rest in DynamoDB, as the leak occurs after the data is decrypted by the service.
To contextualize risk, middleBrick’s checks for CORS misconfiguration and overprivileged IAM roles relevant to DynamoDB interactions. The scanner tests whether the Actix endpoint responds with a wildcard Access-Control-Allow-Origin and whether the backend’s authorization logic correctly scopes DynamoDB requests to the requesting user. These findings map to OWASP API Top 10 controls and highlight the need to couple CORS policies with strict identity-based access controls when DynamoDB is in the data path.
Dynamodb-Specific Remediation in Actix — concrete code fixes
Remediation centers on replacing the wildcard with an allowlist of origins and enforcing user-level scoping for every DynamoDB operation. In Actix, configure CORS using the actix-cors crate so that Access-Control-Allow-Credentials is set only when origins are explicitly trusted. Combine this with per-request authorization in the handler to ensure each DynamoDB request is limited to the data belonging to the authenticated subject.
Below is a minimal, realistic example in Rust using the official AWS SDK for Rust. The Actix handler retrieves a user’s documents from DynamoDB, using the authenticated user’s ID to constrain the query. Note that the SDK client is constructed outside the handler and reused, and the partition key is derived from the identity, not from user-controlled input without validation.
use actix_web::{web, HttpResponse, Result};
use aws_sdk_dynamodb::Client;
use aws_sdk_dynamodb::types::AttributeValue;
async fn get_user_docs(
client: web::Data,
user_id: String, // already validated and sanitized
) -> Result {
let key = AttributeValue::S(user_id.clone());
let resp = client
.query()
.table_name("UserDocuments")
.key_condition_expression("user_id = :uid")
.expression_attribute_values(":uid", key)
.send()
.await
.map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string()))?;
let items: Vec<_> = resp.items().unwrap_or_default().to_vec();
Ok(HttpResponse::Ok().json(items))
}
On the CORS side, configure Actix to permit only known origins and avoid credentials leakage to untrusted sites:
use actix_cors::Cors;
use actix_web::App;
let cors = Cors::default()
.allowed_origin("https://app.example.com")
.allowed_origin("https://staging.example.com")
.allowed_methods(vec!["GET", "POST"])
.allowed_header(actix_web::http::header::AUTHORIZATION)
.allowed_header(actix_web::http::header::CONTENT_TYPE)
.max_age(3600);
App::new()
.wrap(cors)
.route("/documents", web::get().to(get_user_docs));
To further reduce risk, validate and normalize the Origin header on each request and include Vary: Origin in responses to prevent cache poisoning. For DynamoDB, prefer condition expressions that assert ownership (e.g., checking a user_id attribute matches the authenticated identity) rather than relying solely on the client-supplied key. Use IAM roles with least privilege so that the Actix service can only query the specific table and index required, and enable encryption at rest using KMS keys that are separate per environment.
middleBrick’s Pro plan supports continuous monitoring for such misconfigurations, scanning Actix endpoints on a schedule and flagging wildcard CORS alongside overprivileged IAM roles. If you integrate the GitHub Action, you can fail CI when a regression introduces a permissive CORS rule or when the scanned API surface reveals overly broad DynamoDB permissions. These capabilities complement the manual fixes shown here by providing automated guardrails as your service evolves.
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 |