Back to skill

Security audit

Redline

Security checks for vulnerabilities and agentic risk

Overview

This contract-redlining skill is purpose-aligned, but its bundled DOCX parser has a concrete unsafe XML/ZIP handling concern for untrusted contracts.

Review contracts only from trusted sources or run the skill in a constrained workspace. Before broad use, the publisher should harden XML parsing, reject suspicious DOCX archives, and document that the skill should read only the user-provided contract/review JSON and write only the requested output files.

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/contract_review_pipeline.py:50
Finding

Unsafe Parsing of Attacker-Controlled DOCX XML

Content
View full analysis

Vulnerability Details

File Location: scripts/contract_review_pipeline.py:50-51
Related Call Sites: scripts/contract_review_pipeline.py:78-79, scripts/contract_review_pipeline.py:210-211, and scripts/contract_review_pipeline.py:360-361
Vulnerability Type: Unsafe XML parsing
Risk Level: Medium

Vulnerable Code

python
def parse_xml(data: bytes) -> etree._Element:
    return etree.fromstring(data)

Attacker-controlled DOCX members are passed to this function, including:

python
comments_root = parse_xml(archive.read("word/comments.xml"))
document_root = parse_xml(archive.read("word/document.xml"))
python
document_xml = read_docx_member(input_docx, "word/document.xml")
root = parse_xml(document_xml)
python
document_root = parse_xml(original_files["word/document.xml"])
settings_root = parse_xml(original_files["word/settings.xml"])

Technical Analysis

A DOCX document is a ZIP archive containing XML files. The skill processes user-supplied DOCX files and parses their document.xml, comments.xml, and settings.xml members through lxml.etree.fromstring() without supplying an explicitly hardened XML parser.

The implementation does not explicitly disable:

  • DTD processing
  • XML entity resolution
  • Network-based resource resolution
  • Oversized XML tree handling

Consequently, its security depends on implicit lxml and libxml2 defaults, which can vary by version and runtime configuration. A crafted document containing malicious declarations or resource-intensive XML structures could expose the process to entity expansion, unintended local-resource resolution, or parser-based denial of service.

The surrounding ZIP-processing code also reads relevant members into memory without enforcing per-member or aggregate uncompressed-size limits. This can amplify denial-of-service risk when maliciously compressed or oversized DOCX content is supplied.

Attack Path

  1. An attacker creates a DOCX archive cont ...[truncated 1335 chars]
Remediation
View remediation

Remediation Suggestions

Create and use an explicitly hardened XML parser rather than relying on library defaults:

python
def parse_xml(data: bytes) -> etree._Element:
    parser = etree.XMLParser(
        resolve_entities=False,
        load_dtd=False,
        no_network=True,
        huge_tree=False,
    )
    return etree.fromstring(data, parser=parser)

Apply the following additional controls:

  1. Reject XML documents containing a DOCTYPE declaration before parsing.
  2. Enforce a maximum compressed and uncompressed size for each DOCX member.
  3. Enforce a maximum aggregate uncompressed size for the entire DOCX archive.
  4. Reject duplicate, unexpected, encrypted, or suspicious archive entries.
  5. Limit XML nesting depth, paragraph count, comment count, and extracted text size.
  6. Catch zipfile, lxml, memory, and malformed-document errors and fail closed with a safe diagnostic.
  7. Test the parser against entity-expansion payloads, external-entity payloads, deeply nested XML, oversized XML members, and ZIP bombs.
  8. Process untrusted contracts in a resource-constrained environment where practical.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to run a local Python script and produce amended DOCX and JSON outputs, which implies file read/write capability, but it does not declare any explicit tool scope or permissions boundary. This is dangerous because an agent or orchestrator may grant broader filesystem access than necessary, increasing the chance of unintended access to sensitive local documents or overwriting files during contract processing.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.