HIGH request smugglingexpressfirestore

Request Smuggling in Express with Firestore

Request Smuggling in Express with Firestore — how this specific combination creates or exposes the vulnerability

Request smuggling arises when an Express application parses HTTP requests differently from the next hop (e.g., a proxy, load balancer, or API gateway) and passes the resulting interpretation to Firestore or uses Firestore data in unsafe ways. A common pattern is accepting a user-supplied URL or path parameter and using it to build a Firestore reference or query without strict validation. If the parameter contains encoded or malformed separators (e.g., mixed slashes and backslashes, double URL encoding, or header injection sequences), the Express route may interpret one request while the proxy interprets another, causing request splitting or merging. This can lead to authentication bypass, data leakage across users, or unexpected Firestore document access.

For example, an endpoint like /lookup that forwards a path to Firestore without canonicalization may allow a smuggled request to reach a different document path than intended. Consider a route that concatenates a user value into a Firestore document path:

app.get('/lookup', (req, res) => {
  const userPath = req.query.path; // e.g., users/uid/../other-uid/doc
  const docRef = admin.firestore().doc(userPath);
  docRef.get().then(doc => { /* ... */ });
});

If the proxy normalizes paths before routing but Express does not, a request for /lookup?path=users/alice/doc could be transformed into two separate requests at the proxy layer (one for /lookup, one smuggled for another path). Because Firestore rules operate on the document path provided by the server code, a path traversal can expose documents belonging to other users, violating BOLA/IDOR checks that middleBrick flags under the Property Authorization and BOLA/IDOR categories. middleBrick detects such patterns in unauthenticated scans and highlights the risk of data exposure when Firestore references are derived from untrusted input.

Additionally, smuggling can occur via header-based confusion when Express and the proxy handle headers like Transfer-Encoding or Content-Length differently. If an attacker injects a second request inside the body by manipulating these headers, the backend may process the second request and use Firestore with elevated or inferred context. MiddleBrick’s 12 parallel checks, including Authentication and BOLA/IDOR, are designed to surface these classes of issue in unauthenticated scans, emphasizing the need to validate and normalize all inputs before using them with Firestore.

Firestore-Specific Remediation in Express — concrete code fixes

Remediation focuses on strict input validation, canonical path construction, and avoiding direct concatenation of user-controlled values into Firestore document paths. Use parameterized paths and enforce allowlists for document IDs and collection names. Prefer Firestore’s built-in APIs to reference documents rather than building paths from strings.

1. Validate and canonicalize paths with a allowlist of allowed collections and a strict document ID pattern:

const ALLOWED_COLLECTIONS = new Set(['users', 'orgs', 'projects']);

function safeDocRef(collection, docId) {
  if (!/^[a-zA-Z0-9_-]{1,100}$/.test(docId)) {
    throw new Error('Invalid document ID');
  }
  if (!ALLOWED_COLLECTIONS.has(collection)) {
    throw new Error('Unauthorized collection');
  }
  return admin.firestore().collection(collection).doc(docId);
}

app.get('/doc', (req, res) => {
  try {
    const col = req.query.collection;
    const id = req.query.id;
    const docRef = safeDocRef(col, id);
    docRef.get().then(doc => {
      if (!doc.exists) return res.status(404).send('Not found');
      res.json(doc.data());
    });
  } catch (e) {
    res.status(400).send(e.message);
  }
});

2. Use Firestore’s doc and collection helpers with hardcoded segments where possible, and avoid dynamic path assembly from raw query parameters. If you must accept a document ID, normalize by trimming and rejecting path-like characters:

function normalizeDocId(input) {
  return input.replace(/[^a-zA-Z0-9_-]/g, '').substring(0, 100);
}

app.get('/userdoc', (req, res) => {
  const raw = req.query.id;
  const docId = normalizeDocId(raw);
  const docRef = admin.firestore().doc(`users/${docId}`);
  docRef.get().then(doc => {
    res.json(doc.data() || {});
  });
});

3. Enforce authentication and use Firestore security rules to complement server-side checks. Even when you sanitize inputs on the server, ensure rules deny read/write across user boundaries:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId}/documents/{document=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

4. For endpoints that proxy or forward requests, avoid passing user-controlled paths directly. Instead, map user identifiers to canonical references server-side:

app.get('/me/profile', async (req, res) => {
  if (!req.session || !req.session.uid) return res.status(401).send('Unauthorized');
  const docRef = admin.firestore().doc(`users/${req.session.uid}`);
  const doc = await docRef.get();
  res.json(doc.data());
});

These practices reduce the risk of request smuggling and BOLA/IDOR by ensuring Firestore references are predictable, constrained, and validated. middleBrick’s CLI can be used to scan endpoints like these and surface related findings under Property Authorization and Data Exposure, helping teams verify remediation.

Frequently Asked Questions

How can I test my Express endpoints for request smuggling without sending malicious traffic to production?
Use middleBrick’s CLI to scan your staging environment: middlebrick scan https://staging.example.com. The scan runs unauthenticated checks in 5–15 seconds and reports findings related to Authentication, BOLA/IDOR, and Data Exposure without requiring credentials.
Does Firestore’s security rules fully protect against request smuggling if the backend is vulnerable?
Security rules help enforce access per document path, but they do not prevent smuggling at the HTTP layer. If the backend constructs paths from untrusted input, smuggling can bypass rules. Always validate and canonicalize inputs server-side before referencing Firestore.