Back to skill

Security audit

HKEX L&I Daily Factor Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill has a legitimate HKEX digest purpose, but it needs Review because its cleanup logic can delete unrelated PDF/text files if the scratch directory is misconfigured.

Review the tmp_dir setting before installing or scheduling this skill. Use a dedicated empty private directory, do not point it at Documents, a workspace, /tmp directly, or any shared folder, and avoid running the agent as root. Only enable the cron job if you are comfortable with scheduled exec-based runs.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:128
Finding

Configurable Scratch Directory Allows Deletion of Unrelated Files

Content
View full analysis
/dev/null # start clean trap 'rm -f "$TMP"/*.pdf 2>/dev/null' EXIT # belt-and-braces cleanup (also done explicitly in Step 6) ``` The final cleanup expands the set of affected files: ```bash rm -f "$TMP"/*.pdf "$TMP"/*.txt "$TMP"/discover.json "$TMP"/matches.tsv "$TMP"/selected.tsv "$TMP"/http_code 2>/dev/null ``` The directory originates from user-editable configuration: ```bash TMP=$(jq -r '.tmp_dir' "$SRC") ``` ### Technical Analysis The Skill treats `tmp_dir` as a dedicated scratch directory but does not enforce that assumption. It neither creates a unique per-run subdirectory nor verifies that the configured path is reserved exclusively for this Skill. At startup, every file matching `*.pdf` in the configured directory is removed. At normal exit, every matching `*.pdf` and `*.txt` file is removed. These wildcard operations are not restricted to files created by the current execution. Although shell quoting prevents ordinary whitespace expansion of the directory value, it does not prevent destructive behavior when the quoted value identifies an existing shared directory. A legitimate configuration error, such as setting `tmp_dir` to `/tmp`, a workspace, or a document directory, is sufficient to trigger data loss. The exit trap only removes PDFs, so it does not fully implement the stated cleanup policy on failure. Conversely, the explicit successful cleanup is overly broad because it removes all text and PDF files in t ...[truncated 1491 chars]
Remediation
View remediation
&2 exit 1 ;; esac mkdir -p -- "$TMP_PARENT" || exit 1 chmod 700 -- "$TMP_PARENT" || exit 1 RUN_TMP=$(mktemp -d "$TMP_PARENT/run.XXXXXXXX") || { echo "ERROR: unable to create private run directory" >&2 exit 1 } cleanup() { case "$RUN_TMP" in "$TMP_PARENT"/run.*) rm -rf -- "$RUN_TMP" ;; *) echo "ERROR: refusing unsafe cleanup path" >&2 ;; esac } trap cleanup EXIT HUP INT TERM ``` Additional hardening measures: 1. Use `RUN_TMP` for every downloaded or generated file. 2. Refuse empty paths, `/`, and paths that are not absolute. 3. Resolve canonical paths and reject known shared or sensitive directories unless a private child directory is created within them. 4. Set restrictive permissions with `umask 077`. 5. Never remove `"$TMP"/*.pdf` or `"$TMP"/*.txt` from a user-selected parent directory. 6. If recursive deletion is used, guard it with strict prefix and non-empty-path validation. 7. Track exact generated filenames if a unique run directory cannot be used. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:37
Finding

Undefined Default Home Variable Can Resolve Configuration Paths to the Filesystem Root

Content
View full analysis
"$HOME_DIR/.wtest" && rm -f "$HOME_DIR/.wtest" ) || echo "FAIL: $HOME_DIR not writable (set HKEX_LI_MONITOR_HOME)" ``` ```text 4. Write `$HOME_DIR/config.json` from the schema atomically (write `config.json.tmp`, then `mv`). Seed it from `config.example.json`. ``` ### Technical Analysis The mandatory path-resolution block references `HOME_DIR_DEFAULT`, but the documented procedure never initializes that variable before it is expanded. When both `HKEX_LI_MONITOR_HOME` and `HOME_DIR_DEFAULT` are unset, this assignment produces an empty value: ```bash HOME_DIR="" ``` The subsequent configuration expression becomes: ```bash CFG="/config.json" ``` Similarly, the writable probe becomes `/.wtest`. The behavior therefore differs from the documented default of `$HOME/.config/hkex-li-daily-factor-monitor`. Under a normal unprivileged account, `mkdir -p ""` generally fails, making setup or execution unreliable. The block does not enable `set -e` or explicitly check the result, so later steps may continue using root-relative paths. Under a privileged Agent account, the readiness probe and setup procedure can create files at the filesystem root. If ` ...[truncated 1920 chars]
Remediation
View remediation
&2 exit 1 ;; /*) ;; *) echo "ERROR: HOME_DIR must be an absolute path" >&2 exit 1 ;; esac mkdir -p -- "$HOME_DIR" chmod 700 -- "$HOME_DIR" CFG="$HOME_DIR/config.json" ``` Configuration should be written atomically and with restrictive permissions: ```bash CFG_TMP=$(mktemp "$HOME_DIR/config.json.tmp.XXXXXXXX") chmod 600 "$CFG_TMP" # Write validated configuration to "$CFG_TMP" here. mv -f -- "$CFG_TMP" "$CFG" ``` Additional hardening measures: 1. Check the return status of every filesystem operation. 2. Reject empty, root, relative, or newline-containing configuration paths. 3. Ensure the resolved directory is owned by the expected user. 4. Avoid running setup or monitoring tasks as root. 5. Keep the documented setup behavior consistent with `scripts/setup.sh`, which already uses `$HOME/.config/hkex-li-daily-factor-monitor`. 6. Add automated tests covering unset variables, an unset `HOME`, malformed overrides, root paths, and unwritable directories. ]]>
Vulnerability Patterns
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • 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
Findings (17)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 118)May include surrounding context.

curl -sS -o /dev/null -m 20 -A "$UA" -w "sfc: HTTP %{http_code}\n" https://apps.sfc.hk/
|| echo "WARN: cannot reach https://apps.sfc.hk (not needed today; reserved for future extension)"

4. Writable home + scratch

( : > "$HOME_DIR/.wtest" && rm -f "$HOME_DIR/.wtest" ) || echo "FAIL: $HOME_DIR not writable (set HKEX_LI_MONITOR_HOME)" mkdir -p "$TMP" 2>/dev/null && ( : > "$TMP/.wtest" && rm -f "$TMP/.wtest" ) || echo "FAIL: tmp_dir '$TMP' not writable (set config.tmp_dir)"

text
A 30x/200 from hkexnews counts as reachable. `apps.sfc.hk` is a soft check kept

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · SKILL.md (reported line 118)May include surrounding context.

curl -sS -o /dev/null -m 20 -A "$UA" -w "sfc: HTTP %{http_code}\n" https://apps.sfc.hk/
|| echo "WARN: cannot reach https://apps.sfc.hk (not needed today; reserved for future extension)"

4. Writable home + scratch

( : > "$HOME_DIR/.wtest" && rm -f "$HOME_DIR/.wtest" ) || echo "FAIL: $HOME_DIR not writable (set HKEX_LI_MONITOR_HOME)" mkdir -p "$TMP" 2>/dev/null && ( : > "$TMP/.wtest" && rm -f "$TMP/.wtest" ) || echo "FAIL: tmp_dir '$TMP' not writable (set config.tmp_dir)"

text
A 30x/200 from hkexnews counts as reachable. `apps.sfc.hk` is a soft check kept

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · SKILL.md (reported line 119)May include surrounding context.

curl -sS -o /dev/null -m 20 -A "$UA" -w "sfc: HTTP %{http_code}\n" https://apps.sfc.hk/
|| echo "WARN: cannot reach https://apps.sfc.hk (not needed today; reserved for future extension)"

4. Writable home + scratch

( : > "$HOME_DIR/.wtest" && rm -f "$HOME_DIR/.wtest" ) || echo "FAIL: $HOME_DIR not writable (set HKEX_LI_MONITOR_HOME)" mkdir -p "$TMP" 2>/dev/null && ( : > "$TMP/.wtest" && rm -f "$TMP/.wtest" ) || echo "FAIL: tmp_dir '$TMP' not writable (set config.tmp_dir)"

text
A 30x/200 from hkexnews counts as reachable. `apps.sfc.hk` is a soft check kept

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 119)May include surrounding context.

|| echo "WARN: cannot reach https://apps.sfc.hk (not needed today; reserved for future extension)"

4. Writable home + scratch

( : > "$HOME_DIR/.wtest" && rm -f "$HOME_DIR/.wtest" ) || echo "FAIL: $HOME_DIR not writable (set HKEX_LI_MONITOR_HOME)" mkdir -p "$TMP" 2>/dev/null && ( : > "$TMP/.wtest" && rm -f "$TMP/.wtest" ) || echo "FAIL: tmp_dir '$TMP' not writable (set config.tmp_dir)"

text
A 30x/200 from hkexnews counts as reachable. `apps.sfc.hk` is a soft check kept
for a possible future SFC cross-reference; its failure is a WARN, not a FAIL.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

The skill performs wildcard deletion in a configurable scratch directory (rm -f "$TMP"/*.pdf) without validating that the directory resolves to a safe, dedicated location. If tmp_dir is misconfigured or maliciously set to an unintended path, the cleanup step could delete unrelated PDF files in that directory, causing integrity loss.

Content

Scanner excerpt · SKILL.md (reported line 132)May include surrounding context.

Run the storage block and the config-load block above. Then prepare a clean scratch dir and register cleanup so PDFs are removed even if a later step fails:

bash
mkdir -p "$TMP"; rm -f "$TMP"/*.pdf 2>/dev/null   # start clean
trap 'rm -f "$TMP"/*.pdf 2>/dev/null' EXIT        # belt-and-braces cleanup (also done explicitly in Step 6)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · SKILL.md (reported line 132)May include surrounding context.

Run the storage block and the config-load block above. Then prepare a clean scratch dir and register cleanup so PDFs are removed even if a later step fails:

bash
mkdir -p "$TMP"; rm -f "$TMP"/*.pdf 2>/dev/null   # start clean
trap 'rm -f "$TMP"/*.pdf 2>/dev/null' EXIT        # belt-and-braces cleanup (also done explicitly in Step 6)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

The EXIT trap repeats the same wildcard deletion against a configurable directory, so any unsafe tmp_dir value will trigger cleanup automatically even on failure paths. That makes accidental or malicious misconfiguration more dangerous because deletion is harder to avoid once execution starts.

Content

Scanner excerpt · SKILL.md (reported line 133)May include surrounding context.

scratch dir and register cleanup so PDFs are removed even if a later step fails:

bash
mkdir -p "$TMP"; rm -f "$TMP"/*.pdf 2>/dev/null   # start clean
trap 'rm -f "$TMP"/*.pdf 2>/dev/null' EXIT        # belt-and-braces cleanup (also done explicitly in Step 6)

Step 2 — Discover the latest relevant announcement(s)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This cleanup on the no-results path again deletes *.pdf from the configured scratch directory rather than only the files fetched by the current run. In a shared or incorrectly set directory, an attacker or operator mistake could cause unrelated documents to be removed.

Content

Scanner excerpt · SKILL.md (reported line 169)May include surrounding context.

Empty result → explicit error (do not emit an empty digest):

bash
if [ ! -s "$TMP/matches.tsv" ]; then
  rm -f "$TMP"/*.pdf 2>/dev/null
  echo "No Daily Targeted Leverage Factor announcements found in the recent HKEXnews window under OTHERS (FUNDS, ETC)." >&2
  exit 1
fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

The final cleanup broadens deletion to multiple wildcarded file classes in the configurable scratch directory (*.pdf, *.txt, and named artifacts). Without strict path validation and per-run isolation, this can destroy unrelated files if the configured directory is shared, symlinked, or mis-set. The skill context increases risk because the cleanup is mandatory and runs on every execution.

Content

Scanner excerpt · SKILL.md (reported line 319)May include surrounding context.

Step 6 — Cleanup & exit

Delete all downloaded PDFs and extracted text; retain nothing (copyright):

bash
rm -f "$TMP"/*.pdf "$TMP"/*.txt "$TMP"/discover.json "$TMP"/matches.tsv "$TMP"/selected.tsv "$TMP"/http_code 2>/dev/null

The EXIT trap from Step 1 also removes PDFs if the run aborted early.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SETUP.md (reported line 9)May include surrounding context.

md
- A Telegram channel/bot configured in OpenClaw for delivery.

## Configuration
1. Create a config directory: `mkdir -p ~/.config/hkex-li-daily-factor-monitor`
2. Copy `config.example.json` to `~/.config/hkex-li-daily-factor-monitor/config.json`.
3. Edit the file to set your `openclaw_workspace` and `history_days`.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill clearly instructs use of shell-capable tools (curl, jq, pdftotext, rm, awk, sed) but declares no explicit tool scope or allowlist. That increases attack surface because an agent/runtime may grant broader execution capability than minimally required, making any prompt-injection or operator mistake more consequential.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The storage section claims 'All reads/writes happen in one writable, per-user home directory,' but later steps create and write PDFs, text files, JSON, TSVs, and status files under config.tmp_dir such as /tmp/hkex_li_daily_factor_monitor. This is an active contradiction in the skill's own instructions about where data is written.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 46)May include surrounding context.

bash
HOME_DIR="${HKEX_LI_MONITOR_HOME:-$HOME_DIR_DEFAULT}"
mkdir -p "$HOME_DIR"
CFG="$HOME_DIR/config.json"          # settings (created at setup; falls back to skill's config.example.json)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The config hard-codes the search parameter lang to EN, which imposes a specific language/locale choice. The document does not offer the user a language choice or explain why English is required for this skill, so it fits the language/locale policy-violation category.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 345)May include surrounding context.

md
2. Run the READINESS CHECK and report gaps.
3. Confirm/ask (offer defaults): `days_back` (7), `run_mode` (`latest`),
   `headline_keyword`, `category_keyword`, `tmp_dir`.
4. Write `$HOME_DIR/config.json` from the schema atomically (write
   `config.json.tmp`, then `mv`). Seed it from `config.example.json`.
5. Offer to install the schedule (below); confirm before creating.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/setup.sh (reported line 10)May include surrounding context.

sh
command -v pdftotext >/dev/null 2>&1 || { echo >&2 "pdftotext required (poppler-utils)."; exit 1; }

echo "Creating config directory..."
mkdir -p "$HOME/.config/hkex-li-daily-factor-monitor"

echo "Setup complete. Please copy config.example.json to ~/.config/hkex-li-daily-factor-monitor/config.json"

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description limits the skill to fetching HKEXnews announcements, parsing their PDFs, and emitting a digest. The readiness check additionally contacts https://apps.sfc.hk and the notes describe it as reserved for future SFC cross-reference, which is extra behavior not needed for the declared HKEX-only workflow.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.generated_source_template_injection

User-controlled placeholder is embedded directly into generated source code.

Critical
Code
suspicious.generated_source_template_injection
Location
SKILL.md:144