T09 · Insecure Skill Coding Practices
- Location
SKILL.md:25- Finding
User-Controlled Water Quantity Injected into Executable JavaScript
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, line 25
Vulnerability Type: JavaScript code injection through unsafe source-code substitution
Risk Level: HighVulnerable Code
bash node -e "const fs=require('fs');const f='{baseDir}/health-data.json';let d={water:[],sleep:[]};try{d=JSON.parse(fs.readFileSync(f))}catch(e){}d.water.push({time:new Date().toISOString(),cups:CUPS});fs.writeFileSync(f,JSON.stringify(d));console.log('Da ghi: '+CUPS+' coc')"The accompanying instruction directs the agent to replace
CUPSwith a number obtained from user input. It does not require strict numeric parsing, range validation, or safe argument passing.Technical Analysis
CUPSis embedded directly into JavaScript source passed tonode -e. If an agent substitutes the raw or insufficiently validated user-controlled value, an attacker can terminate the intended expression and append arbitrary JavaScript.For example, a value shaped like the following can escape the intended
cupsproperty expression:javascript 0});require('child_process').execSync('id');/*After substitution, Node.js evaluates both the intended record operation and the injected statement. The trailing comment can suppress the remaining generated source. Because
requireis available, injected code can access Node.js filesystem, process, networking, and child-process capabilities.This issue does not require a third-party dependency or a remote payload. It results from constructing executable source code with a user-derived value.
Attack Path
- An attacker submits a water-tracking request containing a crafted value instead of a normal cup count.
- The agent follows the skill instruction and substitutes that value for
CUPSwithout strict numeric validation. - The resulting command is supplied to
node -e. - Node.js parses the crafted value as executable source rather than merely as health-record data.
- Th ...[truncated 600 chars]
- Remediation
View remediation
Remediation Suggestions
Do not insert user-controlled values into JavaScript source. Keep the script fixed and pass the quantity as a separate argument or through a structured input channel. Parse and validate it before use.
A hardened implementation should:
- Pass the value as a command-line argument rather than interpolating it into the
node -eprogram. - Convert it with
Number(...). - Reject values for which
Number.isFinite(...)is false. - Enforce an appropriate range and, if required by the data model, integer-only input.
- Avoid invoking a shell where a direct Node.js process call or standalone script is available.
- Report invalid input without modifying the JSON file.
Example validation logic:
javascript const cups = Number(process.argv[1]); if (!Number.isFinite(cups) || !Number.isInteger(cups) || cups < 0 || cups > 100) { throw new Error('Invalid cup count'); }Prefer placing this fixed logic in a reviewed script and invoking it with an argument array so input is treated exclusively as data.
- Pass the value as a command-line argument rather than interpolating it into the
