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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
查看行业清单:`python scripts/main.py --list-industries`

eval() call detected

High
Category
Dangerous Code Execution
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.

Content

Scanner excerpt · scripts/amount_validator.py (reported line 442)May include surrounding context.

python
return None

        try:
            result = eval(expr, {'__builtins__': {}}, {})
            return float(result)
        except Exception:
            return None

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/llm_review.py (reported line 302)May include surrounding context.

python
# 模板中 JSON 示例使用 {{ }} 转义,此处还原为单层大括号
        if '{{' in prompt or '}}' in prompt:
            prompt = prompt.replace('{{', '{').replace('}}', '}')
        return prompt
    
    def _build_industry_suffix(self, industry: str) -> str:
        """v4.0 构建行业专项审查提示词补充段"""