Back to skill

Security audit

Awesome Deck Pdf Check

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but its PDF exporter runs user-selected HTML in Chromium with the browser sandbox disabled and has under-scoped install and temp-file risks users should review.

Install only if you are comfortable reviewing the exporter and running it on trusted HTML. Avoid rendering HTML from untrusted sources, prefer pinned dependencies and a lockfile, avoid sudo unless an administrator approves it, and run the exporter in an isolated workspace or container because it disables Chromium sandboxing and deletes fixed temporary paths named _pdf_pages and _slides.html.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/export_pdf.js:109
Finding

Chromium Sandbox Disabled While Rendering User-Selectable HTML

Content
View full analysis

Vulnerability Details

File Location: scripts/export_pdf.js, lines 109–146
Vulnerability Type: Unsafe browser security configuration
Risk Level: High

Vulnerable Code

javascript
return puppeteer.launch({
  headless: true,
  executablePath,
  args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
});

The resulting browser instance later loads a user-selectable HTML file:

javascript
const page = await browser.newPage();
await page.setViewport({ width: W, height: H, deviceScaleFactor: 2 });
const filePath = path.resolve(process.cwd(), HTML_FILE);
await page.goto(`file://${filePath}`, { waitUntil: 'networkidle0' });

Technical Analysis

The exporter explicitly disables both principal Chromium sandbox mechanisms through --no-sandbox and --disable-setuid-sandbox. These flags are not required for the declared task of rendering HTML slides under a properly configured, unprivileged environment.

The input path comes from process.argv[2], allowing the user or an invoking process to select the HTML document rendered by Chromium. JavaScript remains enabled, and no request interception prevents the document from loading remote scripts, images, frames, or other resources.

Although browser JavaScript does not inherently receive unrestricted filesystem access, disabling the Chromium sandbox removes an important containment boundary. If malicious HTML exercises a Chromium vulnerability, exploitation can occur with the operating-system privileges of the Node.js process rather than being constrained by the browser sandbox.

Attack Path

  1. An attacker supplies, modifies, or convinces a user to render a malicious HTML slide deck.
  2. The user invokes node export_pdf.js malicious.html.
  3. The script starts Chromium with its sandbox explicitly disabled.
  4. Chromium loads the attacker-controlled document with JavaScript enabled.
  5. The document may conta ...[truncated 829 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove --no-sandbox and --disable-setuid-sandbox.
  2. Run Chromium as a dedicated, unprivileged user with a writable profile and functioning browser sandbox.
  3. If the deployment environment cannot support Chromium sandboxing, run the exporter inside a hardened container or virtual machine with:
    • No sensitive host-directory mounts.
    • A read-only root filesystem where practical.
    • Dropped Linux capabilities.
    • Resource and process limits.
    • No host network access unless explicitly required.
  4. Disable JavaScript with page.setJavaScriptEnabled(false) when generated decks do not require scripts.
  5. Add request interception and allow only required file: resources. Block http:, https:, ws:, and wss: requests by default during PDF export.
  6. Resolve and validate the HTML path against an explicitly permitted project directory.
  7. Keep Chromium and Puppeteer pinned and promptly updated for browser security fixes.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/export_pdf.js:158
Finding

Predictable Temporary Paths Permit Data Loss and Symlink Attacks

Content
View full analysis

Vulnerability Details

File Location: scripts/export_pdf.js, lines 158–219
Vulnerability Type: Unsafe temporary-file and directory handling
Risk Level: Medium

Vulnerable Code

javascript
const imgDir = path.resolve(process.cwd(), '_pdf_pages');
if (fs.existsSync(imgDir)) fs.rmSync(imgDir, { recursive: true });
fs.mkdirSync(imgDir);

The script also creates, overwrites, and deletes another fixed path:

javascript
const tmpHtml = path.resolve(process.cwd(), '_slides.html');
fs.writeFileSync(tmpHtml,
  `<!DOCTYPE html><html><head><meta charset="utf-8"><style>` +
  `*{margin:0;padding:0;box-sizing:border-box}body{background:#000}` +
  `@media print{@page{size:${W}px ${H}px;margin:0}body{-webkit-print-color-adjust:exact;print-color-adjust:exact}}` +
  `</style></head><body>${slides}</body></html>`
);

await overlayPage.goto(`file://${tmpHtml}`, { waitUntil: 'networkidle0' });
await new Promise(r => setTimeout(r, 800));
await overlayPage.pdf({
  path: path.resolve(process.cwd(), OUT_FILE),
  width: `${W}px`, height: `${H}px`,
  printBackground: true,
  margin: { top: 0, right: 0, bottom: 0, left: 0 }
});

await browser.close();
fs.rmSync(imgDir, { recursive: true });
fs.unlinkSync(tmpHtml);

Technical Analysis

The exporter uses the fixed names _pdf_pages and _slides.html in the current working directory. It does not verify that these paths were created by the current process, are ordinary files or directories, or are not symbolic links.

Before rendering, _pdf_pages is recursively deleted if it already exists. This can destroy legitimate user data occupying that path. In a shared or attacker-writable working directory, predictable names also enable race conditions and symbolic-link manipulation around file creation, overwrite, and cleanup.

The fixed _slides.html path is overwritten without e ...[truncated 1520 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create a unique private temporary directory with fs.mkdtempSync(path.join(os.tmpdir(), 'html-ppt-to-pdf-')).
  2. Store all intermediate HTML and PNG files inside that unique directory.
  3. Create temporary files using exclusive flags such as flag: 'wx' where applicable.
  4. Before destructive operations, use fs.lstatSync() and reject symbolic links or unexpected filesystem object types.
  5. Track only paths created by the current execution and never recursively remove a pre-existing project path.
  6. Place cleanup in a try/finally block so failures do not leave sensitive intermediate files behind.
  7. Generate the output PDF separately from temporary files and avoid overwriting an existing output unless the user explicitly permits it.
  8. Prevent concurrent runs from sharing temporary resources by using per-process random names.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:51
Finding

Unpinned Dependencies and Mutable Installation Commands

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 51–68; also present in README.md, lines 49–51, and references/install.md, lines 60–97
Vulnerability Type: Unpinned third-party executable dependencies
Risk Level: Medium

Vulnerable Code

bash
# Option A: skip Chromium download, install separately
npm install puppeteer --ignore-scripts
npx puppeteer browsers install chrome

# Option B: use puppeteer-core (no bundled Chrome download)
npm install puppeteer-core

# Option C: install system Chrome first, then run script
# macOS: brew install --cask google-chrome
# Linux: sudo apt install chromium-browser
npm install puppeteer-core

Other project instructions similarly recommend mutable package installations:

bash
npm install puppeteer
pip install python-pptx

Technical Analysis

The installation instructions retrieve unspecified current versions of Puppeteer, Puppeteer Core, Python PPTX, Chromium, and related components. The project provides no lockfile, exact version constraints, cryptographic hashes, or registry restrictions.

npm install puppeteer may execute package lifecycle scripts and download a browser binary. The npx puppeteer command may resolve and execute package code from the configured registry. The Python command also resolves a mutable dependency set without hashes. These actions expand the Skill's effective codebase beyond the audited repository.

The identified package names appear legitimate, and the audit found no evidence of intentional typosquatting or a malicious package. The risk arises from non-reproducible installation and reliance on mutable upstream artifacts rather than from a confirmed compromised dependency.

Attack Path

  1. A user follows the documented installation commands.
  2. The package manager resolves the latest available package and transitive dependencies from its configured registry.
  3. A compromised registry account, ...[truncated 1198 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin exact Puppeteer, Puppeteer Core, and Python PPTX versions that have been tested and reviewed.
  2. Commit an npm lockfile containing integrity metadata and instruct users to run npm ci rather than an unconstrained npm install.
  3. Use a Python requirements file with exact versions and hashes, installed with pip install --require-hashes -r requirements.txt.
  4. Avoid unpinned npx execution. Invoke a locally installed, lockfile-controlled executable instead.
  5. Document approved package registries and recommend disabling unexpected registry overrides.
  6. Verify downloaded browser artifacts through the package manager's supported integrity controls.
  7. Add automated dependency vulnerability and provenance checks to the release process.
  8. Separate privileged operating-system dependency installation from normal Skill execution and require explicit user approval before administrative commands are run.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (21)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**`export_pdf.js` auto-detects Chrome in this order:**

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**`export_pdf.js` auto-detects Chrome in this order:**

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**`export_pdf.js` auto-detects Chrome in this order:**

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**`export_pdf.js` auto-detects Chrome in this order:**

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**`export_pdf.js` auto-detects Chrome in this order:**

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**`export_pdf.js` auto-detects Chrome in this order:**

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are very broad (make me a nice PPT, build a deck, generate presentation) and can cause the skill to activate in contexts the user did not specifically intend. In agent systems, overbroad activation increases the chance of unexpected external fetching, file handling, or command guidance being surfaced without adequate user awareness.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The skill instructs use of npx puppeteer, which resolves and executes a package version that is not pinned. That creates a supply-chain risk: a future compromised or incompatible release could be fetched and run at execution time, especially in automated agent environments where users may follow the instruction verbatim.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
87% confidence
Finding

The skill includes guidance to run sudo apt install chromium-browser, which normalizes privileged command execution during setup. In an agent or user-followed workflow, encouraging sudo increases risk because it can lead to unnecessary elevation and system modification, especially when paired with package-install instructions users may not independently validate.

Content

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

Option C: install system Chrome first, then run script

macOS: brew install --cask google-chrome

Linux: sudo apt install chromium-browser

npm install puppeteer-core

text
**Do NOT fall back to wkhtmltopdf, pdfkit, weasyprint, or any other tool.**

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The instructions mandate appending Chinese fallbacks and later troubleshooting specifically directs adding 'PingFang SC', which imposes a locale-specific typography choice without offering user choice or documenting why this locale preference is required. This can violate language/locale policy when applied universally rather than conditionally based on user content needs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file title and instructions are written entirely in Chinese and direct users to fill the template in that locale, without offering any language or locale choice. This can violate language/locale policy when the skill is expected to be usable across user preferences unless the restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
85% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/install.md (reported line 26)May include surrounding context.

text
3. Reference it in your project's `CLAUDE.md` or system prompt:

Skills path: ~/.claude/skills/html-ppt-to-pdf/SKILL.md

text

---

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/install.md (reported line 26)May include surrounding context.

text
3. Reference it in your project's `CLAUDE.md` or system prompt:

Skills path: ~/.claude/skills/html-ppt-to-pdf/SKILL.md

text

---

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/install.md (reported line 39)May include surrounding context.

text
3. Reference it in your project's `CLAUDE.md` or system prompt:

Skills path: ~/.claude/skills/html-ppt-to-pdf/SKILL.md

text

---

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 · references/install.md (reported line 77)May include surrounding context.

Linux

bash
# Puppeteer may need extra Chrome deps
sudo apt-get install -y libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 \
  libxi6 libxtst6 libnss3 libcups2 libxss1 libxrandr2 libasound2 libatk1.0-0 \
  libgtk-3-0
npm install puppeteer

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.

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 · scripts/export_pdf.js (reported line 103)May include surrounding context.

js
❌ No Chrome/Chromium found. Please install one of the following:

  macOS:   brew install --cask google-chrome
  Linux:   sudo apt install chromium-browser
  npm:     npm install puppeteer   (downloads bundled Chromium)
`);
    process.exit(1);

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script opens a user-supplied local HTML file in a real Chrome instance via a file:// URL and waits for network idle, which allows any embedded JavaScript and remote subresources in that HTML to execute during export. In this skill context, that means exporting an untrusted deck can trigger network requests, local file interaction behaviors available to the browser context, and unintended code execution within the browser session without any warning to the operator.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The description advertises website URL style cloning but does not warn that analyzing external URLs may involve fetching remote content or taking browser screenshots. This reduces user transparency and can lead to unexpected network access or privacy issues when the skill is invoked.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The troubleshooting table instructs users to add 'PingFang SC' when Chinese text renders poorly, but the broader document also frames this fallback as a standard requirement rather than a user-selected locale option. This embeds a locale-specific preference into the workflow without clear opt-in or documented regional justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The document consistently presents all user-facing instructions in Chinese, but it does not indicate that the skill is region-specific or provide any opt-in or alternative language path. Under the policy, forcing a specific language without user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.