Back to skill

Security audit

Contract Risk Helper

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local contract-risk checker whose behavior matches its stated purpose and shows no evidence of hidden data access, network use, persistence, or destructive actions.

Use this for preliminary contract risk spotting only. It appears to process text locally without uploading or storing it, but users should still avoid treating its output as legal advice and should be aware that general contract-review prompts may invoke it.

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

Note
Location
handler.py:333
Finding
Unvalidated Handler Input Causes Invocation Failure## Vulnerability Details **File Location**: `handler.py:333-334` **Vulnerability Type**: Improper input type validation **Risk Level**: Low ### Vulnerable Code ```python contract_text = skill_input.get("contract_text", "") if not contract_text or not contract_text.strip(): ``` ### Technical Analysis The public `handle()` entry point assumes that `skill_input` is a dictionary and that its `contract_text` member is a string. It invokes `.get()` and `.strip()` before validating either type. Although the lower-level `scan()` function checks whether its input is a string, execution does not reach that validation when `contract_text` is a truthy non-string value. Similarly, passing a non-dictionary as `skill_input` fails at the `.get()` call. No input schema or equivalent type enforcement is declared in `skill.json`. Consequently, malformed or adversarial input can raise an uncaught `AttributeError` and terminate the invocation. ### Attack Path 1. An attacker or malformed integration invokes the Skill with a non-string value, such as `{"contract_text": 1}`. 2. `handle()` retrieves the integer through `skill_input.get()`. 3. Because the integer is truthy, evaluation proceeds to `contract_text.strip()`. 4. The integer has no `.strip()` method, causing an uncaught `AttributeError`. 5. The current Skill invocation fails instead of returning a structured validation error. A similar failure occurs if the top-level input is not a dictionary, because `.get()` is called without first validating `skill_input`. ### Impact Assessment Exploitation can cause application-level denial of service for the affected invocation and may produce repeated failures if an upstream caller retries malformed requests. The flaw does not grant additional privileges and provides no demonstrated path to command execution, data disclosure, network access, persistence, or cross-session compromise. Its scope is limited to availability and error handli ...[truncated 83 chars]
Remediation
## Remediation Suggestions Validate both the top-level input and the contract text before invoking type-specific methods: ```python def handle(skill_input: dict) -> dict: if not isinstance(skill_input, dict): return { "ok": False, "error": "Invalid input: an object is required." } contract_text = skill_input.get("contract_text", "") if not isinstance(contract_text, str): return { "ok": False, "error": "Invalid contract text: a string is required." } if not contract_text.strip(): return { "ok": False, "error": "No contract text was provided." } results = scan(contract_text) output = format_results(results) # Continue constructing the successful response. ``` Also apply a documented maximum input length to limit excessive CPU and memory consumption, declare an input schema if supported by the Skill platform, and add tests for non-dictionary input, `None`, integers, lists, nested objects, and oversized strings.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger list includes broad, everyday phrases such as '帮我看合同' and '合同检查', which can cause the skill to activate on general contract-related requests rather than explicit invocation. Over-broad activation is dangerous because it can hijack unrelated conversations, produce unsolicited legal-style guidance, and increase the chance that sensitive contract text is routed into this skill unexpectedly.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The handler docstring declares a `language` field, but the implementation never reads it and unconditionally formats results in both Chinese and English. This imposes a specific locale/output style regardless of user preference, which matches the policy concern about forcing language behavior without opt-in.

Intent-Code Divergence

Low
Confidence
78% confidence
Finding
The docstring at L271 describes the function as a straightforward scan for risk patterns, but the code later skips matches whose suggestion fields are empty. In particular, the confidentiality return/destroy pattern is matched yet deliberately omitted, so the implementation does not fully reflect the apparent scanning behavior described in the documentation.

Static analysis

No suspicious patterns detected.