Back to skill

Security audit

audit-catalyst-experimental-methods-rd

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local report generator for catalyst-method review, with no evidence of hidden exfiltration, persistence, or unrelated authority.

Install only if you are comfortable running a local Python report generator on your own catalyst-method files. Use a dedicated output directory, avoid hostile or unusually large DOCX inputs, and do not authorize external patent or scientific services for confidential material unless you intend to share that material.

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

Warning
Location
scripts/run_audit.py:194
Finding

Unbounded DOCX Decompression and XML Parsing Can Cause Denial of Service

Content
View full analysis

Vulnerability Details

File Location: scripts/run_audit.py:194-200
Additional Location: scripts/validate_outputs.py:24-28
Vulnerability Type: Uncontrolled resource consumption during archive decompression and XML parsing
Risk Level: Medium

Vulnerable Code

From scripts/run_audit.py:

python
def read_docx_text(path: Path) -> str:
    """Read DOCX text using only Python standard library."""
    ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}
    try:
        with zipfile.ZipFile(path) as zf:
            xml_data = zf.read("word/document.xml")
    except Exception as exc:
        raise RuntimeError(f"Unable to read the Word document; confirm that it is a valid .docx file: {exc}") from exc
    root = ET.fromstring(xml_data)

The same unsafe processing pattern occurs in scripts/validate_outputs.py:

python
def read_docx_text(path: Path) -> str:
    """Extract paragraph text from a valid DOCX package."""
    namespace = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}
    with zipfile.ZipFile(path) as archive:
        xml_data = archive.read("word/document.xml")
    root = ET.fromstring(xml_data)

Technical Analysis

A DOCX file is a ZIP archive. Both processing paths call ZipFile.read() on word/document.xml, causing the complete compressed entry to be decompressed into memory. The code does not enforce limits on:

  • Overall input size
  • Declared or actual uncompressed entry size
  • Compression ratio
  • XML depth or element count
  • Parsing memory or CPU consumption
  • Processing duration

An attacker able to supply a DOCX file can construct an archive whose word/document.xml is very small when compressed but expands to a very large payload. The expanded data is then retained in memory and passed to xml.etree.ElementTree.fromstring(), which can further consume substantial memory and CPU while building the complete XML tree.

The issue affects both initial DOCX input ...[truncated 1795 chars]

Remediation
View remediation

Remediation Suggestions

  1. Enforce an input-file size limit before opening the archive.

    python
    MAX_DOCX_SIZE = 20 * 1024 * 1024
    if path.stat().st_size > MAX_DOCX_SIZE:
        raise RuntimeError("DOCX exceeds the permitted input size.")
    
  2. Inspect ZIP metadata before decompressing any entry. Retrieve ZipInfo for word/document.xml and reject entries whose declared uncompressed size exceeds a conservative limit.

    python
    MAX_XML_SIZE = 50 * 1024 * 1024
    MAX_COMPRESSION_RATIO = 100
    
    info = zf.getinfo("word/document.xml")
    if info.file_size > MAX_XML_SIZE:
        raise RuntimeError("DOCX document XML exceeds the permitted size.")
    
    compressed_size = max(info.compress_size, 1)
    if info.file_size / compressed_size > MAX_COMPRESSION_RATIO:
        raise RuntimeError("DOCX contains a suspicious compression ratio.")
    
  3. Read decompressed content through a bounded stream. Do not rely exclusively on attacker-controlled ZIP metadata. Read at most MAX_XML_SIZE + 1 bytes and reject the document if the bound is exceeded.

    python
    with zf.open(info) as source:
        xml_data = source.read(MAX_XML_SIZE + 1)
    if len(xml_data) > MAX_XML_SIZE:
        raise RuntimeError("DOCX document XML exceeds the permitted size.")
    
  4. Apply archive-wide controls. Limit the number of entries, cumulative uncompressed size, individual entry size, and compression ratio. Reject encrypted entries, malformed paths, and unsupported compression methods where appropriate.

  5. Constrain XML complexity. Prefer bounded or streaming parsing and impose reasonable limits on nesting depth, element count, text length, and total parsed content.

  6. Use runtime isolation. Process untrusted documents in a worker with explicit memory, CPU, and wall-clock limits. Terminate the worker when those limits are exceeded.

  7. Use one hardened helper in both scripts. Replace the duplicated DOCX-reading implementat ...[truncated 314 chars]

Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python scripts/run_audit.py --input <input_file_or_transcription> --out outputs

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This markdown file includes natural-language statements that the complete skill package was localized into "international scientific English." For all file types, forcing a specific language without user opt-in can violate locale policy, and the changelog does not mention any user language choice or region-specific justification.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill instructs the agent to read inputs, generate reports, and validate outputs, which implies file read/write capability, but it does not declare an explicit tool scope such as allowed-tools or permissions. That omission can lead to over-broad filesystem access at runtime, increasing the risk of unintended reading or writing beyond the intended input and output directories, especially because the skill is designed to handle confidential experimental material.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Line L3 explicitly instructs the skill to use 'precise, restrained, evidence-calibrated English.' This is a natural-language locale constraint, and the file does not provide an opt-in, alternative language option, or justification for enforcing English-only output.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The indicator phrases for scientific-paper methods are broad enough that unrelated text containing section-like headings such as 'Methods' or 'Characterization' could be classified into the wrong audit mode. In this skill, that can reduce classification precision and route inputs to an inappropriate analysis path, which may weaken reproducibility or safety-review judgments for borderline materials.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The patent classification trigger uses very generic words like 'example' and 'embodiment', which commonly appear outside patent documents and can cause false routing into the embodiment audit mode. In a skill that audits experimental methods, this misclassification could skew the evaluation criteria applied to user-provided content and produce misleading audit results.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The top-level documentation states that 'All outputs are written only to the selected output directory, which is reset at start.' However, reset_output_dir later explicitly says it will 'Remove only this generator's known artifacts, never an entire directory' and only unlinks three named files. This is an active contradiction between the file's documentation and its implemented behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.