Skip to content

Projects.json check/test commands passed to /bin/sh without shell metacharacter protection #79

@ooloth

Description

@ooloth

Current state

loops/common/projects.py runs check, install, and test commands from projects.json via:

subprocess.run(["/bin/sh", "-c", "$_CMD"], env={..., "_CMD": cmd})

where cmd comes from project.get("check"), project.get("install"), and project.get("test").

The shell command is literally $_CMD — the shell substitutes the variable and then further parses the result as a shell expression. A projects.json entry whose check value contains shell metacharacters (;, &&, ||, $(...)) causes those metacharacters to be interpreted by /bin/sh, enabling arbitrary command execution on the agent's host. A supply-chain push to the repository that adds a malicious command to projects.json would execute on every subsequent agent run targeting that project.

Ideal state

  • Commands from projects.json are executed without shell interpretation — passed as a list of arguments to a known interpreter (e.g. shlex.split(cmd) passed directly as the args list, without shell=True or /bin/sh -c).
  • Shell metacharacters in a command string from projects.json are treated as literals, not executable syntax.
  • Alternatively, projects.json commands are validated against an allowlist or a format constraint (e.g. must match a regex that excludes ;, &&, ||, $(, and backticks) before execution.

Starting points

  • loops/common/projects.py lines 57–58, 72–73, 92–93 — the subprocess.run(["/bin/sh", "-c", "$_CMD"], ...) calls for run_command, run_tests, and their variants

QA plan

  1. Add a project to projects.json with "check": "echo safe; touch /tmp/agency-injection-test". Run the scan. Check for /tmp/agency-injection-test — expect it does not exist.
  2. Verify a normal check command (e.g. "uv run --frozen prek run --all-files") still executes correctly.
  3. Verify that a command containing $(whoami) does not expand the subcommand.

Done when

Shell metacharacters in projects.json command values cannot alter the commands executed on the agent's host.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions