HIGH api key exposurehapidynamodb

Api Key Exposure in Hapi with Dynamodb

Api Key Exposure in Hapi with Dynamodb — how this specific combination creates or exposes the vulnerability

Hapi is a rich framework for building HTTP services in Node.js. When you store sensitive configuration such as API keys in DynamoDB and retrieve them at runtime in a Hapi application, the exposure risk depends on how you access and transmit those values. If your Hapi server reads an API key from a DynamoDB table and includes it in logs, error responses, or unencrypted internal communications, the key can be unintentionally exposed to unauthorized parties.

Consider a typical setup where a Hapi service queries DynamoDB for a row that contains an api_key attribute. If the response is mishandled—for example, returned directly to the client or logged at an unsafe log level—an attacker who can observe logs or error payloads may recover the key. DynamoDB itself does not cause the exposure; the exposure arises from how the Hapi application uses the retrieved value. Common patterns that increase risk include missing input validation on identifiers used to fetch the item, verbose error messages that echo the retrieved item, and missing runtime controls that prevent excessive logging of sensitive fields.

Another vector specific to this combination is misconfigured SDK clients. If your Hapi service uses the AWS SDK for JavaScript to interact with DynamoDB, ensure that the SDK is configured with the least privilege permissions required for the task. Overly permissive credentials attached to the SDK increase the impact of any accidental exposure. In addition, if the API key is used to sign or authenticate outbound requests, ensure that the key is never concatenated into URLs or query strings that could be captured by proxies or logs.

Real attack patterns include log injection and SSRF-assisted data exfiltration. For instance, an SSRF vulnerability in your Hapi service could allow an attacker to force the server to fetch its own DynamoDB item, including the key, and then exfiltrate it via a callback URL. Even without SSRF, improperly handled CORS or missing authentication on certain Hapi routes can allow a browser-based attacker to trigger requests that cause the server to return sensitive configuration values in JSON responses.

To detect this class of issue, scans check whether items retrieved from DynamoDB containing keys are ever returned directly to clients or logged in plaintext. They also verify that the Hapi server does not leak metadata that could facilitate enumeration of DynamoDB items, such as verbose error objects that disclose table structure or attribute names.

Dynamodb-Specific Remediation in Hapi — concrete code fixes

Remediation focuses on handling sensitive values retrieved from DynamoDB with care: avoid returning them to clients, minimize logging, and enforce strict access controls. Below are concrete, realistic code examples that demonstrate secure patterns for a Hapi service that reads an API key from DynamoDB.

First, structure your DynamoDB fetch to retrieve only the attributes you need and never forward the raw item to the client:

// server.js
const Hapi = require('@hapi/hapi');
const { DynamoDBClient, GetItemCommand } = require('@aws-sdk/client-dynamodb');

const client = new DynamoDBClient({ region: 'us-east-1' });

const getItem = async (tableName, id) => {
  const command = new GetItemCommand({
    TableName: tableName,
    Key: { id: { S: id } },
    // Explicitly project only non-sensitive attributes if possible
    ProjectionExpression: 'id,public_flag'
  });
  const { Item } = await client.send(command);
  return Item;
};

const init = async () => {
  const server = Hapi.server({ port: 4000, host: 'localhost' });

  server.route({
    method: 'GET',
    path: '/public-config/{id}',
    handler: async (request, h) => {
      const item = await getItem('MyTable', request.params.id);
      if (!item) {
        return h.response({ error: 'not found' }).code(404);
      }
      // Return only safe, non-sensitive data
      return { id: item.id.S, publicFlag: item.public_flag?.BOOL };
    }
  });

  server.route({
    method: 'POST',
    path: '/use-key',
    handler: async (request, h) => {
      const item = await getItem('SecretsTable', 'api-key-id');
      const apiKey = item?.api_key?.S;
      if (!apiKey) {
        return h.response({ error: 'configuration missing' }).code(500);
      }
      // Use the key securely, e.g., pass it as a header or env variable to downstream services
      // Do NOT log apiKey, and do NOT attach it to response objects
      return h.response({ status: 'ok' }).code(200);
    }
  });

  await server.start();
  console.log('Server running on %s', server.info.uri);
};

init().catch(err => {
  console.error('Startup error:', err);
  process.exit(1);
});

This example shows how to limit the data projected from DynamoDB and ensure sensitive fields like api_key are not included in responses. Even when the key is needed for internal operations, it should remain in memory only for the duration of the request and never be serialized into logs or HTTP outputs.

Second, enforce schema validation and strict error handling to prevent verbose messages that might expose DynamoDB structure:

// route-options.js
exports.plugin = {
  name: 'error-handler',
  register: function (server) {
    server.ext('onPreResponse', (request, h) => {
      const response = request.response;
      if (response.isBoom) {
        // Replace detailed errors with generic messages
        return h.response({ error: 'bad request' }).code(response.output.statusCode);
      }
      return h.continue;
    });
  }
};

// Usage in server registration
const Hapi = require('@hapi/hapi');
const errorHandler = require('./route-options');

const server = Hapi.server({ port: 4000 });
server.register(errorHandler);
// ... routes as above

By using selective attribute projection and robust error handling, you reduce the likelihood that DynamoDB-stored API keys are inadvertently surfaced through the Hapi application. Combine these practices with runtime scans that check for exposure patterns to maintain a strong security posture.

Frequently Asked Questions

Can DynamoDB encryption at rest alone prevent API key exposure in Hapi?
No. Encryption at rest protects data stored in DynamoDB, but exposure in Hapi typically occurs when the application retrieves and uses the key. Secure handling, minimal logging, and strict response controls are still required.
Does scanning detect API key exposure in Hapi applications that fetch keys from DynamoDB?
Yes. Scans check whether items from DynamoDB containing sensitive values are returned to clients or logged in plaintext, and they flag verbose errors that could disclose table or attribute details.