Back to skill

Security audit

PDF Watermark

Security checks for vulnerabilities and agentic risk

Overview

This is a local PDF watermarking tool with some operational cautions, but I found no hidden exfiltration, persistence, credential access, or purpose-mismatched behavior.

Install dependencies in a virtual environment, avoid running the tool as root, use a custom watermark/config for your language needs, and do not expose the optional web UI through a tunnel unless the served directory contains nothing sensitive. Be aware that PPT/PPTX conversion may leave an unwatermarked temporary PDF on disk until manually cleaned up.

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)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:18
Finding

Unpinned Third-Party Python Dependencies

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:18-21
Additional Locations: README.en.md:29-32, README.md:29-32
Vulnerability Type: Supply-chain exposure through unpinned dependencies
Risk Level: Medium

Vulnerable Code Snippet:

bash
- **Python 3**: `PyPDF2`, `reportlab`
  ```bash
  pip3 install PyPDF2 reportlab
  ```

The same unpinned installation command is repeated in both README files:

bash
pip3 install PyPDF2 reportlab

Technical Analysis

The installation instructions retrieve the latest available versions of PyPDF2 and reportlab without version constraints, integrity hashes, a lock file, or a reviewed package manifest. Consequently, the code installed and subsequently imported by the Skill can change without any modification to this repository.

No evidence indicates that the currently named packages are malicious or intentionally misspelled. The risk arises because a future compromised release, maintainer account, distribution channel, or unexpectedly incompatible update could introduce attacker-controlled behavior. Both packages are imported at module initialization, so malicious package code could execute when the watermark script starts.

Attack Path

  1. An attacker compromises a dependency maintainer account, package release process, or package-distribution infrastructure.
  2. The attacker publishes a malicious release under one of the dependency names.
  3. A user follows the documented pip3 install PyPDF2 reportlab command.
  4. Because no versions or hashes are specified, pip downloads the latest accepted release.
  5. The user invokes scripts/pptx_to_pdf_watermark.py.
  6. The malicious dependency is imported and executes with the privileges of the user running the script.

Impact Assessment

A compromised dependency could obtain the same operating-system privileges as the installing or executing user. Depending ...[truncated 465 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add a reviewed dependency manifest with exact version pins:

    text
    PyPDF2==REVIEWED_VERSION
    reportlab==REVIEWED_VERSION
    
  2. Generate and record cryptographic hashes for all approved distributions.

  3. Install dependencies using hash verification:

    bash
    pip3 install --require-hashes -r requirements.txt
    
  4. Use a reproducible lock-file workflow and update dependencies through a controlled review process.

  5. Run dependency vulnerability and provenance checks in CI.

  6. Keep installation inside an isolated virtual environment and avoid installing or running the Skill as root.

  7. Update SKILL.md, README.en.md, and README.md so all installation examples use the secured dependency manifest.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/pptx_to_pdf_watermark.py:207
Finding

Converted Source Documents Are Not Removed from Temporary Storage

Content
View full analysis

Vulnerability Details

File Location: scripts/pptx_to_pdf_watermark.py:207-213
Vulnerability Type: Sensitive temporary-file retention
Risk Level: Low

Vulnerable Code Snippet:

python
# Convert if needed
ext = os.path.splitext(input_file)[1].lower()
if ext in ('.pptx', '.ppt'):
    tmp_dir = tempfile.mkdtemp()
    pdf_path = pptx_to_pdf(input_file, tmp_dir)
else:
    pdf_path = input_file

add_watermark(pdf_path, output_file, config)

Technical Analysis

When processing a PPT or PPTX file, the script creates a temporary directory using tempfile.mkdtemp() and asks LibreOffice to write a complete converted PDF into that directory. Neither the converted PDF nor its containing directory is removed after watermarking.

The generated per-page watermark overlays are deleted elsewhere in the implementation, but the potentially sensitive, unwatermarked document produced by LibreOffice remains on disk. Because mkdtemp() is not managed by a context manager and there is no finally cleanup block, the residue persists after successful execution and after many failure conditions.

The temporary directory normally has restrictive permissions, which limits immediate exposure to the owning user and privileged local processes. Nevertheless, persistent copies may later be collected by indexing tools, backup software, forensic processes, or an attacker who gains access to the same account.

Attack Path

  1. A user processes a confidential PPT or PPTX presentation.
  2. LibreOffice creates an unwatermarked PDF inside the directory returned by tempfile.mkdtemp().
  3. The script generates the requested output but does not remove the temporary directory or converted PDF.
  4. A process running as the same user, a privileged local process, backup software, or a later attacker enumerates temporary storage.
  5. The residual PDF is recovered, exposing the document without the intended wa ...[truncated 602 chars]
Remediation
View remediation

Remediation Suggestions

Replace unmanaged temporary-directory creation with tempfile.TemporaryDirectory() so cleanup occurs automatically:

python
ext = os.path.splitext(input_file)[1].lower()
if ext in ('.pptx', '.ppt'):
    with tempfile.TemporaryDirectory() as tmp_dir:
        pdf_path = pptx_to_pdf(input_file, tmp_dir)
        add_watermark(pdf_path, output_file, config)
else:
    add_watermark(input_file, output_file, config)

Additional hardening measures:

  1. Put cleanup operations in a finally block if a context manager cannot be used.
  2. Ensure partial output files are removed when conversion or watermarking fails.
  3. Avoid logging temporary document paths or sensitive filenames unnecessarily.
  4. Document that temporary storage may contain sensitive content during processing.
  5. Add tests confirming that temporary converted PDFs and directories are absent after both successful and failed executions.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The trigger words include very generic phrases such as 'convert to PDF' and 'PDF watermark', which can cause the skill to activate for broad, ordinary document-conversion requests that may not actually require this tool. In an agent environment, overbroad activation increases the chance of unintended file processing, mistaken tool selection, or handling of sensitive documents without clear user intent.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill documents shell execution and file access behavior but does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, missing scope metadata can cause over-broad execution or make reviewers unaware that the skill invokes local file reads and command execution, increasing the chance of unsafe use.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

  • LibreOffice (soffice, headless mode for PPTX→PDF conversion)
    • macOS: brew install --cask libreoffice
    • Linux: sudo apt install libreoffice
    • Windows: Download from libreoffice.org
  • Python 3: PyPDF2, reportlab
    bash

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill recommends exposing a locally hosted UI through a tunnel service without any warning about the security implications. Publishing a local HTTP server can expose sensitive files, configuration data, or an unauthenticated interface to external users, especially if the working directory contains more than the intended HTML files.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/pptx_to_pdf_watermark.py (reported line 64)May include surrounding context.

python
def pptx_to_pdf(pptx_path, output_dir):
    """Convert PPTX to PDF via LibreOffice."""
    result = subprocess.run(
        ['soffice', '--headless', '--convert-to', 'pdf', '--outdir', output_dir, pptx_path],
        capture_output=True, text=True, timeout=120
    )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document declares lang="zh-CN", and the visible UI text throughout the page is also fixed in Simplified Chinese. For a general-purpose PDF watermark tool, this imposes a specific language/locale without any user opt-in or explanation, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document declares lang="zh-CN" and all visible interface text is presented only in Simplified Chinese. This creates a natural-language locale constraint without any opt-in, alternative language option, or documented justification that the tool is intended only for a China-specific audience.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest describes a skill that converts PPT/PPTX to PDF and adds watermarks, and the button label at L114 says it will export configuration and add a watermark. In this file, however, the implemented behavior is limited to rendering a canvas preview and copying JSON config text to the clipboard via navigator.clipboard/document.execCommand; no file conversion, PDF generation, or watermark application occurs.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The button text '导出配置并加水印' at L114 and the status message at L219 telling the user to send the config to an AI assistant imply the action performs or completes watermarking. The code in exportConfig() only serializes the current settings and copies them to the clipboard, which contradicts the user-facing intent conveyed by that inline documentation/UI text.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The one-sentence hook is presented only in Chinese, while the document otherwise includes bilingual content and an English toggle line. This can violate language/locale expectations by privileging a specific language without explicit user choice or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default watermark text is fixed to Chinese ("内部资料 请勿外传"), and the script does not provide any user-facing opt-in or explanation that it is intended only for a Chinese-language workflow. This is a natural-language locale constraint embedded in code, which can violate language/locale policy when not made optional or justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.