T01 · Skill Instruction Hijacking
Error
- Location
- scripts/build_banker_prompt.py:7
- Finding
- Untrusted parameters and raw-data filenames are embedded directly into an executable agent prompt<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_banker_prompt.py`, lines 7-21 **Vulnerability Type**: Indirect prompt injection through command-line parameters, paths, and filenames **Risk Level**: High ### Vulnerable Code ```python ts_code, name_cn, industry, raw_dir, out_dir = sys.argv[1:6] # Discover raw-data files + uscc files = sorted(glob.glob(f"{raw_dir}/*.json")) file_list = "\n".join(f"- `{pathlib.Path(f).name}`" for f in files) # Find PM uscc from filename uscc = next((pathlib.Path(f).stem.split("-primematrix-")[0] for f in files if "primematrix" in pathlib.Path(f).name), "N/A") print(f"""## 身份 你是中资投行(卖方研究)资深分析师,覆盖{industry}板块。当前任务:基于 `{raw_dir}/` 真实 MCP 调用快照,针对 **{name_cn}({ts_code})** 写一份**投行级深度研报 memo**,给信贷评审委员会 + 股权投资经理共用。 ## 你有的真实数据(读取 {raw_dir}/ 目录) {file_list} ``` The output directory is likewise placed directly into an instruction later in the same prompt: ```python ## 输出(写入 `{out_dir}/`) ``` ### Technical Analysis The script treats command-line arguments and discovered filesystem names as trusted prompt instructions. It performs no validation, escaping, canonicalization, or separation between trusted instructions and untrusted data before inserting the following values into the prompt: - `ts_code` - `name_cn` - `industry` - `raw_dir` - `out_dir` - Discovered JSON filenames through `file_list` - A filename-derived identifier through `uscc` A filename can contain spaces, backticks, Markdown syntax, and, on supported filesystems, newline characters. An attacker who can populate the raw-data directory can therefore create a filename that terminates the intended Markdown formatting and injects new instructions. Direct command-line parameters provide an even simpler injection channel if they originate from an untrusted caller. This prompt is not merely displayed to a user. The workflow in `SKILL.md` directs the operator to submit the generated text to the main OpenClaw agent. Consequently, injected tex ...[truncated 2611 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Treat all supplied values and snapshot contents as untrusted data** - Do not concatenate untrusted strings directly into an instruction-bearing prompt. - Clearly label external values as data that must never be interpreted as instructions. - This framing is defense in depth only; textual delimiters alone do not reliably prevent prompt injection. 2. **Validate command-line parameters** - Restrict `ts_code` to the expected exchange-code syntax. - Apply strict length and character allowlists to company and industry names. - Reject control characters, newlines, backticks, and other prompt-structure characters where they are not required. - Resolve `raw_dir` and `out_dir` with `Path.resolve()` and verify that both remain under administrator-approved roots. 3. **Validate discovered filenames** - Accept only a documented filename grammar, such as alphanumeric characters, underscores, hyphens, and a `.json` suffix. - Reject filenames containing control characters, line breaks, backticks, or unexpected Unicode formatting characters. - Do not derive a trusted company identifier from an unvalidated filename. 4. **Parse snapshots before model exposure** - Validate every JSON file against an explicit schema. - Extract only expected scalar fields and serialize them into a constrained data structure. - Reject or neutralize instruction-like free-text fields where those fields are unnecessary. - Prefer deterministic preprocessing and calculations outside the language model. 5. **Separate data processing from privileged actions** - Run the report-writing agent with a minimal tool allowlist. - Restrict reads to the validated raw-data directory. - Restrict writes to a newly created, dedicated output directory. - Disable network access and unrelated shell or filesystem tools for this workflow. - Enforce these boundaries at the tool or operating-system layer rather than relying on prom ...[truncated 390 chars]
