Back to skill

Security audit

Patent Fee Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned for patent fee monitoring, but it automatically uses external patent services and persists or exports sensitive IP records without enough user-control safeguards.

Review before installing if your patent portfolio, filing strategy, owners, notes, or reminder dates are sensitive. Use it only with data you are comfortable storing locally in the skill directory and sending as patent lookups to public patent services, and be cautious opening exported CSV or .ics files until export escaping is fixed.

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

Warning
Location
main.py:902
Finding
Spreadsheet Formula Injection in CSV Exports<![CDATA[ ## Vulnerability Details **File Location**: `main.py:902-927` and `main.py:985-1002` **Vulnerability Type**: CSV/spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python def import_csv(csv_content: str) -> Tuple[int, List[str]]: """Import IP assets from CSV content.""" lines = csv_content.strip().split('\n') reader = csv.DictReader(io.StringIO(csv_content)) success = 0 errors = [] for row_num, row in enumerate(reader, start=2): if not row.get('ip_no', '').strip(): errors.append(f"Row {row_num} is missing ip_no") continue try: add_asset({ 'ip_no': row.get('ip_no', ''), 'title': row.get('title', ''), 'type': row.get('type', 'patent'), 'sub_type': row.get('sub_type', 'invention'), 'country': row.get('country', 'CN'), 'filing_date': row.get('filing_date', ''), 'grant_date': row.get('grant_date', ''), 'next_fee_date': row.get('next_fee_date', ''), 'status': row.get('status', 'Unknown'), 'owner': row.get('owner', ''), 'notes': row.get('notes', ''), }) success += 1 except Exception as e: errors.append(f"Import failed on row {row_num}: {e}") return success, errors ``` ```python def export_assets_csv() -> str: """Export the IP asset ledger as CSV.""" assets = load_assets() if not assets: return "No IP asset data" output = io.StringIO() fieldnames = ['ip_no', 'title', 'type', 'sub_type', 'country', 'filing_date', 'grant_date', 'next_fee_date', 'status', 'owner', 'inventor', 'notes'] writer = csv.DictWriter(output, fieldnames=fieldnames) writer.writeheader() for asset in assets: writer.writerow({k: asset.get(k, '') for k in fieldnames}) return outp ...[truncated 2644 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Neutralize formula-prefixed values before writing any user-controlled field to CSV: ```python def sanitize_csv_cell(value: Any) -> str: text = '' if value is None else str(value) if text.startswith(('=', '+', '-', '@')): return "'" + text return text ``` Apply it to every exported field: ```python for asset in assets: writer.writerow({ key: sanitize_csv_cell(asset.get(key, '')) for key in fieldnames }) ``` 2. Account for leading whitespace and control characters that may be ignored by spreadsheet clients. A stricter implementation should detect formula prefixes after tabs, carriage returns, line feeds, or leading spaces. 3. Apply protection at export time even if validation is also added during import. Stored records may originate from other interfaces or pre-existing JSON data. 4. Document that exported files can contain user-controlled content and should be opened using protected-view settings. 5. Add regression tests covering values beginning with `=`, `+`, `-`, `@`, tab characters, carriage returns, and line feeds. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
main.py:649
Finding
iCalendar Property Injection Through Unescaped Asset Data<![CDATA[ ## Vulnerability Details **File Location**: `main.py:649-693` **Vulnerability Type**: iCalendar content and property injection **Risk Level**: Medium ### Vulnerable Code ```python def _generate_ics_content(patent_no: str, title: str, due_date_str: str, fee_amount: str = '', notes: str = '') -> str: """ Generate iCalendar text content. """ from datetime import timezone now = datetime.now(timezone.utc) due_dt = datetime.strptime(due_date_str, '%Y-%m-%d') due_dt_utc = due_dt.replace(tzinfo=timezone.utc) description = f"Patent fee deadline reminder - {patent_no}" if fee_amount: description += f"\\nAmount due: {fee_amount}" if notes: description += f"\\nNotes: {notes}" description += "\\n\\nPay the fee before the deadline to avoid surcharges." alarm_due = due_dt_utc - timedelta(days=7) ics = f"""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//PatentFeeMonitor//CN CALSCALE:GREGORIAN METHOD:PUBLISH BEGIN:VEVENT UID:{patent_no}@{due_date_str} DTSTAMP:{now.strftime('%Y%m%dT%H%M%SZ')} DTSTART;VALUE=DATE:{due_dt.strftime('%Y%m%d')} DTEND;VALUE=DATE:{due_dt.strftime('%Y%m%d')} SUMMARY:Patent fee deadline - {title} DESCRIPTION:{description} CATEGORIES:Patent fee BEGIN:VALARM TRIGGER:-P7D ACTION:DISPLAY DESCRIPTION:Patent fee deadline approaching END:VALARM END:VEVENT END:VCALENDAR""" return ics ``` The displayed English literals are translations of the original user-facing text. The vulnerable interpolation behavior is unchanged: `title`, `notes`, and related values are inserted directly into iCalendar properties. ### Technical Analysis RFC 5545 requires special characters in text properties to be escaped. In particular, backslashes, commas, semicolons, and line breaks require appropriate encoding or escaping. Long content lines must also be folded correctly. The function directly interpolates the stored `title` into `SUMMARY` and `notes` into `DESCRIPTION`. It does ...[truncated 2197 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape all user-controlled RFC 5545 text values before interpolation: ```python def escape_ical_text(value: Any) -> str: text = '' if value is None else str(value) text = text.replace('\\', '\\\\') text = text.replace('\r\n', '\\n') text = text.replace('\r', '\\n') text = text.replace('\n', '\\n') text = text.replace(';', '\\;') text = text.replace(',', '\\,') return text ``` Use this function for `title`, `notes`, `fee_amount`, `patent_no`, and every other value placed in an iCalendar text property. 2. Reject unexpected control characters before generating the file. Do not permit raw CR or LF characters to reach an iCalendar property. 3. Validate identifiers used in `UID` separately because escaping rules for identifiers differ from ordinary text properties. 4. Implement RFC 5545 line folding so content lines longer than 75 octets are folded correctly. 5. Prefer a maintained iCalendar library that handles escaping, property serialization, date formatting, and line folding. 6. Add tests containing CRLF injection, commas, semicolons, backslashes, Unicode content, long lines, and attempted `BEGIN:VEVENT` or `BEGIN:VALARM` injection. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (15)

Hidden Instructions

High
Category
Prompt Injection
Content
ip_no,title,type,sub_type,country,filing_date,grant_date,next_fee_date,status,owner,inventor,notes
CN202310123456.X,一种智能温控系统,patent,invention,CN,2023-01-15,2023-08-20,2026-08-20,专利权维持,张三科技,,
US12345678B2,Method for data processing,patent,invention,US,2022-06-10,2023-12-05,2025-06-05,Patented Case,Innovation Inc.,,
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill describes capabilities that imply network access plus file read/write behavior, but it does not declare any explicit tool scope or permissions boundary. This creates ambiguity about what the agent may access and makes it easier for the skill to overreach at runtime, especially when handling imported CSVs, exports, or external patent lookups.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger phrases are broad enough to match generic requests like '管理我的IP资产' or '生成日历提醒', which can cause the skill to activate in contexts the user did not intend. Over-broad invocation increases the chance of unnecessary external queries or file operations being performed on potentially sensitive intellectual property data.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill states that it will query multiple third-party patent data sources, but it does not disclose that patent identifiers and related metadata may be transmitted externally. Even if patent records are public, a user's monitoring targets, portfolio composition, and lookup patterns can still reveal sensitive business strategy or ongoing filing activity.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill offers CSV and iCalendar export features but does not warn users that sensitive IP asset information may be written to local files. This can lead to unintentional disclosure of patent portfolios, deadlines, and ownership metadata if files are stored in insecure locations or shared accidentally.

External Transmission

Medium
Category
Data Exfiltration
Content
return None
        app_number = numbers[0]
        
        url = "https://api.uspto.gov/api/v1/patent/applications/search"
        headers = {
            'Content-Type': 'application/json',
            'X-API-Key': api_key
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"limit": 1,
            "offset": 0
        }
        resp = requests.post(url, headers=headers, json=payload, timeout=15)
        
        if resp.status_code != 200:
            return None
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill persists the IP asset ledger to `ip_assets.json` on local disk without clear user disclosure, even though the ledger can contain sensitive business metadata such as owners, inventors, filing dates, notes, and future fee dates. Silent persistence increases the risk of unintended retention, later exposure to other local users/processes, and compliance issues where users expect ephemeral skill behavior.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill automatically performs network lookups for user-supplied patent numbers via external services when `search_patent()` calls `monitor_patent_fee(..., auto_query=True)`, but the user-facing interface does not clearly disclose that data will leave the local environment. Even if patent numbers are often public, user-entered IP portfolio context and query timing can still reveal sensitive business interests, filing strategy, or confidential asset tracking activity.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The file presents the skill description, examples, and instructions only in Chinese, which can amount to a language-policy issue when no user opt-in or locale limitation is stated. There is no indication that the skill is intentionally restricted to Chinese-speaking users or a China-only deployment context.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
This file contains natural-language values in multiple languages, including Chinese and English, but provides no indication of a user-selected locale or documented language policy. Under the policy-violation category, forcing or assuming a locale without opt-in can be problematic when the file is part of a skill's user-facing behavior or processing expectations.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
This JSON asset file mixes Chinese and English natural-language values for similar fields, such as status at L12 ('专利权维持') and L29 ('Patented Case'). For a skill consuming this file, the data effectively enforces inconsistent locale behavior without any visible user opt-in or documented locale policy, which can violate language/locale consistency requirements.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The file contains user-facing natural-language fields in both Chinese and English, such as Chinese headers/values and English patent descriptors, with no indication of locale selection or user opt-in. This can conflict with language policy expectations when a skill output or bundled artifact implicitly forces mixed-language content.

Missing User Warnings

Low
Confidence
88% confidence
Finding
Generating calendar reminders writes a `.ics` file to disk under a local `calendar/` directory without prior warning. This is lower severity than ledger persistence, but it still creates an undeclared local artifact containing potentially sensitive patent identifiers, dates, and notes that may be accessible to other users or tools on the system.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The only natural-language content in this file is written exclusively in Chinese, which may indicate a language-specific constraint without any user choice or justification. Under the policy rules, language-only instructions can be a violation when they implicitly force a specific language or locale.

Static analysis

No suspicious patterns detected.