Data Exposure in Hapi with Dynamodb
Data Exposure in Hapi with Dynamodb — how this specific combination creates or exposes the vulnerability
When building Hapi serverless functions or endpoints that interact with DynamoDB, data exposure can occur through misconfigured access patterns, overly permissive IAM policies, and insufficient runtime validation. In this combination, the API surface often includes DynamoDB operations such as GetItem, Scan, or Query that may inadvertently return sensitive attributes or entire items due to projection expressions or missing attribute filters.
Hapi does not enforce data filtering by default; developers must explicitly shape responses. If a route handler passes raw DynamoDB output to the response, fields such as password_hash, api_key, or personal identifiable information (PII) can be exposed. A common pattern is using documentClient.get(params, callback) without trimming non-essential attributes, which can expose internal metadata or sensitive columns stored alongside business data.
Additionally, DynamoDB’s flexible schema can lead to inconsistent item shapes. If a route expects a subset of attributes but the item contains extra sensitive fields (for example, ssn or credit_card), missing schema validation in Hapi increases the risk of accidental exposure. Route-level validation using Joi in Hapi can mitigate this, but if validation rules are incomplete or loosely defined, sensitive data can pass through unchecked.
Another vector involves scan and query operations without server-side filtering. Developers sometimes use Scan to retrieve items and then apply client-side filtering, which is inefficient and risky because the scan returns entire items. An attacker who compromises the API endpoint may receive more data than intended, including credentials or tokens stored in DynamoDB item attributes.
Error handling also plays a role. Misconfigured error responses can leak stack traces or internal DynamoDB messages that reveal table or index names, helping an attacker refine exploitation. In a Hapi service, uncaught exceptions from DynamoDB may expose sensitive context if responses are not sanitized before reaching the client.
To reduce data exposure in Hapi with DynamoDB, adopt explicit attribute selection, enforce strict Joi validation, apply server-side filtering where possible, and sanitize errors. These practices limit the data returned and ensure that only intended attributes traverse the API layer, reducing the impact of misconfigurations or injection attempts covered by checks such as those in middleBrick’s Data Exposure category.
Dynamodb-Specific Remediation in Hapi — concrete code fixes
Remediation focuses on controlling what DynamoDB returns and ensuring Hapi responses contain only necessary data. Use projection expressions in GetItem and Query to limit attributes, and avoid Scan unless absolutely necessary. Validate and transform DynamoDB output before sending it to the client.
Example 1: Safe GetItem with projection and validation
const Hapi = require('@hapi/hapi');
const AWS = require('aws-sdk');
const Joi = require('joi');
const server = Hapi.server({ port: 4000 });
const docClient = new AWS.DynamoDB.DocumentClient();
const userSchema = Joi.object({
userId: Joi.string().required(),
email: Joi.string().email().required(),
name: Joi.string().required()
});
server.route({
method: 'GET',
path: '/users/{id}',
handler: async (request) => {
const params = {
TableName: process.env.USERS_TABLE,
Key: { userId: request.params.id },
// Limit returned attributes to reduce exposure
ProjectionExpression: 'userId, email, name'
};
const data = await docClient.get(params).promise();
if (!data.Item) {
throw Boom.notFound('User not found');
}
// Validate shape before returning
const { error, value } = userSchema.validate(data.Item);
if (error) {
throw Boom.badImplementation('Data validation failed');
}
return value;
}
});
Example 2: Query with server-side filtering and strict response shaping
server.route({
method: 'GET',
path: '/orders',
handler: async (request) => {
const params = {
TableName: 'Orders',
IndexName: 'UserIdIndex',
KeyConditionExpression: 'userId = :uid',
FilterExpression: 'orderStatus = :status',
ExpressionAttributeValues: {
':uid': request.query.userId,
':status': 'completed'
},
// Only fetch required fields
ProjectionExpression: 'orderId, total, createdAt'
};
const data = await docClient.query(params).promise();
// Shape response to exclude any reserved or sensitive metadata
return data.Items.map(item => ({
orderId: item.orderId,
total: item.total,
createdAt: item.createdAt
}));
}
});
Example 3: Avoid Scan; use Query with pagination and attribute selection
server.route({
method: 'GET',
path: '/search',
handler: async (request) => {
const params = {
TableName: 'Products',
IndexName: 'CategoryIndex',
KeyConditionExpression: 'category = :cat',
Select: 'SPECIFIC_ATTRIBUTES',
ProjectionExpression: 'productId, name, price',
Limit: 20
};
const data = await docClient.query(params).promise();
return data.Items;
}
});
IAM and configuration best practices
- Apply least-privilege IAM policies to the Lambda/role used by Hapi, allowing only needed DynamoDB actions on specific table resources.
- Enable DynamoDB encryption at rest and use VPC endpoints or AWS PrivateLink where applicable to reduce exposure in transit.
- Rotate credentials and use AWS SDK’s default credential provider chain; avoid embedding keys in code or environment variables without encryption.
- Log and monitor access patterns; use AWS CloudTrail and DynamoDB Streams cautiously, ensuring logs themselves do not expose sensitive fields.
These concrete fixes help ensure that Hapi services handling DynamoDB responses adhere to the principle of least disclosure, reducing data exposure risks while maintaining functionality.
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 |