HIGH server side template injectionhapifirestore

Server Side Template Injection in Hapi with Firestore

Server Side Template Injection in Hapi with Firestore — how this specific combination creates or exposes the vulnerability

Server Side Template Injection (SSTI) in a Hapi application that interacts with Firestore occurs when unvalidated user input is embedded into a template string or evaluated as part of dynamic query construction before being sent to Firestore. Hapi does not include a built-in templating engine for database operations, but developers commonly construct Firestore queries using JavaScript template literals or concatenation. If those values originate from request parameters, headers, or cookies without strict validation or sanitization, an attacker can inject expressions that alter query logic or leak data.

Consider a route that builds a Firestore query from a query parameter without sanitization:

// Unsafe: user input directly interpolated into a Firestore query
const buildUserQuery = (username) => `users/${username}`;

// Route definition
server.route({
  method: 'GET',
  path: '/users/{username}',
  handler: (request, h) => {
    const userRef = db.doc(buildUserQuery(request.params.username));
    return userRef.get().then(doc => doc.data());
  }
});

An attacker can supply a payload such as {username: 'attacker__where__1__1'} to manipulate the resulting document path, potentially accessing unintended documents if path traversal is feasible within the application’s data model. While Firestore itself does not evaluate templates, the injection occurs at the application layer where paths and field values are constructed, enabling information disclosure or bypass of intended access controls.

Another common pattern is dynamic field selection based on user input:

// Unsafe: field name taken directly from request
server.route({
  method: 'GET',
  path: '/users/profile',
  handler: async (request, h) => {
    const field = request.query.field;
    const snapshot = await db.collection('users').select(field).get();
    return snapshot.docs.map(d => d.data());
  }
});

If field is not validated, an attacker can inject field names such as __proto__ or use dot notation to traverse nested objects, potentially exposing sensitive fields or causing application errors. This becomes more impactful when combined with overly permissive Firestore rules, where the injected query may still return data the attacker should not see.

Because SSTI in this context is about query manipulation rather than template rendering, the risk often maps to Injection and Broken Access Control categories within OWASP API Top 10. The specific combination of Hapi’s flexible route definitions and Firestore’s document-path model creates opportunities for path traversal and field enumeration if input is not strictly constrained. middleBrick’s checks for Property Authorization and Input Validation would flag these patterns as high-risk, especially when unauthenticated endpoints expose query-building logic.

Firestore-Specific Remediation in Hapi — concrete code fixes

Remediation focuses on strict input validation, avoiding direct interpolation of user data into document paths or query selectors, and using Firestore’s built-in APIs safely. Always treat user input as opaque identifiers rather than structural components of paths.

Safe document path resolution: Use a whitelist or mapping to translate user identifiers to known document IDs, avoiding string concatenation entirely:

// Safe: map username to a known document ID via lookup
const userMap = {
  'alice': 'docIdAlice123',
  'bob':   'docIdBob456'
};

server.route({
  method: 'GET',
  path: '/users/{username}',
  handler: (request, h) => {
    const docId = userMap[request.params.username];
    if (!docId) {
      return h.response({ error: 'Invalid user' }).code(400);
    }
    const userRef = db.doc(`users/${docId}`);
    return userRef.get().then(doc => doc.exists ? doc.data() : null);
  }
});

Safe field selection: Validate field names against an allowlist instead of passing raw query parameters to Firestore:

// Safe: restrict field selection to known fields
const allowedFields = new Set(['displayName', 'email', 'photoURL']);

server.route({
  method: 'GET',
  path: '/users/profile',
  handler: async (request, h) => {
    const requested = request.query.fields ? request.query.fields.split(',') : ['displayName'];
    const validFields = requested.filter(f => allowedFields.has(f));
    if (validFields.length === 0) {
      return h.response({ error: 'No valid fields requested' }).code(400);
    }
    const snapshot = await db.collection('users').select(...validFields).get();
    return snapshot.docs.map(d => d.data());
  }
});

Using Firestore get with a document ID: When you must accept an identifier, enforce strong constraints and use Firestore’s doc with a predictable pattern rather than dynamic path building:

// Safe: constrained ID pattern
const idPattern = /^[a-zA-Z0-9_-]{1,50}$/;

server.route({
  method: 'GET',
  path: '/items/{itemId}',
  handler: (request, h) => {
    const itemId = request.params.itemId;
    if (!idPattern.test(itemId)) {
      return h.response({ error: 'Invalid item ID' }).code(400);
    }
    const itemRef = db.doc(`items/${itemId}`);
    return itemRef.get().then(doc => doc.data());
  }
});

These patterns ensure that user input never directly dictates path structure or query selectors, mitigating SSTI-like risks in the Hapi + Firestore stack. middleBrick’s scans will highlight the original unsafe patterns and map findings to relevant compliance frameworks such as OWASP API Top 10 and SOC2, while the Pro plan can help you enforce continuous monitoring to catch regressions early.

Frequently Asked Questions

Can SSTI in Hapi lead to unauthorized Firestore access?
Yes, if user-controlled input is concatenated into document paths or query selectors, attackers may read or infer data outside intended access boundaries. Always validate and map identifiers before building references.
Does middleBrick fix SSTI in Hapi applications?
middleBrick detects and reports insecure patterns such as unsafe interpolation and property authorization gaps. It provides remediation guidance, but does not automatically fix code.