Summary
The staging Lambda Function URL is configured with allowed_origins = ["*"] (wildcard) in terraform/environments/aws/github-staging.tfvars while simultaneously setting Access-Control-Allow-Credentials: true via the cors { allow_credentials = true } block in the Lambda Terraform module (terraform/modules/compute/aws/lambda/main.tf). AWS Lambda Function URLs enforce CORS at the infrastructure layer before the Go application code runs: an Origin request header causes AWS to emit Access-Control-Allow-Origin: <reflected-origin> + Access-Control-Allow-Credentials: true in every response, regardless of what the Go handler sets. Dynamic probing confirms this: curl -H "Origin: https://attacker.io" https://33pz7pombdqwu3bdlxp4lqxyra0bsriy.lambda-url.us-east-1.on.aws/api/health returns both the configured origin AND the attacker's origin, each with Access-Control-Allow-Credentials: true.
Per the CORS specification, a browser will forward cookies/credentials to a cross-origin response only when Access-Control-Allow-Origin exactly matches the request's Origin AND Allow-Credentials is true. With a wildcard origin the spec says browsers must not expose credentials — but this deployment is not using the literal * response value; AWS is reflecting the inbound Origin verbatim, which turns it into a fully-trusted origin. Any website on the internet can therefore issue fetch("https://33pz7pombdqwu3bdlxp4lqxyra0bsriy.lambda-url.us-east-1.on.aws/api/users", {credentials:"include"}) and the browser will attach the victim's session token, bypassing the CSRF defence.
Risk: full account takeover if a CUDly admin can be tricked into visiting an attacker-controlled page while logged in. Staging is used by the CI pipeline and by engineers validating changes before production — the attack surface is real.
Location
terraform/environments/aws/github-staging.tfvars line 28: lambda_allowed_origins = ["*"]
terraform/modules/compute/aws/lambda/main.tf: cors { allow_credentials = true; allow_origins = var.allowed_origins }
Reproduction / PoC
# Confirm reflected Origin + Allow-Credentials: true
curl -s -i -X OPTIONS \
-H "Origin: https://attacker.io" \
-H "Access-Control-Request-Method: POST" \
"https://33pz7pombdqwu3bdlxp4lqxyra0bsriy.lambda-url.us-east-1.on.aws/api/auth/login" \
| grep -i "access-control"
# Returns:
# Access-Control-Allow-Origin: https://attacker.io ← reflected
# Access-Control-Allow-Credentials: true
# Cross-origin credential read PoC (browser):
# fetch("https://33pz7pombdqwu3bdlxp4lqxyra0bsriy.lambda-url.us-east-1.on.aws/api/auth/me",
# { credentials: "include" })
# .then(r => r.json())
# .then(console.log) // leaks full user profile
Suggested fix
- Replace
lambda_allowed_origins = ["*"] with the actual CloudFront/dashboard origin in every environment's tfvars. For staging this should be the staging CloudFront domain or the Lambda URL itself:
lambda_allowed_origins = ["https://33pz7pombdqwu3bdlxp4lqxyra0bsriy.lambda-url.us-east-1.on.aws"]
- Add a Terraform validation rule to the
allowed_origins variable that rejects ["*"] when allow_credentials = true:
validation {
condition = !(contains(var.allowed_origins, "*") && var.function_url_allow_credentials)
error_message = "Wildcard origin is incompatible with allow_credentials = true."
}
- Consider adding an integration test that hits the Lambda preflight with a random origin and asserts the response does NOT reflect it.
Severity rationale
CORS wildcard + credentials = any-origin cross-site request forgery without a CSRF token. While the Go application also enforces per-session CSRF tokens for state-changing requests, the reflected-origin response means a cross-origin browser fetch with credentials: "include" reads the session token from a prior JSON response (e.g., /api/auth/me) and can then supply its own CSRF header — full bypass. Priority P1 because staging is actively used by the CI pipeline and by engineers.
Summary
The staging Lambda Function URL is configured with
allowed_origins = ["*"](wildcard) interraform/environments/aws/github-staging.tfvarswhile simultaneously settingAccess-Control-Allow-Credentials: truevia thecors { allow_credentials = true }block in the Lambda Terraform module (terraform/modules/compute/aws/lambda/main.tf). AWS Lambda Function URLs enforce CORS at the infrastructure layer before the Go application code runs: anOriginrequest header causes AWS to emitAccess-Control-Allow-Origin: <reflected-origin>+Access-Control-Allow-Credentials: truein every response, regardless of what the Go handler sets. Dynamic probing confirms this:curl -H "Origin: https://attacker.io" https://33pz7pombdqwu3bdlxp4lqxyra0bsriy.lambda-url.us-east-1.on.aws/api/healthreturns both the configured origin AND the attacker's origin, each withAccess-Control-Allow-Credentials: true.Per the CORS specification, a browser will forward cookies/credentials to a cross-origin response only when
Access-Control-Allow-Originexactly matches the request'sOriginANDAllow-Credentialsistrue. With a wildcard origin the spec says browsers must not expose credentials — but this deployment is not using the literal*response value; AWS is reflecting the inboundOriginverbatim, which turns it into a fully-trusted origin. Any website on the internet can therefore issuefetch("https://33pz7pombdqwu3bdlxp4lqxyra0bsriy.lambda-url.us-east-1.on.aws/api/users", {credentials:"include"})and the browser will attach the victim's session token, bypassing the CSRF defence.Risk: full account takeover if a CUDly admin can be tricked into visiting an attacker-controlled page while logged in. Staging is used by the CI pipeline and by engineers validating changes before production — the attack surface is real.
Location
terraform/environments/aws/github-staging.tfvarsline 28:lambda_allowed_origins = ["*"]terraform/modules/compute/aws/lambda/main.tf:cors { allow_credentials = true; allow_origins = var.allowed_origins }Reproduction / PoC
Suggested fix
lambda_allowed_origins = ["*"]with the actual CloudFront/dashboard origin in every environment's tfvars. For staging this should be the staging CloudFront domain or the Lambda URL itself:allowed_originsvariable that rejects["*"]whenallow_credentials = true:Severity rationale
CORS wildcard + credentials = any-origin cross-site request forgery without a CSRF token. While the Go application also enforces per-session CSRF tokens for state-changing requests, the reflected-origin response means a cross-origin browser fetch with
credentials: "include"reads the session token from a prior JSON response (e.g.,/api/auth/me) and can then supply its own CSRF header — full bypass. Priority P1 because staging is actively used by the CI pipeline and by engineers.