Cors Wildcard in Actix with Basic Auth
Cors Wildcard in Actix with Basic Auth — how this specific combination creates or exposes the vulnerability
A CORS wildcard (Access-Control-Allow-Origin: *) combined with HTTP Basic Authentication in an Actix web application can unintentionally expose authenticated endpoints to any origin. When credentials are required (e.g., browser-based Basic Auth), browsers enforce that the server must not respond with a wildcard; the response must specify an explicit origin. If an Actix service uses a wildcard while also requiring Basic Auth, a browser will block the frontend JavaScript from reading the response even though the request may be sent, leading to inconsistent behavior and potential information leakage through error messages or preflight responses.
During a black-box scan, middleBrick checks whether CORS responses include a wildcard while authentication mechanisms like Basic Auth are in use. If both conditions are present, the scan flags a finding because the wildcard can cause browsers to reject authenticated responses, which may result in applications handling errors insecurely or exposing stack traces. Attackers can probe these misconfigurations using preflight requests and observe discrepancies between allowed origins and authentication requirements, potentially identifying endpoints that accept credentials from unexpected sources.
In Actix, CORS is typically configured using the actix-cors crate. A common insecure setup might set Access-Control-Allow-Origin: * while also enabling Basic Auth via middleware or guards. Because Basic Auth relies on the browser sending an Authorization header, the combination creates a scenario where the server signals that any origin is acceptable, but browsers treat the response as opaque if credentials are involved. This mismatch can be leveraged in SSRF or client-side attacks where an attacker tricks a victim’s browser into making authenticated requests and reading error details, aiding further exploitation.
middleBrick’s 12 checks run in parallel and include Input Validation and Authentication tests that can detect mismatched CORS and auth configurations. For example, if an endpoint responds with a wildcard CORS header while also rejecting unauthenticated requests, the scanner records this as a potential bypass vector. The report highlights the specific endpoint, the observed headers, and provides remediation steps. Developers should ensure that when Basic Auth or any credentialed authentication is used, CORS origins are explicitly set to trusted domains rather than a wildcard.
Basic Auth-Specific Remediation in Actix — concrete code fixes
To remediate the CORS wildcard issue with Basic Auth in Actix, explicitly set allowed origins and ensure that credentials are only accepted from trusted sources. Below are two concrete Actix examples: one insecure configuration that demonstrates the problem, and one corrected configuration that pairs explicit CORS origins with Basic Auth middleware.
Insecure example (vulnerable to wildcard + Basic Auth mismatch):
use actix_web::{web, App, HttpServer, Responder};
use actix_cors::Cors;
async fn index() -> impl Responder {
"public endpoint"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
let cors = Cors::permissive(); // allows wildcard
App::new()
.wrap(cors)
.route("/", web::get().to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Corrected example (explicit origins with Basic Auth):
use actix_web::{web, App, HttpServer, Responder, HttpRequest};
use actix_cors::Cors;
use actix_http::header;
async fn index() -> impl Responder {
"protected endpoint"
}
fn basic_auth_middleware(req: &HttpRequest, payload: &mut actix_web::dev::Payload) -> Result<(), actix_web::Error> {
// Simple Basic Auth check (in production, use a robust extractor or guard)
let auth = req.headers().get(header::AUTHORIZATION);
match auth {
Some(value) if value.to_str().map(|s| s.starts_with("Basic ")).unwrap_or(false) => Ok(()),
_ => Err(actix_web::error::ErrorUnauthorized("Missing or invalid auth")),
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let cors = Cors::default()
.allowed_origin("https://trusted.example.com")
.allowed_methods(vec!["GET", "POST"])
.allowed_header(header::AUTHORIZATION)
.allowed_header(header::CONTENT_TYPE)
.max_age(3600);
HttpServer::new(move || {
App::new()
.wrap(cors.clone())
.route("/secure", web::get().to(index).wrap_fn(|req, srv| {
basic_auth_middleware(&req, srv.request().payload_mut()).map_err(|e| e.into())
}))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
In the corrected setup, allowed_origin is set explicitly to a trusted domain, avoiding wildcard usage. The Basic Auth check is implemented as a lightweight middleware wrapper, ensuring that only requests with valid credentials reach the handler. middleBrick’s scan can verify that the returned Access-Control-Allow-Origin header is not a wildcard when authentication is required, and it can confirm that preflight requests correctly reflect the strict origin policy.
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 |