Back to skill

Security audit

patent-asset-grading

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a coherent patent-rating workflow that uses patent lookups and local report generation for its stated purpose, with some reliability and dependency hygiene caveats.

Before installing, confirm you are comfortable authorizing the Zhihuiya/PatSnap MCP service to retrieve the patent data you submit. Keep patent batches small, use a controlled Python environment with reviewed dependency versions, and treat the generated asset grades as decision-support rather than legal or valuation advice.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/grading_pipeline.py:806
Finding

Batch Size Limit Is Documented but Not Enforced

Content
View full analysis

Vulnerability Details

File Location: scripts/grading_pipeline.py, lines 806–821
Vulnerability Type: Unbounded input processing and resource exhaustion
Risk Level: Medium

Vulnerable Code

python
# Collect patent numbers
patent_numbers = []
if args.patents:
    patent_numbers.extend(args.patents)
if args.patents_file:
    with open(args.patents_file, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if line and not line.startswith("#"):
                patent_numbers.extend(
                    [p.strip() for p in line.replace(",", " ").split() if p.strip()]
                )

if not patent_numbers:
    parser.print_help()
    sys.exit(0)

patent_numbers = list(dict.fromkeys(patent_numbers))

The skill documentation states that each batch is limited to 50 patents, but the CLI does not enforce that restriction. Every supplied identifier is loaded into memory, deduplicated, processed, retained in the results list, and subsequently written into a Word or Excel document.

Technical Analysis

An attacker or untrusted user can provide a --patents-file containing an arbitrarily large number of entries. The program reads the entire list and performs grading for every unique value. The resulting memory, CPU, document-generation, and disk usage scale with the number of entries.

The risk is amplified because run_grading() accumulates every generated result in memory before creating the output document. Word and Excel generation also creates a large in-memory document structure. This can exhaust the agent worker's memory or consume excessive CPU and disk space.

The limit described in SKILL.md is therefore only advisory and does not establish a security boundary.

Attack Path

  1. An attacker submits or references a patent list containing hundreds of thousands or millions of unique identifiers.
  2. The agent invokes the script with --patents-file or passes the identifiers through `--p ...[truncated 849 chars]
Remediation
View remediation

Remediation Suggestions

Enforce the documented limit after combining and deduplicating all input sources:

python
MAX_PATENTS = 50

patent_numbers = list(dict.fromkeys(patent_numbers))
if len(patent_numbers) > MAX_PATENTS:
    parser.error(
        f"A maximum of {MAX_PATENTS} unique patent numbers is allowed per batch."
    )

Additional hardening should include:

  1. Limit the size of --patents-file before reading it.
  2. Reject excessively long patent identifiers and validate their format.
  3. Stream input records rather than loading an unbounded file into memory.
  4. Apply output-size, execution-time, memory, and disk quotas.
  5. Enforce the same limit inside run_grading() so callers cannot bypass the CLI validation.
  6. Rate-limit or budget MCP requests independently of the number of supplied identifiers.
  7. Add tests for 0, 1, 50, and 51 identifiers, as well as oversized input files.

T08 · Insecure Dependencies

Note
Location
scripts/grading_pipeline.py:462
Finding

Third-Party Installation Guidance Does Not Pin Dependency Versions or Verify Integrity

Content
View full analysis

Vulnerability Details

File Location: scripts/grading_pipeline.py, lines 462–470; additional occurrence at lines 623–633
Vulnerability Type: Unpinned third-party dependencies
Risk Level: Low

Vulnerable Code

python
def export_excel(results: list[dict], output_path: str) -> str:
    """将评审结果输出为格式化Excel文件。"""
    try:
        import openpyxl
        from openpyxl.styles import (Font, PatternFill, Alignment,
                                      Border, Side, numbers)
        from openpyxl.utils import get_column_letter
    except ImportError:
        print("[ERROR] 缺少 openpyxl,请执行:pip install openpyxl", file=sys.stderr)
        sys.exit(1)

A corresponding Word-export error directs the operator to install python-docx without a pinned version or integrity hash.

Technical Analysis

The project does not include a lock file or hash-verified dependency manifest. When a dependency is unavailable, it instructs the operator to install the latest package selected by the configured Python package index.

The package names are legitimate and the script does not automatically execute pip, so this is not direct remote code execution by itself. However, installation behavior can vary over time and between environments. If an index, mirror, package maintainer account, DNS path, or local package-index configuration is compromised, the installation can retrieve attacker-controlled package code.

Python packages can execute code during build or installation, and imported package modules execute with the privileges of the Python process. Consequently, dependency installation and subsequent import form a supply-chain execution path that is not reproducible or integrity-verified.

Attack Path

  1. The target environment lacks openpyxl or python-docx.
  2. The script displays an installation command without a version constraint or hash.
  3. An operator or automated setup process runs that command against a compromised or untrusted package index ...[truncated 1195 chars]
Remediation
View remediation

Remediation Suggestions

  1. Add a version-controlled dependency manifest with reviewed, exact versions.
  2. Generate and verify cryptographic hashes for all distributions, including transitive dependencies.
  3. Use a lock-file-capable dependency workflow and update dependencies through a controlled review process.
  4. Install only from an approved HTTPS package index or internal artifact repository.
  5. Prefer prebuilt, reviewed environments rather than instructing users to install packages interactively.
  6. Replace generic instructions with a project-specific command, for example:
text
python -m pip install --require-hashes -r requirements.txt
  1. Run dependency vulnerability and provenance checks in continuous integration.
  2. Execute report generation in a least-privileged, isolated environment without unnecessary credentials.
  3. Document supported dependency versions and periodically update them after security review.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The entire skill description, triggers, input example, and usage instructions are written only in Chinese, which implies a fixed language requirement for use. The file does not offer multilingual support, user opt-in, or a documented justification that this is a region-specific or Chinese-only skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains user-facing natural-language descriptions exclusively in Chinese, including the module docstring and operational descriptions. The policy requires flagging language or locale constraints when a skill forces a specific language without user opt-in, and there is no indication that users may choose another language or that the locale restriction is justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documented Markdown fallback parser is broken because parse_patent_markdown() calls extract(..., flags=re.MULTILINE), but the nested extract() helper does not accept a flags parameter. When the primary title regex does not match and execution reaches the fallback branch, the function can raise a TypeError, causing grading to fail on crafted or merely unexpected Markdown input. In this skill’s context, the issue is primarily a denial-of-service/reliability flaw rather than code execution or data exfiltration.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.