T09 · Insecure Skill Coding Practices
- Location
tasks.py:82- Finding
Shell Command Injection Through Remotely Controlled Job IDs
- Content
View full analysis
Vulnerability Details
File Location:
tasks.py, lines 82–87
Vulnerability Type: Shell command injection through unsafe command generation
Risk Level: HighComplete Code Snippet
python title = "CLAIM " + job_id body = "```json\n" + json.dumps(claim, indent=2) + "\n```\n" print(json.dumps({ "open_this_issue": {"repository": REPO, "title": title, "body": body}, "with_gh": "gh issue create -R %s --title %s --body-file claim.md # after saving body to claim.md" % (REPO, json.dumps(title)), "in_a_browser": "https://github.com/%s/issues/new?%s" % (REPO, urllib.parse.urlencode({"title": title, "body": body})), "then": "a bot answers on the issue within about a minute: the job is yours, or exactly what to fix", }))The affected
job_idoriginates from the remote board data:python BOARD = "https://raw.githubusercontent.com/dhyabi2/paid-work-queue/main/jobs.json"Technical Analysis
The skill obtains job records from a mutable remote JSON document and uses a selected record's
idto construct a shell command advertised as a ready-to-runghinvocation.json.dumps(title)produces JSON string syntax, not safe POSIX shell quoting. The resulting value is normally enclosed in double quotes. Shell substitutions such as$(command)and backtick substitutions remain active inside double-quoted shell arguments.An attacker able to modify the remote board data can therefore publish a valid, open job whose ID contains shell substitution syntax. The ID passes through
by_id,title, andjson.dumps()without shell-safe escaping. If the generatedwith_ghcommand is executed by an agent or operator, the local shell evaluates the injected substitution before invokinggh.The relevant trust boundary is from attacker-controlled remote repository content to a command executed in the local agent environment. There is no evidence that the project author intentionally uses ...[truncated 1295 chars]
- Remediation
View remediation
Remediation Suggestions
Do not generate executable shell command strings containing remote data.
-
Prefer invoking GitHub CLI directly with an argument array and shell processing disabled:
python subprocess.run( [ "gh", "issue", "create", "-R", REPO, "--title", title, "--body-file", "claim.md", ], check=True, shell=False, ) -
If the skill must only print instructions, emit a structured argument array rather than a copy-and-paste shell command.
-
If a shell command must be displayed, quote every dynamic argument with a shell-specific quoting function such as
shlex.quote()and clearly identify the target shell. -
Apply a restrictive validation policy to remotely supplied job IDs, such as permitting only letters, digits, periods, underscores, and hyphens. Validation should be defense in depth rather than a substitute for safe process invocation.
-
Keep remote task data separate from executable instructions and require explicit review before executing any command derived from that data.
-
