Back to skill

Security audit

sn-da-non-spreadsheet-analysis

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent document-analysis tool, but it needs Review because it writes sensitive document-derived images and conversions to predictable shared temporary paths without cleanup.

Install only in trusted, single-user or well-sandboxed environments, and avoid using it on highly confidential contracts, invoices, resumes, or presentations unless temporary-file handling is fixed. The skill should use private per-run temp directories, delete rendered/extracted artifacts, and make captioning of document images explicit and user-controllable.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
capability/pdf-analysis/SKILL.md:127
Finding

Predictable Shared Temporary Files in PDF Processing

Content
View full analysis

Vulnerability Details

File Location: capability/pdf-analysis/SKILL.md, lines 127, 188, and 228
Vulnerability Type: Predictable temporary-file creation
Risk Level: Medium

Vulnerable Code

python
# Scanned PDF page
img_path = f"/tmp/pdf_page_{i+1}.png"
pix.save(img_path)

# Hybrid PDF page
img_path = f"/tmp/hybrid_page_{i+1}.png"
pix.save(img_path)

# Embedded PDF image
img_path = f"/tmp/pdf_img_p{page_num+1}_{img_idx}.{ext}"
with open(img_path, 'wb') as f:
    f.write(img_bytes)

Technical Analysis

PDF pages and embedded images are written into the system-wide /tmp directory using deterministic filenames derived only from page and image indexes. The workflow does not create a private per-run directory, generate unpredictable names, check whether an existing path is a symbolic link, enforce restrictive permissions, or delete generated files after processing.

In a multi-user or concurrently executing environment, another process can predict these paths and pre-create files or symbolic links. Concurrent Skill invocations can also overwrite each other's files. The explicit open(..., 'wb') operation used for embedded images follows symbolic links under normal filesystem semantics and truncates the destination before writing.

Attack Path

  1. A local attacker determines that the Agent will process a PDF.
  2. The attacker predicts a path such as /tmp/pdf_page_1.png, /tmp/hybrid_page_1.png, or /tmp/pdf_img_p1_0.png.
  3. The attacker pre-creates the path as a file or, where filesystem permissions permit, as a symbolic link to another file writable by the Agent.
  4. The Agent processes the PDF and writes document-derived content to the attacker-controlled path.
  5. The attacker reads the extracted document image, corrupts the analysis through a race condition, or causes the linked destination to be overwritten.
  6. Because no cleanup is performed, sensitive page images may remai ...[truncated 511 chars]
Remediation
View remediation

Remediation Suggestions

  • Create a private directory for every processing operation with tempfile.TemporaryDirectory().
  • Generate files inside that directory with tempfile.NamedTemporaryFile() or unpredictable UUID-based names.
  • Ensure temporary directories and files are accessible only to the Agent account, such as directory mode 0700 and file mode 0600.
  • Avoid reopening attacker-influenced paths. Where applicable, use exclusive creation and no-follow semantics.
  • Pass the private temporary directory explicitly to rendering and extraction functions.
  • Place cleanup in a context manager or finally block so files are removed after success, failure, or timeout.
  • Do not reuse page-only names across users, documents, or concurrent executions.

T09 · Insecure Skill Coding Practices

Warning
Location
capability/ppt-analysis/SKILL.md:174
Finding

Predictable Shared Conversion and Slide Files in PowerPoint Processing

Content
View full analysis

Vulnerability Details

File Location: capability/ppt-analysis/SKILL.md, lines 174–194
Vulnerability Type: Predictable temporary-file creation and output collision
Risk Level: Medium

Vulnerable Code

python
# Convert PPTX → PDF (preserves slide visuals)
out_dir = "/tmp"
r = subprocess.run(
    ['libreoffice', '--headless', '--convert-to', 'pdf', '--outdir', out_dir, pptx_path],
    capture_output=True, text=True
)
pdf_name = os.path.basename(pptx_path).rsplit('.', 1)[0] + '.pdf'
pdf_path = os.path.join(out_dir, pdf_name)

if not os.path.exists(pdf_path):
    print(f"LibreOffice conversion failed: {r.stderr[:200]}")
    return slides_data

# Render each image-only slide
doc = fitz.open(pdf_path)
for s in image_slides:
    page_idx = s['slide'] - 1
    if page_idx >= len(doc):
        continue
    page = doc[page_idx]
    mat = fitz.Matrix(150/72, 150/72)
    pix = page.get_pixmap(matrix=mat)
    img_path = f"/tmp/slide_{s['slide']}.png"
    pix.save(img_path)

Technical Analysis

LibreOffice conversion output and rendered slide images are placed directly in the shared /tmp namespace. The converted PDF name is derived from the uploaded presentation's basename, while slide images use only the slide number. These paths are predictable and are not isolated by user, input document, or execution.

The code verifies only that the expected PDF path exists. It does not establish that the file was created by the current conversion process or that it is a regular, trusted file. A pre-existing or concurrently replaced PDF could therefore be opened and processed. Rendered slide files are likewise vulnerable to cross-run collisions and symbolic-link manipulation.

Attack Path

  1. A local attacker predicts /tmp/slide_1.png or learns the presentation basename and predicts the converted PDF path.
  2. The attacker pre-creates or races the expected path, potentially using a sym ...[truncated 985 chars]
Remediation
View remediation

Remediation Suggestions

  • Allocate a unique private conversion directory with tempfile.TemporaryDirectory().
  • Direct LibreOffice output to that private directory rather than /tmp.
  • Generate rendered slide filenames within the private directory and include a random component.
  • Before opening conversion output, verify that LibreOffice succeeded, the output is a regular file inside the expected private directory, and the file was produced during the current operation.
  • Reject symbolic links and unexpected path resolution.
  • Apply restrictive permissions to all converted and rendered document artifacts.
  • Automatically remove the converted PDF and slide images when processing completes or fails.

T09 · Insecure Skill Coding Practices

Warning
Location
capability/word-analysis/SKILL.md:190
Finding

Predictable Embedded-Image Paths Permit Symlink Overwrite in Word Processing

Content
View full analysis

Vulnerability Details

File Location: capability/word-analysis/SKILL.md, lines 190–193
Vulnerability Type: Predictable temporary file with unsafe overwrite
Risk Level: Medium

Vulnerable Code

python
# Save to temp
tmp_path = f"/tmp/{os.path.basename(media)}"
with z.open(media) as src, open(tmp_path, 'wb') as dst:
    dst.write(src.read())

Technical Analysis

Embedded Word images commonly have predictable archive names such as word/media/image1.png. The code strips the archive directory and writes the image to a predictable shared path such as /tmp/image1.png.

Python's ordinary open(path, 'wb') follows symbolic links and truncates an existing destination. The code performs no exclusive creation, symbolic-link check, ownership validation, permission hardening, per-run isolation, or cleanup. Different documents and concurrent users will frequently produce identical media basenames, making collisions particularly likely.

Attack Path

  1. A local attacker anticipates that a Word document containing word/media/image1.png will be processed.
  2. The attacker creates /tmp/image1.png as a symbolic link to a file writable by the Agent, or monitors the predictable path for extracted content.
  3. The Agent opens /tmp/image1.png with wb mode while extracting the document.
  4. The operation follows the symbolic link, truncates the linked target, and writes the embedded image bytes.
  5. Alternatively, the attacker reads or replaces the temporary image before it is sent to the captioning subprocess.
  6. The substituted image can corrupt the analysis, while an unremoved extracted image can disclose document contents.

Impact Assessment

A successful attack can overwrite or corrupt files writable by the Agent process, disclose embedded Word images, manipulate image-captioning results, or cause denial of service. The affected scope is bounded by the filesystem privileges of the Agent acco ...[truncated 107 chars]

Remediation
View remediation

Remediation Suggestions

  • Extract images into a unique directory created by tempfile.TemporaryDirectory().
  • Generate destination names independently of archive-controlled media names.
  • Use exclusive file creation and reject symbolic links; on supported systems, use secure no-follow semantics.
  • Canonicalize the destination and verify that it remains inside the private temporary directory.
  • Restrict temporary-file permissions to the Agent account.
  • Keep extracted files private until captioning has completed, then remove them automatically.
  • Use a separate temporary directory for every document and every concurrent invocation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (15)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest description says to proactively use the skill when users mention broad phrases such as "文档分析", "报告解析", "合同分析", and even proofreading-style requests like "错别字" or "语病". These phrases are common in everyday assistance requests and the trigger list does not provide negative examples or tighter scope boundaries, which could cause unintended invocation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest scopes this skill to Word/PDF/PPT parsing and analysis, and explicitly says pure image analysis should use a different skill. However, the code directly executes another skill's caption.py through subprocess.run, introducing process execution as an additional capability beyond straightforward document parsing. While delegating to an image-caption skill may support OCR-like cases, spawning a separate process is not itself declared in the manifest and is an unjustified capability at the intent level.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The workflow renders each PDF page to an image and sends it to another script for caption/OCR without any disclosure, consent, or data-handling guardrails. Because PDFs commonly contain sensitive business, legal, financial, or personal data, this silent cross-component transfer can expose document contents to additional processing surfaces, logging, retention, or downstream model services.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The file describes PDF parsing and extraction, but its scanned-PDF path shells out to another skill's script using subprocess to perform caption/OCR-like extraction. Calling an external executable is not an obvious requirement from this skill file's own documented purpose and materially expands capability beyond in-process document parsing.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

For mixed text/image PDFs, the code again renders pages to files and executes a separate Python script for captioning. This introduces process-spawning behavior that is not reflected in the file's PDF-analysis description, which otherwise reads like a parsing/extraction workflow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill omits a clear warning that image-only slides will be rendered and then passed to a separate captioning script, which can surprise users and violate data-handling expectations for sensitive presentations. Even if the external script is local, this undisclosed secondary processing materially changes how user content is handled and can increase confidentiality risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill sends slide-derived image data to an external captioning script via subprocess, creating a trust boundary where potentially sensitive document content is handed off to another component without any explicit consent, sandboxing, or provenance checks. This is risky because the called script could log, transmit, or otherwise mishandle extracted slide contents, and the parent skill does not constrain what data is exposed beyond selecting image-only slides.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default caption prompt explicitly requires Markdown output in Chinese, which imposes a specific language without user opt-in. The file does not document that this language choice is optional or region-specific, so it conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest description is written as a Chinese-only capability statement, and several examples are framed in Chinese without indicating that output language follows user preference. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy violation unless the locale constraint is documented and justified.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The SKILL.md for this file describes Word document parsing and extraction, but the implementation includes subprocess execution of LibreOffice to convert .doc files before analysis. While conversion may support legacy .doc handling, spawning external executables is a materially broader capability than straightforward in-process parsing and is not clearly declared in this skill file's stated purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Line L003 describes Word document parsing, including extracting embedded images to captions, but the code actually shells out to a separate image-caption skill script to analyze those images. That behavior is not merely extraction from Word; it extends into image understanding, which is a different capability and diverges from a narrow Word-analysis description in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill writes embedded document images to predictable paths under /tmp and passes them to an external script without cleanup, isolation, or user notice. This can expose sensitive document content through temporary-file leakage, filename collisions, or unintended retention on shared systems, especially because documents often contain confidential screenshots, signatures, or personal data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

Embedded images are written to predictable /tmp paths with no warning, cleanup, or confidentiality controls. On shared systems or long-lived environments, sensitive charts, photos, or document fragments may remain recoverable by other users/processes or be unintentionally retained after analysis.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This skill claims PPT parsing and extraction, but implements that by launching LibreOffice through subprocess.run to convert .ppt to .pptx and later .pptx to PDF. While conversion is related to the purpose, arbitrary local process execution is a stronger capability than the manifest text suggests and is not explicitly declared.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The documented code converts .ppt to .pptx in the source directory and later converts presentations to PDF and PNG files under /tmp. Although this is part of the implementation, the markdown does not explicitly disclose that derivative copies of user presentations and slide images are written to disk, which can affect user data handling expectations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.