HIGH injection flawskoamongodb

Injection Flaws in Koa with Mongodb

Injection Flaws in Koa with Mongodb — how this specific combination creates or exposes the vulnerability

Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query. In a Koa application using Mongodb, the risk centers on how user-controlled input is incorporated into database operations. If input is concatenated into query objects or aggregation pipelines without strict validation, an attacker can manipulate the structure of the query to change its intent.

Consider a typical Koa route that builds a find query from request query parameters:

// Risky: directly using query params in the query object
const { name, status } = ctx.request.query;
const filter = {};
if (name) filter.name = name;
if (status) filter.status = status;
const users = await db.collection('users').find(filter).toArray();

While this appears safe because the code only copies known keys, an attacker can still supply unexpected keys (e.g., $where, $expr, or $ne) if the code merges or extends the filter object elsewhere. For example, if a developer builds queries by spreading user input into a base object:

const base = { deleted: { $ne: true } };
const combined = { ...base, ...ctx.request.query };
const results = await db.collection('items').find(combined).toArray();

An attacker can provide { "$ne": "" } as a query parameter, which may override intended constraints depending on merging logic, leading to unintended data exposure. A more severe pattern occurs when developers attempt to perform server-side search by embedding user input directly into the query language syntax:

// Dangerous: constructing a JSON string from user input
const search = ctx.request.query.q || '';
const query = '{ "name": /' + search + '/i }';
// eslint-disable-next-line no-eval
const filter = eval('(' + query + ')');
const results = await db.collection('products').find(filter).toArray();

Using eval or similar mechanisms to build query objects enables injection by allowing attackers to terminate the intended structure and append arbitrary operators. Even without eval, concatenating strings to form JSON or BSON can allow injection if the parsing is not strict.

Another vulnerable pattern involves the use of aggregation pipelines where user input is inserted into stage objects without sanitization:

const pipeline = [
  { $match: { status: ctx.request.query.status || 'active' } },
  { $group: { _id: '$role', count: { $sum: 1 } } }
];
// If an attacker can control a stage key, they might inject $where or $function
const results = await db.collection('logs').aggregate(pipeline).toArray();

Although Mongodb’s driver will reject some server-side expressions in certain contexts, others like $where or custom extensions may be processed if they reach the server. The combination of Koa’s flexible request handling and Mongodb’s expressive query language increases the impact of injection when input validation is incomplete.

Mongodb-Specific Remediation in Koa — concrete code fixes

Defending against injection in a Koa + Mongodb stack requires strict input validation, type checking, and avoiding dynamic construction of query objects from raw user input. Prefer using typed query structures and avoid eval or string-to-code parsing entirely.

1. Use explicit field allowlisting and schema validation

Define which fields are expected and validate types before constructing queries:

const validStatuses = ['active', 'inactive', 'pending'];
const name = typeof ctx.request.query.name === 'string' ? ctx.request.query.name : '';
const status = validStatuses.includes(ctx.request.query.status) ? ctx.request.query.status : 'active';

const filter = {
  name: { $regex: name, $options: 'i' },
  status: status,
  deleted: { $ne: true }
};
const users = await db.collection('users').find(filter).toArray();

This ensures only known operators and values are used and prevents unexpected keys from being injected.

2. Avoid string concatenation when building queries or pipelines

Never build JSON or query expressions by concatenating strings. Instead, construct objects programmatically:

// Safe: building filter as a plain object
const filter = {
  deleted: { $ne: true },
  name: { $exists: true, $type: 'string' }
};
if (ctx.request.query.minLength) {
  const min = parseInt(ctx.request.query.minLength, 10);
  if (!Number.isNaN(min)) {
    filter.name.$minLength = min;
  }
}
const results = await db.collection('items').find(filter).toArray();

For aggregation, define stages as static objects and only inject validated, typed values:

const matchStage = { $match: { status: 'active' } };
if (ctx.request.query.role) {
  matchStage.$match.role = ctx.request.query.role;
}
const pipeline = [
  matchStage,
  { $group: { _id: '$role', count: { $sum: 1 } } }
];
const results = await db.collection('logs').aggregate(pipeline).toArray();

3. Use Mongodb schema validation where possible

Define JSON Schema rules at the collection level to reject malformed documents at the server:

await db.command({
  collMod: 'users',
  validator: {
    $jsonSchema: {
      bsonType: 'object',
      required: ['name', 'email'],
      properties: {
        name: { bsonType: 'string' },
        email: { bsonType: 'string', pattern: '^.+@.+$' },
        status: { enum: ['active', 'inactive'] }
      }
    }
  }
});

This adds a server-side layer of enforcement, complementing client-side checks in Koa.

4. Apply principle of least privilege to the database user

Ensure the Mongodb user used by Koa has only the necessary permissions (e.g., read for queries, write for specific collections) to limit the impact of any successful injection attempt.

5. Log and monitor suspicious inputs

Log unexpected query keys or operators and set alerts for patterns commonly associated with injection attempts:

const suspiciousKeys = ['$where', '$eval', '$function', '$near', '$maxDistance'];
for (const key of suspiciousKeys) {
  if (Object.prototype.hasOwnProperty.call(ctx.request.query, key)) {
    ctx.logger.warn('Potential injection indicator', { key, value: ctx.request.query[key] });
  }
}

These practices help ensure that even if an attacker finds a vector, the operational impact is contained.

Frequently Asked Questions

Does middleBrick detect injection flaws in Koa APIs using Mongodb?
Yes, middleBrick runs checks for injection-related patterns, including improper query construction and unsafe use of operators. Findings include severity, context, and remediation guidance.
Can I integrate middleBrick into my CI/CD to block deployments with risky Mongodb usage in Koa?
With the Pro plan, you can use the GitHub Action to add API security checks to your CI/CD pipeline and fail builds if risk scores exceed your configured threshold.