Token Leakage in Express with Dynamodb
Token Leakage in Express with Dynamodb — how this specific combination creates or exposes the vulnerability
Token leakage in an Express service that uses DynamoDB often occurs when authentication tokens (such as session cookies, JWTs, or API keys) are inadvertently exposed through API responses, logs, or error messages. Because DynamoDB is frequently used as a user data store, application code may retrieve user records and accidentally include sensitive fields or return full items to clients or downstream services.
One common pattern is an Express route that fetches a user object directly from DynamoDB and responds with the raw item. If the item contains a token field (e.g., refresh_token, api_key, or internal session identifier) and the response is not explicitly filtered, the token can be exposed to unauthorized clients or be logged by middleware. For example, a developer might write res.json(userItem) where userItem is the full DynamoDB record, including credential-like attributes.
Another vector arises from error handling. Unhandled exceptions or failed DynamoDB operations can cause stack traces or configuration details to be returned in HTTP responses. Tokens stored in environment variables or passed through context objects may appear in these messages. Additionally, misconfigured CORS or overly broad route parameters can allow token-bearing requests to be reflected or cached by intermediaries, compounding exposure risks.
The DynamoDB data model encourages storing many attributes in a single item, which increases the chance that sensitive tokens coexist with business data. Without strict attribute-level controls, scan findings may show that endpoints return items with excessive permissions or unredacted credential fields. This violates the principle of least privilege and can lead to token replay or elevation attacks.
Dynamodb-Specific Remediation in Express — concrete code fixes
Remediation focuses on ensuring tokens are never returned to clients and are handled safely within Express routes that interact with DynamoDB. Use projection to retrieve only necessary, non-sensitive attributes, and avoid passing raw DynamoDB items directly to responses.
Example: Safe DynamoDB GetItem with selective projection
const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB.DocumentClient();
app.get('/api/users/me', async (req, res) => {
const params = {
TableName: process.env.USERS_TABLE,
Key: { userId: req.user.sub },
// Explicitly project only safe, non-sensitive attributes
ProjectionExpression: 'userId, email, createdAt, profile'
};
try {
const data = await dynamo.get(params).promise();
if (!data.Item) {
return res.status(404).json({ message: 'User not found' });
}
// Respond with a filtered object that excludes tokens
const { userId, email, createdAt, profile } = data.Item;
res.json({ userId, email, createdAt, profile });
} catch (err) {
// Avoid exposing internal details in errors
console.error('Failed to fetch user:', err);
res.status(500).json({ message: 'Internal server error' });
}
});
Example: UpdateItem excluding token fields
app.patch('/api/users/me', async (req, res) => {
const updateParams = {
TableName: process.env.USERS_TABLE,
Key: { userId: req.user.sub },
UpdateExpression: 'set email = :email, profile = :profile',
ExpressionAttributeValues: {
':email': req.body.email,
':profile': req.body.profile
},
// Return only updated attributes and avoid tokens
ReturnValues: 'UPDATED_NEW'
};
try {
const data = await dynamo.update(updateParams).promise();
res.json({ updated: data.Attributes });
} catch (err) {
console.error('Update failed:', err);
res.status(500).json({ message: 'Internal server error' });
}
});
Secure token storage and handling practices
- Never store access or refresh tokens in DynamoDB attributes that may be returned to clients. If token storage is required, keep them in a separate secure vault or use short-lived session references.
- Apply attribute-level filters in your application logic and avoid generic item returns. Use
ProjectionExpressionto limit fields andExpressionAttributeNamesto safely reference attribute names. - Ensure error messages do not include stack traces or configuration values. Log sensitive details server-side only, and return generic error payloads to clients.
- Validate and sanitize all inputs to DynamoDB operations to prevent injection and malformed queries that could trigger verbose errors exposing tokens.