HIGH server side template injectionfiberfirestore

Server Side Template Injection in Fiber with Firestore

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

Server Side Template Injection (SSTI) occurs when user-controlled data is inserted into a template function that causes arbitrary code execution on the server. In a Fiber application using Firestore, this typically arises when dynamic values from Firestore documents or request parameters are passed into template rendering without proper escaping or sandboxing. For example, if a handler retrieves a user document from Firestore and passes fields such as username or bio into a template context, an attacker who can influence document content (for example, via compromised admin tooling or exported data) may inject template directives.

Consider a route that renders a profile page using Firestore data:

import { render } from "https://deno.land/x/[email protected]/mod.ts";
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-app.js";
import { getFirestore, doc, getDoc } from "https://www.gcstatic.com/firebasejs/9.6.1/firebase-firestore.js";

const app = initializeApp({ /* config */ });
const db = getFirestore(app);

app.get("/profile/:uid", async (c) => {
  const uid = c.params.uid;
  const docSnap = await getDoc(doc(db, "users", uid));
  if (!docSnap.exists()) {
    return c.status(404).send("Not found");
  }
  const data = docSnap.data();
  // Potentially unsafe: data fields used directly in template
  return await render(`Hello #{data.displayName}`, data);
});

If data.displayName contains a template expression such as #{2*2} or a more dangerous payload compatible with the template engine (Pug, in this case), the server may evaluate it. The combination of Fiber’s lightweight routing, Firestore’s flexible document model, and dynamic template rendering increases risk when input validation and output escaping are omitted. Attackers can leverage this to read server-side files, execute commands, or probe internal services via SSRF if the template engine permits arbitrary function calls.

Additionally, because Firestore documents can contain nested maps and arrays, developers might recursively merge entire documents into the template context. This expands the attack surface: nested fields may include values that, when rendered by an unsafe template engine, trigger logic branches or filters that lead to code execution. MiddleBrick’s scans detect such patterns by correlating OpenAPI specifications with runtime behavior, noting places where Firestore document fields enter template rendering without sanitization.

Firestore-Specific Remediation in Fiber — concrete code fixes

To mitigate SSTI when using Fiber with Firestore, ensure that template rendering contexts are strictly controlled and that Firestore data is treated as untrusted input. Prefer explicit allowlists for which fields are passed to the template, and use escaping functions provided by the template engine. Below are concrete, secure patterns.

1. Restrict template context to selected safe fields

Instead of passing the entire Firestore document, explicitly pick safe scalar values:

import { render } from "https://deno.land/x/[email protected]/mod.ts";
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-app.js";
import { getFirestore, doc, getDoc } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js";

const app = initializeApp({ /* config */ });
const db = getFirestore(app);

app.get("/profile/:uid", async (c) => {
  const uid = c.params.uid;
  const docSnap = await getDoc(doc(db, "users", uid));
  if (!docSnap.exists()) {
    return c.status(404).send("Not found");
  }
  const data = docSnap.data();
  // Safe: only explicitly allowed fields are used
  const context = {
    displayName: data.displayName || "",
    email: data.email || "",
  };
  return await render("Hello #{displayName}", context);
});

2. Use template engine auto-escaping and avoid eval-like features

Configure your template engine to escape dynamic content. For Pug, ensure you use != only for trusted HTML and #{} for text (which auto-escapes). Avoid filters or includes that enable code execution. If you must include dynamic partials, validate the partial name against an allowlist.

3. Validate and sanitize Firestore data before rendering

Apply schema validation (for example with Zod) to Firestore documents and reject documents containing unexpected keys or executable patterns:

import { z } from "https://deno.land/x/[email protected]/mod.ts";

const UserProfileSchema = z.object({
  displayName: z.string().min(1).max(120),
  email: z.string().email(),
  // Do not include fields that templates should not use
});

type UserProfile = z.infer<typeof UserProfileSchema>;

app.get("/profile/:uid", async (c) => {
  const uid = c.params.uid;
  const docSnap = await getDoc(doc(db, "users", uid));
  if (!docSnap.exists()) {
    return c.status(404).send("Not found");
  }
  const parsed = UserProfileSchema.safeParse(docSnap.data());
  if (!parsed.success) {
    return c.status(400).send("Invalid document");
  }
  const safe = parsed.data;
  return await render("Hello #{displayName}", { displayName: safe.displayName });
});

4. Disable dangerous template features

If your template engine supports functions, filters, or includes, disable them or restrict them to a safe subset. For Pug, avoid custom filters and do not enable pretty or compileDebug in production-like environments when handling untrusted data.

By combining strict field selection, schema validation, and safe rendering defaults, you reduce the risk that Firestore data can influence template behavior in harmful ways. MiddleBrick’s checks highlight where Firestore document fields enter template contexts without these safeguards.

Frequently Asked Questions

Can a Firestore document structure itself cause template injection even if I sanitize inputs?
Yes. If your application recursively merges entire Firestore documents into the template context, nested fields may introduce values that trigger template logic. Always limit the context to explicitly allowed fields rather than the full document.
Does using the Firebase Admin SDK instead of client SDK reduce SSTI risk in Fiber?
Using Admin SDK changes authentication but does not change how you handle and render data. The risk depends on whether untrusted document fields are placed into templates. Apply the same allowlisting and escaping regardless of which SDK reads Firestore.