T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:159
- Finding
- Workspace-Controlled Quality-Gate Configuration Enables Arbitrary Command Execution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 159–216 **Vulnerability Type**: Command injection through an unrestricted configuration value **Risk Level**: High ### Complete Code Snippet ```markdown Configuration is loaded from (in order of precedence): 1. `.openclaw/review-orchestrator.yaml` (OpenClaw standard) 2. `.claude/review-orchestrator.yaml` (Claude Code compatibility) 3. Defaults (built-in) ``` ```yaml # .openclaw/review-orchestrator.yaml quality_gates: test_command: "npm test" # Node.js (default) # test_command: "go test ./..." # Go # test_command: "pytest" # Python # test_command: "cargo test" # Rust coverage_threshold: 5 # Max allowed coverage drop (%) require_docs: true # Require documentation updates ``` ```markdown ### Quality Gate Checks | Check | Condition | Severity | |-------|-----------|----------| | Tests pass | `{test_command}` exit 0 | Critical | | Coverage maintained | delta ≤ `{coverage_threshold}`% | Important | | No critical findings | review.critical == 0 | Critical | | Docs updated | changed files have docs (if `require_docs`) | Minor | > Checks use configured values from `quality_gates` section. Defaults: test_command=`npm test`, > coverage_threshold=5, require_docs=true. ``` ### Technical Analysis The skill instructs the agent to load `test_command` from configuration files located in the current workspace and execute that value as a quality-gate command. The documented interface represents the command as an unrestricted string rather than an allowlisted executable and structured argument array. A repository author can therefore supply a malicious `.openclaw/review-orchestrator.yaml` or `.claude/review-orchestrator.yaml` containing shell operators, command substitutions, pipelines, or an entirely different executable. If the underlying agent passes this string to a shell when `/ro gate` is invoked, the configuration becomes an arbitrary command-execution ...[truncated 1683 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the unrestricted `test_command` string with a structured executable and argument list, for example: ```yaml quality_gates: test: executable: npm arguments: - test ``` 2. Execute the program directly without a shell, such as through an API equivalent to `execFile`, and never through `sh -c`, `bash -c`, or a similar shell interpreter. 3. Maintain an explicit allowlist of supported test executables and approved arguments. 4. Reject shell metacharacters, command substitutions, redirects, pipelines, and newline characters if backward compatibility temporarily requires a string field. 5. Treat workspace configuration as untrusted input and validate its schema before use. 6. Require explicit user confirmation before executing a non-default or repository-supplied command, displaying the exact executable and arguments. 7. Run quality-gate commands in a restricted sandbox with minimal filesystem access, no unnecessary credentials, and network access disabled by default. 8. Update the security documentation to disclose that quality gates execute local test programs and clearly state their permission boundaries. ]]>
