Back to skill

Security audit

Report Processor

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local research-report processor, but users should be careful with sensitive reports and AI-generated investment summaries.

Install only if you are comfortable processing reports through your local Ollama setup and storing extracted results persistently under ~/.openclaw/workspace/data/reports/. Do not treat the generated investment advice or extracted figures as authoritative without human review, especially for reports from untrusted sources.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/report_processor.py:54
Finding
Untrusted Report Content Can Manipulate Model-Generated Analysis## Vulnerability Details **File Location**: `scripts/report_processor.py`, lines 54–95 **Vulnerability Type**: Prompt injection with insufficient output validation **Risk Level**: Medium ### Vulnerable Code ```python def extract_with_ollama(text, prompt): """使用 Ollama 模型提取信息""" full_prompt = f""" {prompt} 请从以下研报内容中提取信息: --- {text[:50000]} # 限制输入长度 --- 请以 JSON 格式返回结果,包含以下字段: - core_points: 核心观点(数组) - key_data: 关键数据(对象) - investment_advice: 投资建议(字符串) - risk_warnings: 风险提示(数组) """ try: result = subprocess.run( ['ollama', 'run', OLLAMA_MODEL, full_prompt], capture_output=True, text=True, timeout=180, env={**os.environ, 'OLLAMA_HOST': '127.0.0.1:11434'} ) if result.returncode == 0: return result.stdout, None else: return None, f"Ollama 错误: {result.stderr}" except subprocess.TimeoutExpired: return None, "处理超时" except Exception as e: return None, str(e) def parse_json_response(response_text): """解析模型返回的 JSON 响应""" try: # 尝试找到 JSON 块 import re json_match = re.search(r'\{.*\}', response_text, re.DOTALL) if json_match: return json.loads(json_match.group()) except: pass return None ``` ### Technical Analysis The processor interpolates up to 50,000 characters of attacker-controlled report text directly into the Ollama prompt. Although delimiter lines visually separate the report from the surrounding instructions, the prompt does not explicitly identify the document as untrusted data or instruct the model to ignore commands contained within it. A malicious TXT, Markdown, or PDF report can therefore contain instructions that ask the model to disregard the intended extraction task and return fabricated core points, financial data, investment advice, or risk warni ...[truncated 2121 chars]
Remediation
## Remediation Suggestions 1. Treat all extracted report text as untrusted content. Add explicit instructions stating that text inside the document is data only and that any commands, role changes, or output-format instructions within it must be ignored. 2. Use the model runtime's structured-output or JSON-schema capability where available instead of extracting an arbitrary JSON-looking substring with a regular expression. 3. Validate the parsed result against a strict schema: - Require exactly the intended fields. - Enforce arrays for `core_points` and `risk_warnings`. - Enforce an object for `key_data`. - Enforce a string for `investment_advice`. - Reject unknown keys, excessive lengths, invalid nesting, and malformed values. 4. Replace the greedy `r'\{.*\}'` extraction with a robust structured-response parser. Reject responses containing surrounding instructions, multiple objects, or non-JSON content. 5. Require generated claims to include source quotations or page references and verify that cited text occurs in the extracted report. 6. Mark all model-generated output as untrusted before it enters a knowledge base or decision-making workflow. Apply human review for investment recommendations or other high-impact uses. 7. Add adversarial tests containing embedded prompt-injection phrases in every supported input format and verify that the model continues to follow only the processor's extraction policy.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Env Variable Harvesting

High
Category
Data Exfiltration
Content
result = subprocess.run(
            ['ollama', 'run', OLLAMA_MODEL, full_prompt],
            capture_output=True, text=True, timeout=180,
            env={**os.environ, 'OLLAMA_HOST': '127.0.0.1:11434'}
        )
        
        if result.returncode == 0:
Confidence
60% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# macOS
brew install poppler
# Linux
sudo apt install poppler-utils
```

## Usage
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# PDF 文件需要 pdftotext
    elif path.suffix.lower() == '.pdf':
        try:
            result = subprocess.run(
                ['pdftotext', str(path), '-'],
                capture_output=True, text=True, timeout=60
            )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""
    
    try:
        result = subprocess.run(
            ['ollama', 'run', OLLAMA_MODEL, full_prompt],
            capture_output=True, text=True, timeout=180,
            env={**os.environ, 'OLLAMA_HOST': '127.0.0.1:11434'}
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script sends up to 50,000 characters of report content to a local Ollama service without any consent, warning, or data-classification check. Even if hosted on localhost, this can expose sensitive financial research to another service boundary, logs, plugins, model storage, or a misconfigured remote-backed Ollama instance.

Natural-Language Policy Violations

Low
Confidence
72% confidence
Finding
The title and feature description mix English with Chinese output field examples such as `core观点` and `投资建议`, which suggests the skill may expect or produce Chinese-language content by default. The file does not clarify whether language is configurable or whether the skill is intended only for Chinese-language research reports.

Missing User Warnings

Low
Confidence
94% confidence
Finding
The skill explicitly states that results are written to `~/.openclaw/workspace/data/reports/`, but it does not warn users that this is a persistent location under their home directory. That can lead to unintended retention of potentially sensitive research-report contents, especially if users assume outputs are temporary or local to the current project folder.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
Natural-language strings throughout the file, including the top-level description and extraction prompt, assume Chinese as the required interaction language. There is no indication that users may opt into another language or that the locale restriction is explicitly justified as region-specific.

Static analysis

No suspicious patterns detected.