T09 · Insecure Skill Coding Practices
- Location
publish-toutiao.sh:7- Finding
User-Controlled Content Is Interpolated into Executable JavaScript
- Content
View full analysis
{ const editor = document.querySelector('.ProseMirror'); if (!editor) return '错误:未找到编辑器'; // 注入内容 editor.innerHTML = \`$CONTENT\`; // 触发完整事件序列 editor.dispatchEvent(new Event('input', { bubbles: true })); editor.dispatchEvent(new Event('selectionchange', { bubbles: true })); editor.dispatchEvent(new CompositionEvent('compositionend', { bubbles: true, data: editor.innerText })); return '内容注入完成,共' + editor.innerText.length + '字'; }" }" ``` A substantially similar unsafe interpolation pattern is also presented as recommended usage in `SKILL.md`, lines 531-540. ### Technical Analysis The second command-line argument is stored in `CONTENT` and then substituted directly into the source of a JavaScript function passed to the browser automation tool. The value is placed inside a JavaScript template literal without JavaScript or JSON encoding: ```javascript editor.innerHTML = `$CONTENT`; ``` The shell performs the substitution before the request reaches the browser. A value containing a backtick can terminate the intended template literal and append arbitrary JavaScript statements. Template-literal expressions such as `${...}` can also cause supplied expressions to execute while the function is evaluated. The resulting code runs in the context of an authenticated `mp.toutiao.com` page. This is not limited to ordinary HTML injection into the article editor; it permits execution of attacker-controlled JavaScript through the browser evaluation interface. Other arguments, including `TITLE`, `IMAGE_KEYWORD`, and `COVER_KEYWORD`, are als ...[truncated 2095 chars]- Remediation
View remediation
{ const editor = document.querySelector('.ProseMirror'); if (!editor) return 'Editor not found'; const content = %s; editor.innerHTML = content; editor.dispatchEvent(new Event('input', {bubbles: true})); return editor.innerText.length; }""" % json.dumps(content) } print(json.dumps(request)) PY ) browser act request="$REQUEST" ``` Where supported, passing `content` as a separate evaluation argument is preferable to generating function source, even when JSON encoding is used. ]]>
