T09 · Insecure Skill Coding Practices
- Location
workflow.json:18- Finding
Shell Command Injection Through Unsanitized Workflow Template Interpolation
- Content
View full analysis
1000 pushed:>{{date}}\", type: REPOSITORY, first: 20) { nodes { ... on Repository { nameWithOwner description stargazerCount primaryLanguage url } } } }' --jq '.data.search.nodes[]'", ``` ```json "command": "summarize \"{{repo_url}}\" --extract-only", ``` ```json "command": "python3 /root/.openclaw/workspace/skills/card-renderer/scripts/render_vscode_card.py \"{{project_name}}\" \"{{one_liner}}\" \"/tmp/readme_summary.md\" \"/tmp/output/\"", ``` ```json "command": "cat > /tmp/github_blog_{{date}}.md << 'EOF'\n{{blog_content}}\nEOF\necho 'Blog saved to /tmp/github_blog_{{date}}.md'", ``` ### Technical Analysis The workflow directly interpolates template values into command strings intended for shell execution. The affected values include `language`, `date`, `repo_url`, `project_name`, `one_liner`, and `blog_content`. Surrounding a placeholder with shell quotes is not a sufficient defense because interpolation occurs before shell parsing. An attacker-controlled value can include the matching quote character, terminate the intended argument, insert shell syntax, and then restore syntactic validity. Command substitution constructs may also be evaluated when they occur in the resulting double-quoted command. The draft-saving step is especially hazardous. It inserts generated article content directly into a shell heredoc. Although the delimiter is quoted, a line containing only `EOF` still terminates the heredoc. Any following lines in `blog_content` would then be parsed as shell commands. The `date` placeholder is also inserted into an unquoted output path, enabling shell metacharacter injection and potentially arbitrary path selection. Repository de ...[truncated 2514 chars]- Remediation
View remediation
