T09 · Insecure Skill Coding Practices
- Location
SKILL.md:58- Finding
Shell Command Injection Through User-Controlled JSON Payload
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:58-65
Vulnerability Type: Shell command injection and excessive credential exposure
Risk Level: HighVulnerable Code
text Only after confirmation, use the `exec` tool: { "tool": "exec", "command": "bash -c 'set -a; source ~/.openclaw/services/life-db/.env; uv run --project ~/.openclaw {baseDir}/scripts/insert_workout.py <json>'" } Replace `<json>` with the minified JSON payload (no newlines, properly shell-escaped).Technical Analysis
The Skill instructs the Agent to place a JSON document derived from user-controlled workout data directly inside a
bash -ccommand. Correct shell escaping is delegated to the Agent rather than enforced by an argument-safe execution interface. Fields such as exercise names and notes may contain quotes, command substitutions, shell metacharacters, or other syntax that can escape the intended argument if serialization is incomplete.The command loads credentials before processing the payload:
bash set -a source ~/.openclaw/services/life-db/.envsourceexecutes the.envfile as shell code rather than parsing it strictly as data.set -athen exports every variable assigned by that file to subsequently launched processes. This is broader than necessary because the insertion script only requiresDATABASE_URLor the PostgreSQL connection variables.The Python implementation uses parameterized SQL, so direct SQL injection was not identified. The vulnerability exists at the shell-command construction boundary before Python parses the JSON.
Attack Path
- An attacker supplies workout information containing shell syntax in a free-text field such as
notesorexercise_name. - The Agent parses that content and includes it in the minified JSON payload.
- The Agent interpolates the payload into the documented
bash -ccommand. - If quoting or escaping is incomplete ...[truncated 1309 chars]
- An attacker supplies workout information containing shell syntax in a free-text field such as
- Remediation
View remediation
Remediation Suggestions
- Remove
bash -cand invoke the Python script through an execution API that accepts an argument array without shell interpretation. - Prefer passing the JSON document through standard input rather than embedding it in a command string.
- Update
insert_workout.pyto read and decode JSON from standard input, with a documented size limit. - Load the environment file using a strict dotenv parser instead of
source, ensuring that its contents cannot execute shell code. - Allowlist only
DATABASE_URLorPGHOST,PGPORT,PGDATABASE,PGUSER, andPGPASSWORD; do not export unrelated variables. - Protect the credential file with restrictive filesystem permissions, such as mode
0600. - Configure a dedicated database role restricted to the required schema and operations. It should not own the database, create roles, create extensions, or access unrelated schemas.
- Add explicit application-level validation and length limits for dates, numeric fields, exercise names, notes, and the number of exercises.
- If a shell cannot be eliminated, generate the argument with a proven escaping routine and pass it positionally rather than through textual interpolation. Shell removal remains the preferred fix.
- Remove
