Back to skill

Security audit

contract-review

Security checks for vulnerabilities and agentic risk

Overview

The skill is largely purpose-aligned, but it can send sensitive contract text or metadata to configurable external endpoints and stores review data locally with limited controls.

Review this carefully before installing for confidential contracts. Prefer --no-llm or local Ollama for sensitive documents, verify OPENAI_API_BASE before each remote review, avoid configuring webhooks unless the URL is trusted, and periodically inspect or clear ~/.contract-review because it stores review history, ledger/config data, and indexes.

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

Error
Location
scripts/contract_ledger.py:462
Finding
Unrestricted webhook destination permits SSRF and disclosure of confidential contract metadata## Vulnerability Details **File Location**: `scripts/contract_ledger.py:462-489`, `scripts/contract_ledger.py:505-511`, `scripts/contract_ledger.py:552-554`, and `scripts/contract_ledger.py:631-632` **Vulnerability Type**: Server-Side Request Forgery and sensitive-data disclosure **Risk Level**: High ### Vulnerable Code ```python def send_wecom_webhook(self, message: str, webhook_url: str) -> bool: """ Send a WeCom webhook notification. """ try: import urllib.request payload = json.dumps({ 'msgtype': 'markdown', 'markdown': { 'content': message, }, }).encode('utf-8') req = urllib.request.Request( webhook_url, data=payload, headers={'Content-Type': 'application/json'}, ) with urllib.request.urlopen(req, timeout=10) as resp: result = json.loads(resp.read().decode('utf-8')) if result.get('errcode') == 0: logger.info("WeCom notification succeeded") return True else: logger.warning(f"WeCom notification failed: {result}") return False except Exception as e: logger.error(f"WeCom notification failed: {e}") return False ``` ```python def save_config(self, config: Dict): """Save configuration.""" with open(CONFIG_PATH, 'w', encoding='utf-8') as f: json.dump(config, f, ensure_ascii=False, indent=2) ``` ```python webhook_url = config.get('webhook_url', '') if webhook_url: ledger.send_wecom_webhook(message, webhook_url) ``` ```python if args.webhook: config['webhook_url'] = args.webhook ``` ### Technical Analysis The webhook URL is accepted from the command line, stored persistently, and later passed directly to `urllib.request.urlopen`. The implementation does not validate ...[truncated 2436 chars]
Remediation
## Remediation Suggestions 1. Restrict webhook destinations to HTTPS. 2. Allowlist the exact official WeCom webhook hostname or hostname suffix required by the feature. 3. Reject URLs containing embedded credentials, fragments, unsupported ports, or malformed hostnames. 4. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges for both IPv4 and IPv6. 5. Disable redirects or validate every redirect target using the same security policy. 6. Present the normalized destination and a preview of the transmitted fields before enabling notifications. 7. Require explicit confirmation when changing an existing webhook destination. 8. Store webhook secrets using an operating-system credential store rather than a plaintext JSON file. 9. Add an option to omit or redact contract numbers, counterparties, and amounts from notifications. 10. Log only the destination hostname, never the complete webhook URL because it may contain a secret token. 11. Add automated tests covering localhost, private IP addresses, IPv6 literals, DNS rebinding-resistant resolution, redirects, non-HTTPS schemes, and deceptive hostnames.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/llm_review.py:167
Finding
Default LLM workflow can transmit contract contents and API credentials to an untrusted configurable endpoint## Vulnerability Details **File Location**: `scripts/llm_review.py:167-169` and `scripts/llm_review.py:332-367`; default invocation occurs at `scripts/main.py:311-312` and `scripts/main.py:537-549` **Vulnerability Type**: Sensitive-data exposure through an unvalidated external API endpoint **Risk Level**: Medium ### Vulnerable Code ```python self.api_key = api_key or os.environ.get('OPENAI_API_KEY', '') self.model = model or os.environ.get('OPENAI_MODEL', 'gpt-4') self.api_base = api_base or os.environ.get( 'OPENAI_API_BASE', 'https://api.openai.com/v1' ) ``` ```python def _call_openai(self, system_prompt: str, user_prompt: str) -> str: """Call an OpenAI-compatible API.""" try: from openai import OpenAI client = OpenAI( api_key=self.api_key, base_url=self.api_base, timeout=self.timeout, ) response = client.chat.completions.create( model=self.model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], temperature=0.3, max_tokens=4000, ) return response.choices[0].message.content except ImportError: pass url = f"{self.api_base}/chat/completions" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } data = { "model": self.model, "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], "temperature": 0.3, "max_tokens": 4000, } resp = requests.post( url, headers=headers, json=data, timeout=self.timeout, ) resp.raise_for_status() return resp.json()["choices"][0]["message"]["cont ...[truncated 3678 chars]
Remediation
## Remediation Suggestions 1. Make rule-only or local-only review the default. 2. Require an explicit option such as `--remote-llm` before any contract text is sent externally. 3. Before every remote review, display the provider hostname, model, amount of text being transmitted, and categories of potentially sensitive data. 4. Require affirmative per-run consent unless the user has deliberately configured a documented enterprise policy. 5. Restrict endpoints to HTTPS and validate certificates normally. 6. Maintain an allowlist of approved API hosts, or require explicit enrollment and confirmation for custom OpenAI-compatible endpoints. 7. Never attach the API key until the destination has passed validation. 8. Warn or fail closed when `OPENAI_API_BASE` differs from the expected provider while a provider-specific credential is being used. 9. Add configurable redaction for personal identifiers, bank details, pricing, signatures, and other sensitive fields before transmission. 10. Provide a clear local Ollama option that does not probe or use remote services. 11. Avoid logging prompts, API keys, full endpoint URLs containing credentials, or raw model responses with sensitive content. 12. Add tests proving that an unapproved endpoint cannot receive either contract text or authorization credentials.
Vulnerability Patterns
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (181)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding identifies undeclared remote update checks and local persistence of update/reminder state, which are security-relevant side effects beyond core contract analysis. In a contract-review skill, unsolicited network access and stateful tracking increase the risk of metadata leakage, supply-chain exposure, and user surprise, especially when paired with sensitive legal documents.

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
查看行业清单:`python scripts/main.py --list-industries`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

eval() call detected

High
Category
Dangerous Code Execution
Content
return None

        try:
            result = eval(expr, {'__builtins__': {}}, {})
            return float(result)
        except Exception:
            return None
Confidence
97% confidence
Finding
The code evaluates a dynamically constructed expression using eval() after doing string replacement on variable names. Although it attempts to restrict inputs with a regex and removes __builtins__, eval remains unsafe here because expression construction is text-based, variable substitution is not token-aware, and future changes or unexpected inputs could turn this into code execution or logic-manipulation risk. In a contract-review skill that processes untrusted document content and potentially user-supplied rules, this is especially dangerous because attacker-controlled fields or rules may reach the evaluator.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
# 模板中 JSON 示例使用 {{ }} 转义,此处还原为单层大括号
        if '{{' in prompt or '}}' in prompt:
            prompt = prompt.replace('{{', '{').replace('}}', '}')
        return prompt
    
    def _build_industry_suffix(self, industry: str) -> str:
        """v4.0 构建行业专项审查提示词补充段"""
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Static analysis

Detected: suspicious.dynamic_code_execution, suspicious.obfuscated_code

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/amount_validator.py:442

Potential obfuscated payload detected.

Warn
Code
suspicious.obfuscated_code
Location
scripts/extract_text.py:26