Cors Wildcard in Adonisjs with Dynamodb
Cors Wildcard in Adonisjs with Dynamodb — how this specific combination creates or exposes the vulnerability
When using AdonisJS with a DynamoDB-backed backend, configuring CORS with a wildcard (*) can unintentionally expose both data and administrative operations to any origin. In AdonisJS, CORS settings are typically defined in start/cors.js, where origins, methods, and headers are specified. A wildcard origin allows any website to make authenticated requests on behalf of a user, bypassing same-origin policy protections. If credentials or authorization tokens are included (e.g., via cookies or bearer tokens), the browser will send them, and the DynamoDB SDK in AdonisJS may execute privileged operations using the caller’s temporary credentials.
DynamoDB itself does not enforce origin-based restrictions; it relies on the application layer to validate identity and authorization. Therefore, if AdonisJS permits cross-origin requests indiscriminately, an attacker can craft a web page that calls your AdonisJS routes from a malicious domain. These routes might invoke DynamoDB operations such as getItem, query, or updateItem using the security context of the authenticated user. This can lead to unauthorized data access or modification, aligning with the BOLA/IDOR class of vulnerabilities when object-level permissions are not independently verified.
The risk is compounded when the AdonisJS application uses AWS SDKs directly with temporary credentials (e.g., via Cognito Identity Pools). A wildcard CORS policy may permit origins that should never be trusted, allowing malicious scripts to initiate signed DynamoDB requests. Even if the DynamoDB table has fine-grained IAM policies, the application’s role may still perform broader operations than intended for the end-user. Consequently, an improperly configured CORS wildcard transforms the API endpoint into an uncontrolled proxy for DynamoDB actions, amplifying exposure of sensitive data or destructive write capabilities.
Dynamodb-Specific Remediation in Adonisjs — concrete code fixes
To secure AdonisJS applications integrating with DynamoDB, CORS must be restricted to known origins and complemented with explicit authorization checks for each DynamoDB operation. Below are concrete remediation steps with code examples.
1. Restrict CORS origins
Replace wildcard origins with explicit domains in start/cors.js. This prevents untrusted websites from leveraging authenticated sessions.
const Env = use('Env')
const { cors } = require('@adonisjs/fold')
module.exports = {
origin: Env.get('CORS_ORIGIN', 'https://your-trusted-domain.com'),
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
allowHeaders: 'Origin, X-Requested-With, Content-Type, Accept, Authorization',
exposedHeaders: '',
credentials: true,
maxAge: 86400
}
2. Enforce origin validation middleware
Implement middleware to validate the Origin header against a strict allowlist before proceeding to DynamoDB calls.
// start/hooks.js
const allowedOrigins = ['https://your-trusted-domain.com', 'https://app.your-trusted-domain.com']
function validateOrigin(ctx) {
const origin = ctx.request.header().origin
if (allowedOrigins.includes(origin)) {
ctx.response.header('Access-Control-Allow-Origin', origin)
} else {
ctx.response.status(403).send({ error: 'CORS origin not allowed' })
}
}
module.exports = {
handle: validateOrigin
}
3. Apply DynamoDB authorization checks
Before executing any DynamoDB operation, verify that the requesting user has permission to access the specific resource. Use AWS SDK for JavaScript within AdonisJS controllers with scoped credentials.
// app/Controllers/Http/DynamoController.js
const { DynamoDBClient, GetItemCommand } = require('@aws-sdk/client-dynamodb')
const { fromCognitoIdentityPool } = require('@aws-sdk/credential-providers')
class DynamoController {
async getItem({ params, auth }) {
const userId = auth.user.id
const client = new DynamoDBClient({
region: 'us-east-1',
credentials: fromCognitoIdentityPool({
clientConfig: { region: 'us-east-1' },
identityPoolId: 'us-east-1:xxxx-xxxx-xxxx-xxxx'
})
})
const command = new GetItemCommand({
TableName: process.env.DYNAMO_TABLE,
Key: { id: { S: params.id } },
ConsistentRead: true
})
// Ensure the item belongs to the requesting user
const data = await client.send(command)
if (!data.Item || data.Item.userId.S !== userId) {
throw new Error('Unauthorized or item not found')
}
return data.Item
}
}
module.exports = DynamoController
4. Use resource-based policies and conditionals
Combine IAM policies with application-level checks. For example, configure a DynamoDB policy that allows dynamodb:GetItem only when the aws:PrincipalArn matches a specific Cognito identity pool authenticated via AdonisJS. Always validate ownership in code rather than relying solely on IAM conditions.
5. Disable credentials in CORS when unnecessary
If your frontend does not need to call AWS services directly, avoid sending credentials in CORS responses. Set credentials: false in CORS configuration to prevent cookies or authorization headers from being exposed to untrusted origins.
module.exports = {
origin: 'https://your-trusted-domain.com',
credentials: false
}
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 |