T09 · Insecure Skill Coding Practices
- Location
SKILL.md:53- Finding
Unvalidated Remote Metadata Allows Path Traversal and Unintended File Writes
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 53-60
Vulnerability Type: Path traversal, unsafe file-path construction, and unsafe JSON construction
Risk Level: Mediumbash DIR="$HOME/.qclaw/geo-exports/${BRAND}_${PRODUCT}_C${CYCLE}/fanwen" mkdir -p "$DIR" curl -fsSL -o "$DIR/fanwen.zip" \ "$BASE/api/geo/optimization/$OPT_ID/cycles/$CYCLE/export/fanwen.zip" \ -H "Authorization: Bearer $GEO_KEY" curl -s -X POST "$BASE/api/geo/optimization/$OPT_ID/cycles/$CYCLE/mass-publish-export" \ -H "Authorization: Bearer $GEO_KEY" -H "Content-Type: application/json" \ -d "{\"branch\":\"fanwen\",\"local_path_hint\":\"$DIR\"}"Technical Analysis
The export directory incorporates
BRAND,PRODUCT, andCYCLE, which are derived from task metadata returned by the remote service. The Skill does not require these values to be validated, sanitized, or canonicalized before using them as filesystem path components.Shell quoting prevents the expanded values from being reinterpreted as shell commands, but it does not prevent path traversal. Values containing
/,../, or similar path components can cause the resolved directory to escape$HOME/.qclaw/geo-exports. The subsequentmkdir -pandcurl -ooperations would then create directories and writefanwen.zipat an unintended user-writable location.The same path is inserted into a JSON body through manual string interpolation. If remote metadata contains quotation marks, backslashes, or control characters, the resulting body may be malformed or may change the structure or values of the JSON request.
Attack Path
- An attacker gains control of, or compromises, task metadata returned by the configured GEO API.
- The attacker supplies a crafted brand, product, or cycle value containing traversal components, such as
../../target. - The Agent constructs
DIRdirectly from the malicious value without validation. mkdir -p "$DIR"creates the attacker-selected directory ...[truncated 990 chars]
- Remediation
View remediation
Remediation Suggestions
- Use a trusted immutable task identifier for directory names instead of human-readable remote metadata where possible.
- Validate every path component against a strict allowlist, such as
^[A-Za-z0-9._-]+$. - Explicitly reject path separators,
.., control characters, empty values, and absolute paths. - Canonicalize the final destination and verify that it remains beneath
$HOME/.qclaw/geo-exportsbefore creating directories or downloading files. - Refuse to overwrite an existing ZIP unless replacement is explicitly intended and authorized.
- Construct the request body with a JSON serializer rather than manual interpolation. For example:
bash payload=$(jq -n \ --arg branch "fanwen" \ --arg local_path_hint "$DIR" \ '{branch: $branch, local_path_hint: $local_path_hint}') curl -s -X POST \ "$BASE/api/geo/optimization/$OPT_ID/cycles/$CYCLE/mass-publish-export" \ -H "Authorization: Bearer $GEO_KEY" \ -H "Content-Type: application/json" \ --data-binary "$payload"- Apply the same validation and containment checks to both the
fanwenandfangxieexport flows.
