T09 · Insecure Skill Coding Practices
- Location
scripts/episode.js:66- Finding
Untrusted Story State Is Embedded Directly into Agent Instructions
- Content
View full analysis
{ const i = args.indexOf(flag); return i !== -1 && args[i+1] ? args[i+1] : def; }; const series = get('--series', 'shanghai'); const level = get('--level', 'B1').toUpperCase(); const chapter = parseInt(get('--chapter', '1'), 10); const state = get('--state', ''); const lang = get('--lang', 'zh'); ``` ```js ${state ? `STORY SO FAR (continue from this state): ${state} ` : `This is Episode 1. Introduce the world and main character. End on a hook that makes the reader want Episode 2.`} ``` ### Technical Analysis The `--state` argument is accepted as an arbitrary string and interpolated verbatim into a prompt intended for an AI agent. Although the documented input is JSON, the script does not call `JSON.parse`, validate a schema, impose a size limit, or separate the supplied data from executable prompt instructions. Consequently, a state value can contain newlines and imperative text that terminates the intended story-state context and introduces competing instructions. The `--level` and raw `--series` values are also reflected in the generated prompt without strict allowlist validation, although `--state` is the most direct and substantial injection surface. This script only prints the resulting prompt. It does not itself execute shell commands or invoke tools. Exploitation therefore depends on the generated output being passed to an AI agent, as intended by the Skill workflow. ### Attack Path 1. An attacker creates or shares a purported continuation-state JSON value containing embedded prompt instructions. 2. A user follows the documented workflow and passes that value to `episode.js` through `--state`. 3. The script inserts the complete value directly below the `ST ...[truncated 1008 chars]- Remediation
View remediation
