Back to skill

Security audit

MiniMax PDF Pro

Security checks for vulnerabilities and agentic risk

Overview

This PDF skill is mostly aligned with PDF creation and processing, but it uses unsafe dependency installation and gives HTML conversion more file and network access than necessary.

Install only if you trust the publisher and are willing to let the skill modify your development environment. Avoid running its remote `curl | sh` installer; prefer a verified Tectonic release or package manager. Do not use it on untrusted HTML unless network access and local file reads are sandboxed or disabled.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
handlers/latex.md:14
Finding
Mandatory execution of an unverified remote shell installer<![CDATA[ ## Vulnerability Details **File Location**: `handlers/latex.md:14-21` **Vulnerability Type**: Remote payload retrieval and immediate shell execution **Risk Level**: High ### Vulnerable Code ```markdown ### Step 1: Install Environment Tectonic is not pre-installed. Install it first: ```bash cd ~ && curl -fsSL https://drop-sh.fullyjustified.net | sh && ls -la tectonic ``` **Note**: Tectonic will be installed to `~/tectonic` (user home directory) ``` The same unsafe installation command is also presented by the environment-checking script: ```bash echo " Tectonic: curl -fsSL https://drop-sh.fullyjustified.net | sh" ``` This secondary occurrence is located at `scripts/setup.sh:452`. ### Technical Analysis The LaTeX workflow instructs the Agent to download a mutable shell script from `https://drop-sh.fullyjustified.net` and pass its contents directly to `sh`. There is no intervening inspection, version pinning, checksum verification, digital-signature validation, or trusted release manifest. Although HTTPS provides transport encryption, it does not guarantee that the server will continue returning the same reviewed payload. The effective code can change after the Skill package has been audited. Compromise of the remote server, domain, hosting account, certificate issuance process, or deployment pipeline would allow an attacker to replace the installer with arbitrary shell commands. The instruction is presented as the first mandatory step of the LaTeX route. This makes execution likely whenever a user explicitly requests LaTeX or Tectonic-based PDF generation. Installing a single PDF compiler does not require granting an unaudited remote response unrestricted shell execution. `scripts/setup.sh` only prints the command and does not directly execute it. Nevertheless, it promotes the same unsafe installation mechanism. ### Attack Path 1. An attacker compromises or gains control over the remote installer endpoint or its deployment pipeline. ...[truncated 1445 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove every `curl | sh` installation instruction, including the command printed by `scripts/setup.sh`. 2. Download an official, versioned Tectonic release artifact from a documented upstream release location. 3. Pin the exact Tectonic version and platform-specific artifact name. 4. Verify the artifact before execution using a pinned SHA-256 or stronger digest obtained through a separately authenticated release manifest. 5. Prefer upstream cryptographic signatures when available and verify them against a pinned maintainer key. 6. Download into a dedicated temporary directory with restrictive permissions rather than streaming into a shell. 7. Extract only the expected executable and install it into a Skill-specific directory or isolated environment. 8. Do not overwrite an existing executable without explicit user approval. 9. Run the compiler as an unprivileged user and, where possible, inside a sandbox with restricted filesystem and network access. 10. Require explicit user consent before installing any missing dependency. 11. Make the safe installation process fail closed if version, signature, checksum, filename, or destination validation fails. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/html_to_pdf.js:193
Finding
Active HTML rendering permits unrestricted network requests and arbitrary local stylesheet reads<![CDATA[ ## Vulnerability Details **File Location**: `scripts/html_to_pdf.js:193-199, 410-445` **Vulnerability Type**: Unsafe rendering of untrusted active HTML with excessive host access **Risk Level**: High ### Vulnerable Code The input is opened as an active local document without disabling JavaScript or restricting requests: ```javascript const page = await browser.newPage(); // Load HTML content const fileUrl = 'file://' + inputPath; await page.goto(fileUrl, { waitUntil: 'networkidle' }); ``` Absolute stylesheet paths nominated by the HTML are subsequently read by the Node.js process: ```javascript const inlinedCount = await page.evaluate(() => { const links = document.querySelectorAll('link[rel="stylesheet"]'); let count = 0; links.forEach(link => { const href = link.getAttribute('href') || ''; // Only inline local file paths (absolute paths starting with /) if (href.startsWith('/') && !href.startsWith('//') && !href.startsWith('http')) { // Mark for server-side inlining link.setAttribute('data-inline-path', href); count++; } }); return count; }); if (inlinedCount > 0) { const linksToInline = await page.evaluate(() => { return Array.from(document.querySelectorAll('link[data-inline-path]')) .map(link => link.getAttribute('data-inline-path')); }); for (const cssPath of linksToInline) { try { if (fs.existsSync(cssPath)) { const cssContent = fs.readFileSync(cssPath, 'utf-8'); await page.evaluate(({ path: p, css }) => { const link = document.querySelector(`link[data-inline-path="${p}"]`); if (link) { const style = document.createElement('style'); style.textContent = css; style.setAttribute('data-inlined-from', p); link.parentNode.replaceChild(style, link); } }, { path: cssPath, css: cssContent }); console.log(` Inlined CSS: ${cssPath}`); } else { console.lo ...[truncated 3802 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat every converted HTML document as untrusted. 2. Disable JavaScript by default for conversion inputs. If a feature such as Mermaid or KaTeX requires scripts, execute only bundled, reviewed renderer code rather than arbitrary document scripts. 3. Create an isolated browser context with explicit security settings and a restrictive Content Security Policy. 4. Intercept all browser requests and deny them by default. 5. Allow only necessary local assets and explicitly approved HTTPS origins. 6. Block loopback, link-local, private, multicast, and cloud metadata address ranges after DNS resolution and on every redirect. 7. Reject `file:`, `ftp:`, `data:`, `blob:`, and other unnecessary schemes except for narrowly defined uses. 8. Remove support for arbitrary absolute stylesheet paths. 9. Resolve local assets relative to the input document or a dedicated asset root. 10. Canonicalize every asset path with `realpath`, then verify that it remains beneath an approved directory before reading it. 11. Reject symlinks or revalidate the final resolved target to prevent directory escape. 12. Permit only expected asset extensions and enforce file-size limits. 13. Run Chromium and the Node.js wrapper in a disposable container with no credentials, a read-only filesystem, a dedicated working directory, resource limits, and no internal-network access. 14. Add conversion timeouts and terminate browser processes that exceed CPU, memory, page, or request limits. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/pdf.sh:39
Finding
Runtime installation of mutable and unpinned dependencies<![CDATA[ ## Vulnerability Details **File Location**: `scripts/pdf.sh:39-73, 94-101`; `scripts/compile_latex.py:63-80`; `scripts/package.json:3-7` **Vulnerability Type**: Unsafe runtime dependency installation and host-environment mutation **Risk Level**: Medium ### Vulnerable Code The unified repair command globally installs the current Playwright release and installs unpinned Python packages: ```bash cmd_fix() { local rc=0 if command -v npm &>/dev/null; then echo "Installing Playwright (global)..." if ! npm install -g playwright >/dev/null; then echo "Failed to install Playwright via npm." rc=3 fi echo "Installing Chromium browser..." if ! npx playwright install chromium >/dev/null; then echo "Failed to install Chromium via Playwright." rc=3 fi # Install pdf-lib for --preserve-links support (hyperlink injection into PDF) echo "Installing pdf-lib (for hyperlink preservation)..." if [[ -f "$SCRIPT_DIR/package.json" ]]; then (cd "$SCRIPT_DIR" && npm install --omit=dev 2>/dev/null) || echo "Warning: pdf-lib install failed (links may not be clickable)" fi else echo "npm not found; cannot install Playwright automatically." rc=2 fi if command -v python3 &>/dev/null; then echo "Installing Python dependencies (pikepdf, pdfplumber)..." if ! python3 -m pip install --user -U pikepdf pdfplumber >/dev/null; then echo "Failed to install Python dependencies." rc=3 fi else echo "python3 not found; cannot install PDF processing dependencies." rc=2 fi ``` Normal HTML conversion may also invoke npm installation automatically: ```bash if [[ "$*" == *"--preserve-links"* ]] && [[ -f "$SCRIPT_DIR/package.json" ]] && [[ ! -d "$SCRIPT_DIR/node_modules" ]]; then echo "Installing npm dependencies for link preservation..." (cd "$SCRIPT_DIR" && npm install --omit=dev 2>/dev/null) || echo "Warning: npm install failed, links may not be clickable" fi ``` ...[truncated 3688 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove automatic dependency installation from document conversion and compilation paths. 2. Require explicit user approval before any environment modification. 3. Pin exact npm and Python package versions that have been reviewed. 4. Use `npm ci --ignore-scripts` with a committed lockfile where package lifecycle scripts are unnecessary. 5. If lifecycle scripts are required, review them and allow only the minimum necessary scripts in an isolated build environment. 6. Replace the global Playwright installation with a project-local, exactly pinned dependency. 7. Pin the corresponding Chromium revision and verify downloaded browser artifacts. 8. Create a dedicated Python virtual environment for this Skill. 9. Maintain a hash-locked requirements file and install with `pip --require-hashes`. 10. Remove `--break-system-packages` entirely. 11. Avoid `pip install --user` for Skill dependencies because it changes shared user state. 12. Prefer a prebuilt container or immutable environment containing all reviewed dependencies. 13. Separate dependency setup from normal Skill execution and make conversion fail safely when the approved environment is unavailable. 14. Generate and review a software bill of materials, and continuously scan the exact locked dependency versions for known vulnerabilities. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (89)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The supplied code chunk does not implement PDF creation, PDF manipulation, LaTeX handling, citations, math rendering, Mermaid, or academic document features. Its primary purpose is dependency/environment management for Playwright/Chromium, likely as a support component for an HTML-to-PDF pipeline. While such a helper could indirectly support PDF generation, this chunk itself is focused on locating browser binaries and optionally installing Chromium, which is materially different from the declared end-user description. Therefore this code chunk's behavior is not accurately represented by the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
The declared description emphasizes two main areas: creating PDFs using HTML + Paged.js (plus academic/LaTeX-oriented features) and processing existing PDFs with Python. The supplied code does neither of those directly. Instead, it performs file-format conversion from various source formats such as DOCX, PPTX, XLSX, CSV, TXT, and HTML into PDF using a headless LibreOffice subprocess. That is a materially different capability and primary behavior from the declared purpose. While converting HTML to PDF is loosely related to PDF creation, the implementation path and supported formats are much broader and centered on LibreOffice-based document conversion, which is undeclared.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The code chunk does not implement PDF generation, PDF reading/extraction/merge/split/form filling, academic formatting features, KaTeX/Mermaid support, or LaTeX compilation. Instead, it is a standalone HTML hyperlink preservation tool specifically designed for translation workflows. Its primary purpose and exposed commands (extract, restore, placeholder, unplaceholder) are materially different from the declared PDF/LaTeX solution, so this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code appears to be an internal support library for CSS/Paged.js-style document rendering infrastructure, likely part of a PDF-generation stack, but the supplied chunk itself does not implement the declared end-user functionality. It mainly parses CSS, walks ASTs, validates syntax, matches declarations, and generates source maps. Those are supporting implementation details for HTML+Paged.js workflows, but the declared description is much broader and includes direct PDF creation, Python-based PDF processing, and LaTeX support. None of those capabilities are evidenced in this chunk. Therefore the description does not accurately represent what this specific code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code clearly supports several declared PDF-processing capabilities such as extracting content, merging/splitting PDFs, filling forms, and converting files to PDF. However, the declared description emphasizes a PDF creation workflow centered on HTML + Paged.js and academic/LaTeX-oriented features, none of which are evidenced in this code chunk. Instead, the code is a general-purpose PDF processing CLI with delegated commands for forms, extraction, page manipulation, metadata editing, and generic conversion. It also exposes capabilities not explicitly described, such as metadata modification and page rotation/cropping. Because the declared purpose prominently includes specialized creation and academic/LaTeX features that are absent here, while the actual code focuses on operational PDF manipulation, this is a meaningful description/behavior mismatch.

Ae1

High
Category
analysis-evasion
Content
如果运行 `pdf.sh html` 或 `html_to_pdf.js` 时遇到以下错误:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Hidden Instructions

High
Category
Prompt Injection
Content
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="{WORKSPACE}/.minimax/skills/minimax-pdf/scripts/styles/base.css">
    <!-- 如果需要封面,再加一行对应的 cover CSS -->
    <!-- <link rel="stylesheet" href="{WORKSPACE}/.minimax/skills/minimax-pdf/scripts/styles/cover-corporate.css"> -->
    <style>
        /* 这里只写本文档特有的自定义样式,base.css 已包含的不要重复写 */
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="{WORKSPACE}/.minimax/skills/minimax-pdf/scripts/styles/base.css">
    <!-- 如果需要封面,再加一行对应的 cover CSS -->
    <!-- <link rel="stylesheet" href="{WORKSPACE}/.minimax/skills/minimax-pdf/scripts/styles/cover-corporate.css"> -->
    <style>
        /* 这里只写本文档特有的自定义样式,base.css 已包含的不要重复写 */
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
#### Recommended: `data-*` Attributes
```html
<!-- Figures -->
<figure id="fig-1">
    <img src="chart.png" alt="...">
    <figcaption data-label="Figure 1">System Architecture</figcaption>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Missing User Warnings

High
Confidence
96% confidence
Finding
The skill instructs the agent/user to install software by fetching and piping a remote script directly into the shell in the home directory, without integrity verification, pinning, or trust guidance. This creates a clear supply-chain and remote code execution risk: if the endpoint is compromised, spoofed, or changed, arbitrary commands will run with the user's privileges.

External Script Fetching

High
Category
Supply Chain
Content
Tectonic is not pre-installed. Install it first:

```bash
cd ~ && curl -fsSL https://drop-sh.fullyjustified.net | sh && ls -la tectonic
```

**Note**: Tectonic will be installed to `~/tectonic` (user home directory)
Confidence
99% confidence
Finding
The exact command 'curl -fsSL https://drop-sh.fullyjustified.net | sh' is a classic external-script-fetch pattern that executes untrusted remote content immediately. In the context of an agent skill, this is especially dangerous because it normalizes direct execution of network-delivered code during routine document generation workflows.

Chaining Abuse

High
Category
Tool Misuse
Content
Tectonic is not pre-installed. Install it first:

```bash
cd ~ && curl -fsSL https://drop-sh.fullyjustified.net | sh && ls -la tectonic
```

**Note**: Tectonic will be installed to `~/tectonic` (user home directory)
Confidence
95% confidence
Finding
The chained command combines directory changes, remote script execution, and follow-up commands in one line, reducing visibility and making unsafe execution easier to overlook or automate. Chaining amplifies the risk of the remote installer by encouraging non-interactive execution and by making failure modes and side effects harder to inspect.

Chaining Abuse

High
Category
Tool Misuse
Content
* @param {Node} node An object implementing the DOM1 |Node| interface.
	 * @return {boolean} true if the node is:
	 *  1) A |Text| node that is all whitespace
	 *  2) A |Comment| node
	 *  and otherwise false.
	 */
	function isIgnorable(node) {
Confidence
70% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
* @param {Node} node An object implementing the DOM1 |Node| interface.
	 * @return {boolean} true if the node is:
	 *  1) A |Text| node that is all whitespace
	 *  2) A |Comment| node
	 *  and otherwise false.
	 */
	function isIgnorable(node) {
Confidence
70% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
ry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz";
	var _spec = "1.1.3";
	var _where = "/home/gitlab-runner/builds/BQJy2NwB/0/pagedjs/pagedjs";
	var author = {
		name: "Roman Dvornov",
		email: "rdvornov@gmail.com",
		url: "https://github.com/lahmatiy"
	};
	var bugs = {
		url: "https://github.com/csstree/csstree/issues"
	};
	var dependencies = {
		"mdn-data": "2.0.14",
		"source-map": "^0.6.1"
	};
	var description = "A tool set for CSS: fast detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations";
	var devDependencies = {
		"@rollup/plugin-commonjs": "^11.0.2",
		"@rollup/plugin-json": "^4.0.2",
		"@rollup/plugin-node-resolve": "^7.1.1",
		coveralls: "^3.0.9",
		eslint: "^6.8.0",
		"json-to-ast": "^2.1.0",
		mocha: "^6.2.3",
		nyc: "^14.1.1",
		rollup: "^1.32.1",
		"rollup-plugin-terser": "^5.3.0"
	};
	var engines = {
		node: ">=8.0.0"
	};
	var files = [
		"data",
		"dist",
		"lib"
	];
	var
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
this.addNotesStyles(page.notes, page, ruleList, rule, sheet);
			}

			return rule;
		}

		addMarginVars(margin, list, item) {
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
this.addNotesStyles(page.notes, page, ruleList, rule, sheet);
			}

			return rule;
		}

		addMarginVars(margin, list, item) {
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

External Script Fetching

High
Category
Supply Chain
Content
echo "  Python:      brew install python3 (macOS) / apt install python3 (Ubuntu)"
    echo "  pikepdf:     pip install pikepdf pdfplumber --user"
    echo "  LibreOffice: brew install --cask libreoffice (macOS)"
    echo "  Tectonic:    curl -fsSL https://drop-sh.fullyjustified.net | sh"

    echo ""
    echo "=== Fix Version Mismatch ==="
Confidence
98% confidence
Finding
The script prints `curl -fsSL https://drop-sh.fullyjustified.net | sh`, which is a classic remote-script execution pattern with no integrity verification, pinning, or trust validation. In a setup/help context this is dangerous because users often copy-paste suggested commands verbatim, creating a high-impact supply-chain compromise path if the endpoint or transport is ever compromised.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill explicitly instructs the agent to use shell commands, dependency installers, and web-enabled tooling, but it does not declare any tool scope such as allowed-tools or permissions. That creates an authorization gap where an agent may invoke broad shell, environment inspection, and network-capable commands without an auditable least-privilege boundary, increasing the chance of unintended command execution or package installation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The SKILL.md contains multiple mandatory instructions written entirely in Chinese, including operational requirements and prohibitions, which effectively impose a specific language on skill operators. The file does not offer an opt-in language choice or explain that the skill is intentionally limited to Chinese-speaking users, so this is a natural-language locale policy concern.

Rp1

Medium
Category
MCP Rug Pull
Confidence
87% confidence
Finding
The instruction to run `npx playwright install chromium` relies on an unpinned package/tool resolution path, which can introduce supply-chain risk or inconsistent behavior across environments. If the resolved package version is unexpected or compromised, the skill can trigger execution of unreviewed code during installation.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/browser_helper.js:51