HIGH api key exposurerestifymongodb

Api Key Exposure in Restify with Mongodb

Api Key Exposure in Restify with Mongodb — how this specific combination creates or exposes the vulnerability

When a Restify service uses environment variables or configuration files to store database credentials and API keys, and those values are inadvertently included in HTTP responses, logs, or error messages, the combination of Restify and Mongodb can expose sensitive material. This typically occurs when developers accidentally serialize request or response objects that contain connection strings or keys, or when debugging helpers are left enabled in production.

Restify’s built-in behaviors—such as detailed error stacks or custom serialization—can surface database connection details if responses include Mongodb document fields that should have been redacted. For example, returning a Mongodb document directly from a route handler may include fields like password, token, or internal identifiers that should remain server-side. If the application embeds API keys into Mongodb documents for downstream services and those documents are returned to clients, the keys are exposed.

Additionally, misconfigured CORS or overly broad route permissions in Restify can allow unauthenticated or insufficiently authenticated callers to trigger endpoints that query Mongodb. An attacker leveraging this might coax verbose errors that reveal stack traces containing file paths or require statements, indirectly exposing where keys are loaded. Inconsistent use of projection in Mongodb queries can also cause sensitive fields to be included when only a subset of data is intended for the client.

The risk is compounded when API keys are stored in the same database as application data without encryption at rest or strict access controls. middleBrick scans this attack surface by checking whether endpoints return sensitive headers or fields, and whether authentication is consistently enforced across routes that interact with Mongodb. Findings often highlight missing property-based authorization and unsafe consumption patterns where sensitive data could leak through unvalidated output.

In practice, this manifests as endpoints that return full Mongodb documents containing connection strings, or logs that print resolved keys during error handling. Without runtime checks, such leakage can persist across deployments, especially when configuration templates are reused across services.

Mongodb-Specific Remediation in Restify — concrete code fixes

To mitigate exposure, ensure Mongodb queries explicitly exclude sensitive fields and that Restify responses are sanitized before leaving the server. Use projection to return only necessary fields, and avoid passing full Mongodb documents directly to clients.

Example 1: Safe query with projection

const restify = require('restify');
const { MongoClient } = require('mongodb');

const server = restify.createServer();
server.use(restify.plugins.bodyParser());

server.get('/users/me', async (req, res, next) => {
  const client = new MongoClient(process.env.MONGODB_URI);
  try {
    await client.connect();
    const db = client.db('myapp');
    const users = db.collection('users');

    // Explicitly exclude sensitive fields
    const user = await users.findOne(
      { email: req.query.email },
      { projection: { email: 1, name: 1, role: 1, _id: 1 } } // excludes apiKey, password, tokens
    );

    if (!user) {
      return next(new restify.NotFoundError('User not found'));
    }
    res.send(user);
  } catch (err) {
    // Avoid exposing internal details
    req.log.error('User fetch failed');
    return next(new restify.InternalServerError('Request failed'));
  } finally {
    await client.close();
  }
  return next();
});

server.listen(8080, () => console.log('Listening'));

Example 2: Redacting sensitive keys before logging or response

const sanitize = (obj) => {
  if (!obj || typeof obj !== 'object') return obj;
  const clone = Array.isArray(obj) ? [...obj] : { ...obj };
  if (clone.apiKey) clone.apiKey = 'REDACTED';
  if (clone.password) clone.password = 'REDACTED';
  if (clone.token) clone.token = 'REDACTED';
  return clone;
};

server.use((req, res, next) => {
  res.on('header', () => {
    // ensure headers do not contain sensitive values
  });
  return next();
});

server.get('/config', async (req, res, next) => {
  const client = new MongoClient(process.env.MONGODB_URI);
  try {
    await client.connect();
    const db = client.db('myapp');
    const config = await db.collection('configs').findOne({ scope: 'public' });
    res.send(sanitize(config));
  } catch (err) {
    req.log.error('Config fetch failed');
    res.send(500, { error: 'Internal error' });
  } finally {
    await client.close();
  }
  return next();
});

Example 3: Enforcing authentication and role checks before Mongodb access

server.pre((req, res, next) => {
  if (!req.headers.authorization) {
    return next(new restify.UnauthorizedError('Missing authorization'));
  }
  // Validate token and extract user role
  const role = extractRoleFromToken(req.headers.authorization);
  req.context.userRole = role;
  return next();
});

server.get('/secrets/:id', async (req, res, next) => {
  if (req.context.userRole !== 'admin') {
    return next(new restify.ForbiddenError('Insufficient permissions'));
  }
  const client = new MongoClient(process.env.MONGODB_URI);
  try {
    await client.connect();
    const secrets = db.collection('secrets');
    const secret = await secrets.findOne({ _id: req.params.id }, {
      projection: { value: 1, _id: 1 } // never include raw apiKey here
    });
    res.send(secret);
  } catch (err) {
    req.log.error('Secret fetch failed');
    return next(new restify.InternalServerError('Request failed'));
  } finally {
    await client.close();
  }
  return next();
});

General practices

  • Use environment variables for connection strings and keys, and avoid storing them in Mongodb documents served to clients.
  • Apply the principle of least privilege to Mongodb user roles used by Restify; avoid broad read/write access for endpoints that only need to serve public data.
  • Validate and sanitize all inputs to prevent injection that could lead to unauthorized data exposure.
  • Ensure error handlers do not return stack traces or internal paths that hint at file system layout or configuration details.
  • Leverage middleBrick’s checks for authentication, property authorization, and unsafe consumption to catch residual risks before deployment.

Frequently Asked Questions

How can I verify that my Restify endpoints are not leaking Mongodb documents with embedded API keys?
Use middleBrick to scan your endpoints; it checks for unintended data exposure by comparing response fields against expected schemas and flags documents that contain keys such as apiKey or token. Combine this with explicit projection in your Mongodb queries to ensure only intended fields are returned.
Is it safe to log full Mongodb documents for debugging if authentication is enforced on the endpoint?
No. Even with enforced authentication, logging full documents can expose sensitive fields like passwords or API keys in log stores. Sanitize documents before logging by redacting sensitive keys and prefer structured, minimal logging focused on operational metadata.