Back to skill

Security audit

Banker Memo

Security checks for vulnerabilities and agentic risk

Overview

The skill has a legitimate CN banker-memo purpose, but it needs review because unvalidated filenames, paths, and parameters are embedded into a prompt sent to a main agent that can write files.

Install only if you intend to run a China-focused banker-memo workflow on raw-data you trust. Use a fresh output directory, avoid attacker-supplied filenames or JSON snapshots, and run the report agent with read access limited to the validated raw-data directory and write access limited to the chosen output directory.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

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]
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The manifest description restricts use to CN companies and uses Chinese trigger phrases and output framing without any opt-in or alternative language/locale behavior. This is a natural-language locale constraint that appears mandatory rather than user-selectable.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The prompt content is written as a mandatory Chinese analyst persona and requires producing a Chinese investment memo for named Chinese audiences, but it does not offer any language or locale opt-in. Under the policy, forcing a specific language without user choice is a natural-language policy violation unless the constraint is explicitly justified.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The emitted prompt is entirely in Chinese and instructs the model to act as a China-focused investment banker for a Chinese listed company, which imposes a specific language/locale on downstream behavior. Under the stated policy, forcing a language without user choice or explicit opt-in is a natural-language policy concern.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The workflow instructs the agent to run commands that generate prompts, write deliverables, and compile outputs without an explicit warning or consent checkpoint about filesystem modifications. In an agentic environment, silent writes can overwrite existing work, create unexpected artifacts, or operate on attacker-influenced paths if `raw_dir`/`out_dir` are not tightly controlled.

Static analysis

No suspicious patterns detected.