Back to skill

Security audit

finance-daily-report

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a finance daily report tool, but it needs Review because setup stores API keys insecurely and the scheduled workflow uses unsafe shared temporary files.

Review before installing. Use a dedicated unprivileged account, avoid entering API keys into the setup script as written, prefer a proper secret store or tightly permissioned environment file, inspect the cron job before enabling automatic delivery, and assume fetched public content will be sent to DashScope or Volcengine for processing.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:55
Finding

API keys are entered visibly and persisted as plaintext shell configuration

Content
View full analysis
> "$SHELL_RC" echo "# Finance Daily Report — DashScope API Key" >> "$SHELL_RC" echo "export DASHSCOPE_API_KEY=\"$INPUT_DASHSCOPE\"" >> "$SHELL_RC" echo -e "${GREEN}✓ 已写入 $SHELL_RC${NC}" fi fi fi ``` ```bash read -rp " 可选:输入豆包 API Key 作为备用模型(留空跳过): " INPUT_DOUBAO if [ -n "$INPUT_DOUBAO" ]; then export DOUBAO_API_KEY="$INPUT_DOUBAO" if [ -n "$SHELL_RC" ] && ! grep -q "DOUBAO_API_KEY" "$SHELL_RC"; then echo "export DOUBAO_API_KEY=\"$INPUT_DOUBAO\"" >> "$SHELL_RC" echo -e "${GREEN}✓ DOUBAO_API_KEY 已写入 $SHELL_RC${NC}" fi fi ``` ### Technical Analysis The setup script uses `read -rp`, which does not suppress terminal echo. API keys are therefore displayed while the user types them and may be exposed to screen recording, terminal sharing, shoulder surfing, or terminal logging. The keys are subsequently written verbatim into `.bashrc` or `.zshrc`. These files are ordinary plaintext files and may be exposed through backups, diagnostic bundles, accidental repository commits, overly permissive home-directory permissions, or unrelated processes running under the same account. The script does not verify or harden the shell configuration file's permissions. It also writes user-controlled data into shell syntax without validating the expected API-key character set. A value containing shell substitution syntax such as `$(...)` would be stored literally and evaluated the next time the shell configurat ...[truncated 2010 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
scripts/collect_and_structure.py:263
Finding

Untrusted website content is embedded directly into LLM instructions without prompt-injection isolation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/workflow.md:21
Finding

Predictable shared temporary files permit symlink-based file truncation and data replacement

Content
View full analysis
/tmp/collector.log > /tmp/report_data.json ``` The same command pattern is repeated at lines 171-176: ```bash python3 scripts/collect_and_structure.py --date $(date +%Y-%m-%d) \ 2>/tmp/collector.log > /tmp/report_data.json ``` ### Technical Analysis The workflow writes report data and logs to fixed paths under `/tmp`. On typical Unix systems, `/tmp` is writable by every local user. Shell redirection opens or truncates the destination before the Python process begins, and it follows symbolic links. A local attacker can pre-create `/tmp/report_data.json` or `/tmp/collector.log` as a symbolic link to another file writable by the account running the workflow. When the privileged or service account executes the documented command, the shell truncates and overwrites the symlink target. The fixed report filename also allows local data replacement. An attacker with access to the shared temporary namespace may race the workflow or replace the report after collection but before the Phase 2 subagent reads it. This can inject attacker-controlled content into the report-generation pipeline. The project documentation indicates that reports may run from `/root/.openclaw` and be saved under `/root/.openclaw/workspace`. If the workflow is executed as root, the symlink attack could affect root-writable files. Actual impact depends on runtime user, filesystem protections, and local access. ### Attack Path Symlink file-clobbering path: 1. A local attacker creates a symbolic link: ```bash ln -s /path/to/target /tmp/report_data.json ``` 2. The finance-report workflow runs under an account able to write t ...[truncated 1269 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/call_collector.py:35
Finding

Arbitrary collector prompts are transmitted to external LLM providers without data classification or disclosure controls

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (37)

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The core reporting purpose mostly matches: the code does generate a 9-module global finance daily report using external LLMs and supports selective module collection. It also stays within the declared non-advice/reporting domain. However, the description claims additional operational capabilities—module management and setup/install for scheduled daily delivery—that are not present in this code chunk. The code is a standalone CLI collector only; it accepts --date and --module, fetches remote data sources, calls LLM APIs, and emits structured JSON to stdout. It does not implement chat delivery, auto-chunking, persistent configuration, enabling/disabling modules, adding/removing modules, or scheduling/setup flows. Therefore the description overstates the implemented capabilities in a material way.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This code is narrowly focused on editing a finance-report configuration file. That partially aligns with the declared module-management aspect (add/remove/enable/disable/list). However, the declared purpose describes a full finance daily report skill with default modules, external collectors, chat output, and setup/install scheduling behavior. None of those core capabilities are implemented in the supplied code chunk. The primary observed behavior is config mutation via CLI, not report generation. Additionally, the code exposes a 'reorder' command in argparse and in the usage text, but there is no corresponding execution branch, so that advertised capability is absent. Because the declared description materially overstates what this code chunk does, this is a mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill invokes privileged capabilities including cron management, spawning a subagent, reading workflow files, writing reports to disk, and using external collectors, but it declares no explicit tool/permission scope. That increases the blast radius if the skill is triggered unexpectedly or modified later, because the runtime may grant broader access than is necessary for finance reporting.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The setup flow explicitly instructs the agent to use a fixed Chinese greeting and message to the user. This is a natural-language locale policy concern because the skill does not offer the user a language choice or document that the skill is intentionally limited to Chinese-only operation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default configuration ships with a prebuilt module focused on AI agent asset management, investment products, and portfolio-management-adjacent topics even though the skill metadata explicitly says it is not for real-time trading, individual stock analysis, or investment advice. Although disabled by default, including this module expands the skill into a higher-risk financial domain and makes scope creep easier, especially if users enable it without understanding the boundary between news reporting and investment-oriented analysis.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file presents the skill entirely as a Chinese-language prompt template for subagents, including role and output guidance, with no indication that users may choose another language. Under the policy rule, forcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file instructs the agent to perform persistent module-management actions that modify future report behavior, but it provides no requirement to warn the user, confirm destructive changes, or distinguish informational queries from state-changing commands. In a skill that supports natural-language administration, this creates a real risk of unintended or socially engineered configuration changes that persist across future runs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The schema explicitly specifies that the module display name should be Chinese (显示名称(中文)), which imposes a language requirement in the skill's natural-language documentation. This appears to force a specific language without user opt-in or a documented region-specific justification, matching the language/locale policy violation category.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The entire document is written in Chinese and includes Chinese-only source descriptions and instructions, with no indication that language choice is optional or that the skill is intentionally limited to a Chinese-speaking context. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The title and template are written as a fixed Chinese-language daily report format, indicating the skill outputs in Chinese by default. The instructions also prescribe a specific locale/timezone format rather than offering a language or locale choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The template requires timestamps in the Asia/Shanghai timezone, which is a locale constraint. Under the policy, forcing a locale without user choice or clear region-specific justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instruction '所有时间标注 Asia/Shanghai' imposes a fixed locale/timezone on all outputs. The file does not offer an alternative locale or explicit opt-in, which conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The entire skill specification is written as a mandatory Chinese-language workflow and examples, with no indication that users may opt into another language or locale. This creates a natural-language policy concern because it effectively imposes a specific language choice rather than offering flexibility or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This script sends the caller-supplied prompt directly to third-party LLM APIs (DashScope and Volcengine) with no consent gate, redaction, or disclosure mechanism. In a finance reporting skill, prompts may contain proprietary research, internal business context, user identifiers, or scheduled-report configuration details, so silent transmission to external providers creates a real privacy and data-governance risk even if the code is functionally intended.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script sends large amounts of third-party collected content from Jin10, CLS, Eastmoney, and Trading Economics directly to external LLM providers for processing, but there is no user-facing disclosure, consent flow, or data-handling guardrail. In this skill context, that matters because news content, source URLs, and potentially provider-specific licensed content are exfiltrated to external model vendors, creating privacy, compliance, and contractual-use risk even if the data is not obviously secret.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The embedded system prompt instructs the model in Chinese and requires a fixed output behavior without any user opt-in or locale selection mechanism. This enforces a specific language/locale policy in a way that may violate organizational requirements for user choice unless the regional constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The request headers hard-code Accept-Language: zh-CN,zh;q=0.9,en;q=0.8, which explicitly prefers Chinese responses for all fetches. This is a natural-language locale policy concern because the skill imposes a language preference without offering user choice or documenting a justified region-specific requirement.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file-level usage documentation says the script supports reorder --name ... --priority ..., which aligns with the manifest's module management scope. However, although CLI arguments for reorder are defined later, there is no cmd_reorder function and the dispatch logic never handles args.command == "reorder", so the advertised behavior does not occur.

Content

No source excerpt is available for this finding.

Tainted flow: 'config_path' from os.environ.get (line 168, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/manage_modules.py (reported line 140)May include surrounding context.

python
config_path = CONFIG_FILE

    # Append to config
    with open(config_path, "w", encoding="utf-8") as f:
        f.write(raw.rstrip() + "\n" + new_block)

    print(f"✅ 模块已添加:{args.name}")

Tainted flow: 'config_path' from os.environ.get (line 168, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/manage_modules.py (reported line 170)May include surrounding context.

python
config_path = CONFIG_FILE

    # Append to config
    with open(config_path, "w", encoding="utf-8") as f:
        f.write(raw.rstrip() + "\n" + new_block)

    print(f"✅ 模块已添加:{args.name}")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The remove command deletes a module definition from the configuration and immediately writes the modified file back to disk. Although the code prints a success message afterward, there is no confirmation prompt or pre-action warning before this potentially irreversible file modification.

Content

No source excerpt is available for this finding.

Tainted flow: 'config_path' from os.environ.get (line 203, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/manage_modules.py (reported line 186)May include surrounding context.

python
raw = raw.replace(mod["raw"], mod["raw"].replace("enabled: false", "enabled: true"))
            if config_path == DEFAULT_CONFIG:
                config_path = CONFIG_FILE
            with open(config_path, "w", encoding="utf-8") as f:
                f.write(raw)
            print(f"✅ 模块已启用:{args.name}")
            return 0

Tainted flow: 'config_path' from os.environ.get (line 203, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/manage_modules.py (reported line 204)May include surrounding context.

python
raw = raw.replace(mod["raw"], mod["raw"].replace("enabled: false", "enabled: true"))
            if config_path == DEFAULT_CONFIG:
                config_path = CONFIG_FILE
            with open(config_path, "w", encoding="utf-8") as f:
                f.write(raw)
            print(f"✅ 模块已启用:{args.name}")
            return 0

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This Python file contains multiple natural-language strings in Chinese for module names and user-facing recommendations, such as the module labels in the source list and printed guidance like '数据暂缺'. The file does not offer any language selection or document that the skill is intentionally region-specific, which can violate a language/locale policy requiring user choice or justified locale constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The report content is generated with fixed Chinese headings, labels, and narrative markers throughout the script, such as section titles and footer text. Because the file does not provide any user opt-in, language selection, or justification that the skill is intended only for a Chinese-language environment, it appears to enforce a specific locale in violation of the language/locale policy.

Content

No source excerpt is available for this finding.