T09 · Insecure Skill Coding Practices
- Location
SKILL.md:95- Finding
User-Controlled JavaScript Injection in Browser Evaluation
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 95–96
Vulnerability Type: JavaScript injection through unsafe interpolation
Risk Level: HighVulnerable Code
javascript browser action=act profile=user targetId=<id> request={"kind":"evaluate","fn":"() => { const ed=[...document.querySelectorAll('[contenteditable=\"true\"]')].find(e=>{const r=e.getBoundingClientRect();return r.width>100 && r.height>20;}); if(!ed) return 'no-editor'; ed.focus(); const sel=window.getSelection(); const range=document.createRange(); range.selectNodeContents(ed); range.collapse(false); sel.removeAllRanges(); sel.addRange(range); document.execCommand('insertText',false,'<MESSAGE TEXT>'); return ed.innerText; }"}text Replace `<MESSAGE TEXT>` with the user's message. Escape single quotes (`'` → `\\'`).Technical Analysis
The skill instructs the agent to interpolate user-controlled message content directly into JavaScript source executed by the browser's
evaluateoperation. Escaping only apostrophes is not sufficient to create a safe JavaScript string literal.Backslashes, carriage returns, line feeds, Unicode line separators, and interactions between backslashes and escaped quotes can alter the generated source. In particular, attacker-controlled backslashes can interfere with the prescribed quote escaping, potentially terminate the intended string, and introduce arbitrary JavaScript statements.
The resulting code executes in the context of the user's authenticated Douyin page. This is more severe than ordinary message corruption because injected statements may access DOM-visible account or conversation data and perform actions with the active web session.
Attack Path
- An attacker supplies or influences the text that the user asks the agent to send.
- The agent follows the skill and replaces only apostrophes with the documented escape sequence.
- The agent inserts the resulting value in ...[truncated 1515 chars]
- Remediation
View remediation
Remediation Suggestions
Do not concatenate user-controlled message content into executable JavaScript source.
- Pass the message as a separate structured argument to the browser evaluation function if the browser API supports evaluation arguments.
- If separate arguments are unavailable, serialize the message with a trusted JSON serializer rather than implementing character-by-character escaping. The resulting JSON string literal must be inserted without subsequent transformations.
- Prefer a browser typing or DOM API that accepts text as data independently from the evaluation source.
- Avoid
innerHTML, template-generated scripts,eval, or similar dynamic-code mechanisms when inserting the message. - Before sending, compare the editor's text against the original message exactly, allowing only explicitly documented editor artifacts such as a known zero-width character.
- Abort the operation if source construction, insertion, or equality verification fails.
- Add tests covering apostrophes, quotation marks, backslashes, multiline text, Unicode separators, escape-like sequences, and payload-shaped input.
- Treat externally sourced or indirectly supplied message text as untrusted even when the user requested the final send action.
A safe conceptual pattern is:
javascript (message) => { const editor = findMessageEditor(); editor.focus(); document.execCommand("insertText", false, message); }Here,
messagemust be supplied through the tool's structured argument mechanism rather than embedded in the function source.
