Command Injection in Phoenix with Firestore
Command Injection in Phoenix with Firestore — how this specific combination creates or exposes the vulnerability
Command Injection occurs when an attacker can inject and execute arbitrary system commands through inputs that are insufficiently validated or sanitized. In a Phoenix application that interacts with Google Cloud Firestore, the risk typically arises at the integration boundary where user-controlled data is passed to backend commands or scripts that also interact with Firestore. Firestore itself is a managed NoSQL database and does not execute system commands, but a vulnerable Phoenix endpoint might construct shell commands dynamically using data stored in or retrieved from Firestore, or use Firestore document fields as parameters to external tooling.
Consider a scenario where a Firestore document stores a mapping of user identifiers to system usernames, and a Phoenix controller retrieves this mapping and passes it to a shell script via System.cmd/3. If the document value is trusted without validation, an attacker who can write to Firestore (e.g., via misconfigured rules or a compromised service account) could inject shell metacharacters such as ;, &, or backticks. When the Phoenix code uses this value in a command, the shell interprets the injected characters, leading to Command Injection. This is an architectural risk: Firestore becomes a source of attacker-controlled input rather than a purely data store.
Another pattern involves spawning processes to interact with gcloud or other CLI tooling based on Firestore metadata. For example, a background job might read a Firestore field containing a file path or bucket name and construct a gsutil command. Without strict input validation and shell escaping, special characters in the Firestore field can alter command semantics. Because Phoenix often runs on the BEAM VM, developers might assume immutability and safety, but external command execution remains dangerous when inputs originate from Firestore documents that are not strictly typed or validated.
Command Injection in this context does not imply Firestore has a vulnerability; it highlights how insecure integration practices can expose the system. The attack surface includes endpoints that retrieve data from Firestore and then use that data in shell commands, whether for reporting, file manipulation, or invoking third‑party utilities. OWASP API Top 10 A03:2023 (Injection) applies directly, and mappings to PCI‑DSS and SOC2 controls are relevant when sensitive operations are triggered via injected commands.
Firestore-Specific Remediation in Phoenix — concrete code fixes
Remediation focuses on preventing untrusted data from reaching the shell and enforcing strict input validation when Firestore fields participate in command construction. The safest approach is to avoid shell commands entirely and use native Google Cloud client libraries for operations on Firestore and related services. When shell interaction is unavoidable, use structured arguments and avoid the shell interpreter.
1. Use native Firestore client and avoid shell commands
Instead of retrieving a Firestore document and invoking a shell script to process data, use the Firestore client directly. This eliminates command injection risk and improves reliability.
defmodule MyApp.Repo do
import Ecto.Query, warn: false
# This is illustrative; in practice use the Google Cloud Firestore client.
# Example using a hypothetical Firestore client:
def get_user_record(user_id) do
# Direct Firestore read, no shell involved
Firestore.get_document("users/#{user_id}")
end
end
2. Validate and sanitize inputs before any command construction
If you must invoke system commands, validate Firestore-derived values against a strict allowlist and use raw arguments rather than a shell string.
defmodule MyApp.SafeExecutor do
@allowed_names ~w(report_export log_rotate backup_script)
def run_safe(firestore_doc_id) do
case Firestore.get_document("tasks/#{firestore_doc_id}") do
%{ "name" => name, "bucket" => bucket } when name in @allowed_names ->
# Use raw arguments; do not invoke a shell
System.cmd("gsutil", ["cp", "gs://#{sanitize_bucket(bucket)}/file.txt", "/tmp/file.txt"])
_ ->
{:error, :invalid_task}
end
end
defp sanitize_bucket(bucket) when is_binary(bucket) do
# Allow only lowercase alphanumeric and hyphens
if bucket =~ ~r/^[a-z0-9-]+$/, do: bucket, else: raise "Invalid bucket name"
end
end
3. Use :port and avoid shell interpolation
When using System.cmd/3, pass the executable and arguments as a list. Do not concatenate strings to form shell commands.
# Good: arguments are passed as a list, no shell interpolation
System.cmd("curl", ["--silent", "--output", "/dev/null", "https://health.example.com"])
# Avoid: building a command string that will be interpreted by the shell
cmd = "curl --silent --output /dev/null https://#{firestore_host}"
System.cmd("sh", ["-c", cmd]) # Unsafe if firestore_host originates from Firestore
4. Apply least-privilege service accounts
Ensure the service account used by Phoenix has minimal permissions in Firestore and Cloud Storage. This limits the impact if an injection is possible. Combine with VPC Service Controls and restricted IAM roles to reduce lateral movement.
5. Secure Firestore rules and monitor writes
Lock down Firestore rules to prevent unauthorized writes that could seed malicious values used by Phoenix. Use the Firebase Emulator Suite to test rules thoroughly and monitor write attempts via Cloud Logging.
6. Use CI/CD checks with middleBrick
Integrate scanning into your development workflow. Use the GitHub Action to fail builds if security scores drop and run continuous monitoring with the Pro plan to detect regressions. The MCP Server enables scanning APIs directly from your IDE, catching risky patterns before code reaches production.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |