HIGH command injectionadonisjsfirestore

Command Injection in Adonisjs with Firestore

Command Injection in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability

Command Injection occurs when untrusted input is passed to a system shell or to an internal API that executes commands. In AdonisJS, this risk arises when user-controlled data is used to construct shell commands, for example via child process utilities, before those commands interact with Firestore tooling or related system utilities. Although Firestore itself is a managed NoSQL database and does not execute shell commands, a vulnerable AdonisJS controller or service might build a command that includes Firestore gcloud CLI calls, Firestore imports/exports, or custom scripts that include user input. If that input is not strictly validated and sanitized, an attacker can inject additional shell instructions, leading to arbitrary command execution on the host.

Consider an AdonisJS route that accepts a document ID to fetch a Firestore document and then passes that ID to a shell-based helper for logging or archival purposes. If the code uses unsanitized user input in a command such as gcloud firestore documents export gs://bucket --collection-ids=users and appends the ID in an unsafe way, an attacker could break argument boundaries and append extra shell commands. This is especially relevant when the application runs on a platform where gcloud or other Firestore utilities are installed and reachable from Node via exec or spawn. The risk is not in Firestore itself but in how AdonisJS strings together commands and user data, bypassing proper escaping or using dangerous APIs like eval or shell interpolation.

AdonisJS encourages using environment-based configuration and service classes to keep logic out of routes. However, if developers introduce ad hoc command building—such as spawning a child process to run firestore-backup.sh with concatenated IDs or query parameters—each unchecked input becomes a potential injection vector. Common patterns include using child_process.exec with template literals that embed identifiers directly, or passing raw request payloads to scripts that interact with Firestore exports/imports. Attack patterns mirror classic OS Command Injection (CWE-78), where injected payloads like id; cat /etc/passwd or id && rm -rf /tmp/* can alter intended behavior and escalate impact. MiddleBrick’s checks for BOLA/IDOR, Input Validation, and Unsafe Consumption help surface these issues by correlating endpoint behavior with known risky patterns.

Firestore-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on strict input validation, avoiding shell command construction, and using Firestore SDK methods directly instead of invoking CLI tools from within request handling paths. When you must interact with Firestore utilities, perform these actions outside of AdonisJS request lifecycle, using secure, pre-approved scripts with hardcoded parameters, and trigger them via authenticated job queues rather than direct user input.

First, prefer the official Firestore Node.js SDK in your controllers. For example, fetching a document by ID should use the SDK rather than shelling out to gcloud:

import { DateTime } from 'luxon'
import { Firestore } from '@google-cloud/firestore'

const firestore = new Firestore()

async function getDocumentById(collectionName, documentId) {
  // Validate documentId to allow only safe characters (alphanumeric, dash, underscore)
  if (!/^[a-zA-Z0-9\-_]+$/.test(documentId)) {
    throw new Error('Invalid document ID')
  }
  const docRef = firestore.collection(collectionName).doc(documentId)
  const doc = await docRef.get()
  if (!doc.exists) {
    throw new Error('Document not found')
  }
  return doc.data()
}

Second, if you need export or import operations, define strict, parameterized scripts that do not accept raw user input for collection or bucket names. Instead, use environment-controlled configuration and trigger them via authenticated job runners. For example, a script firestore-export.js might read allowed collections from a config file and write to a predefined bucket path:

// firestore-export.js — run as a controlled job, not per request
const { Firestore } = require('@google-cloud/firestore')
const { Storage } = require('@google-cloud/storage')
const firestore = new Firestore()
const storage = new Storage()

async function exportCollections() {
  const collections = process.env.ALLOWED_EXPORT_COLLECTIONS.split(',')
  const timestamp = DateTime.now().toFormat('yyyyMMdd_HHmmss')
  const bucketName = process.env.FIRESTORE_EXPORT_BUCKET
  const uri = `gs://${bucketName}/export-${timestamp}`

  const request = {
    outputUriPrefix: uri,
    collectionIds: collections,
  }
  const [operation] = await firestore.exportDocuments(request)
  const [response] = await operation.promise()
  console.log('Export started:', response.name)
}
exportCollections().catch(console.error)

Third, if you must log or audit IDs as part of operational tooling, sanitize and encode them before using in any logging or auxiliary commands. Never build shell commands using concatenation with user input; use structured logging and predefined binaries with argument arrays to avoid injection risks. For CI/CD or deployment pipelines, integrate middleBrick’s GitHub Action to enforce security gates and scan staging APIs before deploy, ensuring that any remaining risky patterns are caught early.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Can Firestore itself be exploited via command injection in AdonisJS?
Firestore is a managed service and does not execute shell commands. Command Injection risk comes from how AdonisJS constructs shell commands that may include Firestore utilities; the database itself is not the injection target.
What is the safest way to handle document IDs in AdonisJS when working with Firestore?
Validate IDs with a strict allowlist (e.g., alphanumeric, dash, underscore), use the Firestore Node.js SDK directly, avoid building shell commands with user input, and perform export/import operations via controlled jobs with environment-defined parameters.