Back to skill

Security audit

Ppt Generator

Security checks for vulnerabilities and agentic risk

Overview

This PPT generator is mostly purpose-aligned, but it automatically publishes generated presentations to a public file-serving location and renders unescaped user text in an unsandboxed browser.

Review this skill before installing. Avoid using it for confidential presentations unless public upload is disabled or replaced with private local output. Pin and review dependencies, remove the public FileBrowser default, escape slide text before HTML rendering, disable JavaScript/network access during rendering, and run Chromium with proper sandboxing.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate-ppt.js:66
Finding
Unescaped User Input Executes as Active Content During Slide Rendering<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate-ppt.js:66-68, 87-88, 105-110`; additional affected code in `scripts/canvas-generator.js:179-180` **Vulnerability Type**: HTML injection with browser-context script execution **Risk Level**: High ### Vulnerable Code ```javascript function genHTML(topic, s, pn, total) { const isCover = pn===1, isEnd = pn > total-2; const title = isCover ? topic : (isEnd ? 'Thank You' : 'Part '+(pn-1)); const pts = isEnd ? ['Q&A','Contact'] : ['Key Point 1','Key Point 2','Key Point 3']; const tc = s.bg==='#FFFFFF'?'#333':'#fff'; return '<!DOCTYPE html><html><head><meta charset="UTF-8"><style>body{font-family:Inter,sans-serif;background:'+s.bg+';margin:0;width:1280px;height:720px;position:relative;overflow:hidden}.border{position:absolute;top:20px;left:20px;right:20px;bottom:20px;border:8px solid '+s.border+';border-radius:10px}.title{position:absolute;top:60px;left:80px;right:80px;height:100px;background:'+s.accent[0]+';border:6px solid '+s.border+';border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:48px;font-weight:bold;color:#000}.content{position:absolute;top:220px;left:80px;right:80px;bottom:80px;padding:30px;font-size:24px;line-height:1.8;color:'+tc+';background:rgba(0,0,0,0.3);border-radius:10px}.content ul{list-style:none;padding:0}.content li{padding:15px 0;border-bottom:2px dashed '+s.accent[1]+'}.footer{display:none}</style></head><body><div class="border"></div><div class="title">'+title+'</div><div class="content"><ul>'+pts.map(p=>'<li>'+p+'</li>').join('')+'</ul></div><div class="footer"></div></body></html>'; } ``` ```javascript if(args[i]==='--topic'&&args[i+1]) topic=args[++i]; ``` ```javascript for(let i=1;i<=total;i++) fs.writeFileSync( path.join(OUTPUT_DIR,'slide_'+i+'.html'), genHTML(topic,s,i,total) ); const puppeteer = require('/tmp/node_modules/puppeteer'); const browser = await puppeteer.launch({ head ...[truncated 3572 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Encode every user-controlled value before inserting it into HTML. At minimum, escape `&`, `<`, `>`, `"`, and `'`. ```javascript function escapeHTML(value) { return String(value) .replaceAll('&', '&amp;') .replaceAll('<', '&lt;') .replaceAll('>', '&gt;') .replaceAll('"', '&quot;') .replaceAll("'", '&#39;'); } const safeTitle = escapeHTML(title); ``` 2. Apply the same encoding to `title` and `subtitle` in `canvas-generator.js`. 3. Prefer DOM APIs such as `textContent` over string concatenation when constructing presentation content. 4. Disable JavaScript when rendering static presentation HTML: ```javascript await page.setJavaScriptEnabled(false); ``` 5. Use Puppeteer request interception to deny all network requests not strictly required for rendering: ```javascript await page.setRequestInterception(true); page.on('request', request => { const url = new URL(request.url()); if (url.protocol === 'file:') { request.continue(); } else { request.abort(); } }); ``` 6. Remove remote font imports or package required fonts locally so network access can remain disabled. 7. Run Chromium as a dedicated unprivileged user with its sandbox enabled. Remove `--no-sandbox` rather than relying on the browser process as a security boundary. 8. Validate input length and reject control characters or malformed values to reduce denial-of-service and parser edge cases. 9. Add tests using payloads containing HTML tags, event handlers, scripts, iframes, and remote resource URLs, confirming they appear only as literal slide text. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:34
Finding
Mutable and Unpinned Third-Party Dependencies Are Installed and Executed<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:34-52` **Vulnerability Type**: Software supply-chain exposure through unpinned npm packages and container images **Risk Level**: Medium ### Vulnerable Code ```markdown | Tool | Install | Purpose | |------|---------|---------| | Node.js | pre-installed | Runtime | | puppeteer | `npm install puppeteer` | Screenshot capture | | pptxgenjs | `npm install pptxgenjs` | PPTX generation | ``` ```bash # Install Node dependencies cd /tmp && npm install puppeteer pptxgenjs # Deploy FileBrowser docker run -d --name filebrowser \ -v /path/to/share:/srv \ -p 127.0.0.1:8080:80 \ filebrowser/filebrowser:latest ``` ### Technical Analysis The documented installation procedure does not pin exact versions of `puppeteer` or `pptxgenjs`, and the project contains no audited lockfile. Each installation can therefore resolve a different package version and transitive dependency graph. The FileBrowser deployment similarly uses the mutable `latest` tag. A tag can be moved to a different image after this project has been reviewed, meaning the effective executable content is not fixed by the audited source tree. npm packages may run installation lifecycle scripts, and both Node dependencies are subsequently loaded and executed by `generate-ppt.js`. The FileBrowser container is granted access to the host directory mounted at `/srv`. Consequently, a compromised package release, registry account, transitive dependency, or container tag could introduce code that is absent from the reviewed project. No evidence establishes that the named dependencies are currently malicious. The finding concerns the unsafe, non-reproducible dependency acquisition process. ### Attack Path 1. A dependency publisher account, transitive dependency, npm registry path, or container publishing pipeline is compromised, or a future release introduces malicious behavior. 2. A user follows the documented command `npm install puppeteer pptxgen ...[truncated 1136 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a `package.json` that pins reviewed dependency versions rather than installing unconstrained latest releases. 2. Commit a generated lockfile and install with: ```bash npm ci ``` 3. Review and pin transitive dependencies through the lockfile. Use automated vulnerability and integrity monitoring while treating scanner output as one part of the review process. 4. Consider disabling npm lifecycle scripts during installation when compatible with the selected packages: ```bash npm ci --ignore-scripts ``` If Puppeteer requires an installation script, explicitly document and review that requirement instead of enabling all scripts without evaluation. 5. Pin FileBrowser to a reviewed semantic version and immutable image digest: ```bash docker run ... filebrowser/filebrowser:<reviewed-version>@sha256:<reviewed-digest> ``` 6. Use a dedicated, least-privileged service account and mount only the required publication directory. Prefer a read-only mount where write access is unnecessary. 7. Do not expose FileBrowser publicly without authentication, authorization, TLS, and a deliberate publication policy. 8. Establish a controlled update procedure that reviews release notes, source changes, package integrity, and container provenance before changing pinned versions or digests. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill claims AI-powered generation, preview confirmation, and smart automated design, but the behavior appears more limited and also includes undeclared publication of generated files to a public directory. The dangerous aspect is not the marketing exaggeration itself, but that users may be misled about automation, review checkpoints, and external exposure of potentially sensitive presentation content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The skill claims AI-powered generation, preview confirmation, and smart automated design, but the behavior appears more limited and also includes undeclared publication of generated files to a public directory. The dangerous aspect is not the marketing exaggeration itself, but that users may be misled about automation, review checkpoints, and external exposure of potentially sensitive presentation content.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly describes uploading generated PPTX files to FileBrowser and returning a public download link, but does not warn users that their presentation content may become externally accessible. In the context of presentations, this can expose confidential business, educational, or personal data through unintended public sharing.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The example trigger "Make me a PPT about AI" is presented as the way to invoke the skill, but the document does not define any narrower activation constraints or exclusion conditions. Because this phrasing is close to ordinary conversational requests, it could cause unintended invocation in general chat contexts.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The user-facing description is entirely in Chinese and presents the skill's behavior and instructions only in that language, without indicating optional language support or a justified region-specific limitation. This can violate language/locale policy when a skill effectively requires a specific language without user opt-in.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The manifest advertises one-click automatic upload to a file hosting service and also mentions network-based color search, but it does not clearly warn users that presentation content may be transmitted off-device. Because PPTs often contain sensitive business, educational, or personal material, silent or poorly disclosed transmission creates a meaningful confidentiality and privacy risk.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The usage trigger phrase is very broad and conversational, making accidental invocation likely during normal user interaction. In a skill that can generate files, invoke other skills, and upload outputs to a file hosting service, unintended activation could lead to unwanted processing or data handling without deliberate user intent.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The usage field instructs users to say a Chinese phrase to invoke the skill and does not present alternatives for other languages or indicate that language selection is optional. This is a natural-language locale constraint embedded in the manifest without opt-in or justification.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The file header says it is a 'Canvas Design Generator' that uses the Canvas API to generate artistic slide images, and the function comment repeats that it generates slide images. In reality, there is no Canvas API usage or image rendering; the code builds an HTML template string with CSS and writes it to disk as .html.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The top-level description is written as a Chinese-only product description and the generated slide styling hardcodes Chinese font choices, signaling a language-specific behavior without offering the user a locale or language choice. The policy allows locale constraints only when explicitly documented and justified or when the user can opt in, which is not present here.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The generated HTML imports Google Fonts from an external URL, which creates unintended network egress and a third-party dependency during slide rendering. In a skill advertised as local, one-click PPT generation with no API key needed, this can leak usage metadata, break in offline/restricted environments, and expand the attack surface if remote resources are tampered with or blocked.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest advertises a PPT generator that exports to PPTX, but this script produces and saves an HTML file named art_slide_<n>.html under a hard-coded output directory. That behavior is materially different from the claimed export format and suggests the implementation only emits HTML slide templates rather than PPT/PPTX content.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The script emits user-facing status messages in Chinese (for example, `[搜索]`), and additional console output later is also fixed to Chinese, with no indication that users can choose another language. This is a natural-language policy concern because the skill imposes a locale/language preference without opt-in or justification.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The code persists generator state to `/root/.openclaw/workspace/data/ppt-generator-state.json` via `fs.writeFileSync`, but there is no nearby comment, prompt, or explicit disclosure that user input-derived state will be stored on disk. Although some console logs describe progress, they do not warn about persistent state storage.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The generated PPTX is written directly into a public file-serving directory and the script prints a publicly accessible download URL. If presentation content includes sensitive or proprietary material, this exposes it to unintended parties without access controls, consent, or an explicit warning, making data leakage the primary risk.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The natural-language instructions and option descriptions in the script comments are written only in Chinese, with no indication that users may choose another language. This can violate language/locale policy when a skill imposes a specific language without opt-in or documented justification.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The wrapper changes the working directory to /tmp before invoking the Node script, which introduces an attacker-influenced filesystem context into execution. /tmp is world-writable on most systems, so any relative file access, temporary file handling, module resolution edge case, or output path logic in the downstream script may be redirected or manipulated unexpectedly.

Missing User Warnings

Low
Confidence
84% confidence
Finding
Mentioning online color search without a privacy warning implies possible network access during processing, which may transmit user prompts, themes, or derived presentation metadata off-system. While the impact is limited compared with full document upload, it still creates unexpected data egress and trust concerns.

Missing User Warnings

Low
Confidence
88% confidence
Finding
This shell script changes directory and invokes a Node process, which is a subprocess execution covered by the missing-warning rule for code files. While the file comments describe usage, they do not explicitly warn the user that the script will execute another program, and there is no confirmation prompt or runtime disclosure.