Back to skill

Security audit

Slide Editor

Security checks for vulnerabilities and agentic risk

Overview

This slide editor mostly does what it says, but its install and open workflows create avoidable command-execution risk.

Review before installing. Avoid the documented curl|bash or PowerShell iex Bun installation commands, avoid --open on files with untrusted names until the shell execution is fixed, work on copies of presentations, and treat injected/exported HTML as active JavaScript-bearing documents. There is no evidence of deliberate exfiltration or deception in the artifact, but the command-execution and HTML-injection risks are significant enough to require review.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:19
Finding

Remote installer scripts are downloaded and executed without integrity verification

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:19-29 and SKILL.md:196-206
Vulnerability Type: Remote payload retrieval and execution
Risk Level: Critical

The installation instructions contain the following commands in both the English and Chinese sections:

bash
# macOS/Linux
curl -fsSL https://bun.sh/install | bash

# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"

# Or use npm
npm install -g bun

Technical Analysis

The first two installation methods download mutable content from an external server and immediately execute it through Bash or PowerShell. There is no version pinning, checksum verification, signature validation, or separate inspection step.

Although bun.sh is the documented Bun domain, these commands make the code that is ultimately executed dependent on the remote server at installation time. The effective payload can therefore change after the Skill has been reviewed. Compromise of the hosting infrastructure, domain, release pipeline, or network trust chain could turn the documented installation step into arbitrary code execution.

Installing a runtime through an unverified pipe-to-shell command exceeds the minimum risk necessary for the presentation-editing functionality. Safer package-manager and verified-release installation methods are available.

Attack Path

  1. A user or Agent follows the installation instructions.
  2. curl or irm retrieves the current installer from the external domain.
  3. The response is passed directly to Bash or PowerShell without being saved or verified.
  4. The interpreter executes every command supplied by the remote response.
  5. A compromised installer can access or modify anything available to the invoking user and may request or exploit elevated privileges.

Impact Assessment

The remote payload receives arbitrary command execution with the privileges of the user running the installation command. It could ...[truncated 299 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove all pipe-to-shell and PowerShell iex installation examples.
  • Prefer an operating-system package manager or another trusted distribution mechanism.
  • If direct download is necessary, pin an explicit Bun version and provide the expected cryptographic checksum.
  • Require users to download the artifact first, validate its signature or checksum, and only then execute it as a separate step.
  • Document that installation should be performed as an unprivileged user.
  • Avoid requesting sudo, administrator access, or global installation unless it is demonstrably required.
  • Keep one canonical installation section to avoid insecure instructions being retained in a duplicated translation.

T09 · Insecure Skill Coding Practices

Error
Location
inject.ts:174
Finding

Command injection through shell-interpolated output file URL

Content
View full analysis

Vulnerability Details

File Location: inject.ts:174-188
Vulnerability Type: OS command injection
Risk Level: High

typescript
if (shouldOpen) {
  const fileUrl = `file://${outputFile}?edit=1`;
  console.log(`\nOpening: ${fileUrl}`);

  try {
    // macOS
    execSync(`open "${fileUrl}"`, { stdio: 'ignore' });
  } catch {
    // Try xdg-open for Linux
    try {
      execSync(`xdg-open "${fileUrl}"`, { stdio: 'ignore' });
    } catch {
      // Try start for Windows
      try {
        execSync(`start "" "${fileUrl}"`, { stdio: 'ignore' });
      } catch {
        console.log(`Please open manually: ${fileUrl}`);
      }
    }
  }
}

Technical Analysis

outputFile is derived from command-line input, including the positional HTML path or the value supplied after -o. The code interpolates that value into strings passed to execSync. String-form execSync invokes a shell, so shell metacharacters contained in a crafted path can be interpreted as command syntax.

Wrapping the value in double quotes is insufficient because a filename can itself contain a double quote on relevant filesystems. resolve() only converts a path to an absolute normalized path; it does not perform shell escaping or argument separation.

All three platform fallbacks use the same unsafe construction. The vulnerable branch is reached when the --open option is supplied.

Attack Path

  1. An attacker causes the injector to process an HTML file or -o destination with a crafted filename containing a quote and shell metacharacters.
  2. The user or automation invokes the injector with --open.
  3. The application constructs fileUrl from the attacker-influenced path.
  4. The URL is interpolated into an execSync command string.
  5. The shell parses the injected metacharacters and executes the attacker-selected command.

This is particularly relevant when filenames originate from downloaded ar ...[truncated 522 chars]

Remediation
View remediation

Remediation Suggestions

  • Replace string-form execSync with spawnSync or execFileSync and pass the URL as a separate argument.
  • Explicitly disable shell processing.
  • Use Node's pathToFileURL() rather than manually constructing a file:// URL.
  • Select the platform-specific launcher through process.platform rather than attempting commands through nested shell calls.
  • Validate that -o has a following value before resolving it.
  • Add tests using paths containing spaces, quotes, command separators, Unicode characters, and leading hyphens.

Example approach:

typescript
import { spawnSync } from 'child_process';
import { pathToFileURL } from 'url';

const fileUrl = pathToFileURL(outputFile);
fileUrl.searchParams.set('edit', '1');

const command = process.platform === 'darwin'
  ? 'open'
  : process.platform === 'win32'
    ? 'cmd'
    : 'xdg-open';

const commandArgs = process.platform === 'win32'
  ? ['/c', 'start', '', fileUrl.href]
  : [fileUrl.href];

spawnSync(command, commandArgs, { stdio: 'ignore', shell: false });

On Windows, prefer a dedicated URL-opening API or library so that cmd.exe can be avoided entirely.

T09 · Insecure Skill Coding Practices

Warning
Location
src/index.ts:803
Finding

Public text API inserts unsanitized HTML into presentation elements

Content
View full analysis

Vulnerability Details

File Location: src/index.ts:803-811, with unsafe history restoration at src/index.ts:941-947 and src/index.ts:983-989
Vulnerability Type: DOM-based and persistent HTML injection
Risk Level: Medium

Primary vulnerable sink:

typescript
setTextContent(id: string, content: string): void {
  const el = document.querySelector(`[data-editor-id="${id}"]`);
  if (!el) return;

  const oldContent = el.innerHTML;
  el.innerHTML = content;

  this.pushHistory({ type: 'text', elementId: id, from: oldContent, to: content });
}

Unsafe content is also restored by undo and redo:

typescript
case 'text':
  if (action.from !== undefined) {
    el.innerHTML = action.from as string;
  }
  break;
typescript
case 'text':
  if (action.to !== undefined) {
    el.innerHTML = action.to as string;
  }
  break;

Technical Analysis

The globally exposed setTextContent() method describes its input as text but assigns it to innerHTML. As a result, markup is parsed rather than treated as literal text. An attacker-controlled value can introduce active elements, event-handler attributes, external resource references, or other dangerous HTML.

The injected markup is retained in the history stack and reinserted during undo or redo. The export functionality serializes the resulting document, so malicious markup can also persist into an exported presentation. Whether a particular payload executes can depend on browser behavior and the presentation's Content Security Policy, but no sanitizer or allowlist is applied by this method.

Attack Path

  1. Untrusted content reaches the globally exposed window.__openclawEditor.setTextContent() API, such as through Agent-generated presentation text or another script in the presentation.
  2. The API writes the value to innerHTML.
  3. The browser parses attacker-controlled markup.
  4. Active content, such as an eve ...[truncated 785 chars]
Remediation
View remediation

Remediation Suggestions

  • Change setTextContent() to assign through textContent.
  • If rich text is required, provide a separately named API such as setRichTextContent().
  • Sanitize rich HTML with a well-maintained sanitizer configured with a strict allowlist.
  • Reject scripts, inline event handlers, dangerous URL schemes, embedded frames, forms, and unnecessary external-resource elements.
  • Store a sanitized representation in history rather than retaining the original unsafe value.
  • Sanitize or validate presentation content again at export time as a defense-in-depth measure.
  • Adopt an appropriate Content Security Policy for hosted presentations, avoiding unsafe-inline.
  • Add tests for event-handler attributes, SVG payloads, dangerous links, embedded resources, and undo/redo persistence.

T09 · Insecure Skill Coding Practices

Note
Location
src/index.ts:1152
Finding

Cross-origin messages can enable or disable the editor without authorization

Content
View full analysis

Vulnerability Details

File Location: src/index.ts:1152-1160
Vulnerability Type: Unauthenticated cross-window message handling
Risk Level: Low

typescript
// Listen for postMessage activation
window.addEventListener('message', (event) => {
  if (event.data?.type === 'OPENCLAW_EDITOR_ENABLE') {
    editor.enable();
  } else if (event.data?.type === 'OPENCLAW_EDITOR_DISABLE') {
    editor.disable();
  }
});

Technical Analysis

The message listener acts on message data without checking event.origin or event.source. Any parent, opener, frame, or other window capable of obtaining a reference to the presentation window can send a matching message.

The exposed message actions only toggle editor state; the handler does not directly expose arbitrary API method invocation. Consequently, this is less severe than a general cross-origin command channel, but it still crosses an authorization boundary and allows external pages to alter application state.

Attack Path

  1. A user opens the presentation from a hostile page, or the presentation is embedded in a frame.
  2. The hostile window obtains a reference to the presentation window.
  3. It sends a message containing OPENCLAW_EDITOR_ENABLE or OPENCLAW_EDITOR_DISABLE.
  4. The listener accepts the message regardless of its origin or source.
  5. The editor state changes without user authorization.

Impact Assessment

An attacker can unexpectedly expose or hide editor controls and interfere with the presentation-editing workflow. Enabling the interface may facilitate accidental edits or UI confusion, while repeated state changes can cause denial of normal interaction. Based on the reviewed handler, the message alone does not grant filesystem access or arbitrary code execution.

Remediation
View remediation

Remediation Suggestions

  • Validate event.origin against an explicit, narrowly scoped allowlist.
  • Validate event.source against the expected parent, opener, or controller window.
  • Use a capability token or authenticated initialization handshake if cross-origin control is required.
  • Ignore malformed messages and validate the complete message schema.
  • Remove the listener if remote activation is not necessary for the declared functionality.
  • Consider requiring a direct user gesture before enabling editing controls.

T08 · Insecure Dependencies

Warning
Location
package.json:33
Finding

Dependency versions are not locked for reproducible installation

Content
View full analysis

Vulnerability Details

File Location: package.json:33-38; installation is instructed at SKILL.md:33-38 and SKILL.md:210-215
Vulnerability Type: Dependency supply-chain exposure
Risk Level: Medium

json
"devDependencies": {
  "@types/node": "^20.0.0",
  "esbuild": "^0.20.0",
  "puppeteer": "^24.39.1",
  "typescript": "^5.4.0"
},

The documented installation flow is:

bash
# Clone or download this project
cd slide-editor

# Install dependencies and build (use bun, not npm)
bun install
bun run build

Technical Analysis

The audited directory contains no dependency lockfile, and every declared dependency uses a caret range. A fresh bun install can therefore resolve package versions different from those reviewed or previously tested.

Package installation may also run dependency lifecycle behavior. The audit did not identify a confirmed malicious dependency in the manifest; the vulnerability is the absence of deterministic resolution and integrity controls, which increases exposure to a compromised or unexpectedly changed upstream release.

puppeteer is a particularly large development dependency and may perform installation-time artifact handling. If it is not necessary to build the distributed editor, retaining it increases supply-chain surface.

Attack Path

  1. A user follows the documented bun install instruction.
  2. Bun resolves the permitted dependency ranges from the package registry.
  3. A newer, compromised, or otherwise unexpected package version is selected.
  4. Package installation or subsequent build execution runs code from that dependency.
  5. The dependency code receives the privileges of the user performing the installation or build.

Impact Assessment

A compromised dependency can execute code during installation or build with the invoking user's privileges. This can affect source files, generated bundles, user-accessible data, and build ou ...[truncated 224 chars]

Remediation
View remediation

Remediation Suggestions

  • Generate and commit the Bun lockfile.
  • Use exact dependency versions rather than caret ranges where practical.
  • Require frozen-lockfile installation in automated and documented workflows.
  • Review resolved package integrity metadata before release.
  • Remove puppeteer and any other dependency not required for development, testing, or building.
  • Audit package lifecycle scripts and disable them during installation when they are not required.
  • Add automated dependency vulnerability and provenance scanning.
  • Update dependencies through reviewed pull requests rather than allowing silent resolution changes during installation.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (36)

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

The installation instructions fetch and immediately execute a remote script using curl ... | bash, which grants arbitrary code execution to whatever is served from that URL at install time. If the upstream site, network path, or DNS is compromised, users running the documented command could execute attacker-controlled code on their machine.

Content

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

bash
# macOS/Linux
curl -fsSL https://bun.sh/install | bash

# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"

Chaining Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

The | bash pattern is a command-chaining technique that directly pipes network-fetched content into a shell, removing the chance for review before execution. In a skill intended for AI-agent use, this is especially dangerous because agents or users may copy commands verbatim, leading to immediate system compromise if the fetched content is malicious.

Content

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

bash
# macOS/Linux
curl -fsSL https://bun.sh/install | bash

# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

The Chinese installation section repeats the same remote-script execution pattern, exposing another audience to arbitrary code execution during setup. Duplicating the unsafe command in multilingual documentation increases the chance of unsafe execution rather than mitigating it.

Content

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

bash
# macOS/Linux
curl -fsSL https://bun.sh/install | bash

# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"

Chaining Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

The repeated | bash/equivalent installation flow in the Chinese section preserves the same unsafe command-chaining behavior and broadens exposure. Because the skill is for offline-capable local editing and agent control, installation commands are likely to be run on user workstations where compromise has high practical impact.

Content

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

bash
# macOS/Linux
curl -fsSL https://bun.sh/install | bash

# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · test/clean-test.html (reported line 76)May include surrounding context.

html
</script>


<!-- SLIDE_EDITOR_START -->
<script>
// SLIDE_EDITOR_BUNDLE
"use strict";var SlideEditor=(()=>{var P=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var Y=(h,e)=>{for(var t in e)P(h,t,{get:e[t],enumerable:!0})},F=(h,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of U(e))!X.call(h,i)&&i!==t&&P(h,i,{get:()=>e[i],enumerable:!(r=O(e,i))||r.enumerable});return h};var K=h=>F(P({},"__esModule",{value:!0}),h);var _={};Y(_,{SlideEditor:()=>z});var x=class{state;onSelectionChange=null;constructor(e){this.state=e}setOnSelectionChange(e){this.onSelectionChange=e}select(e,t=!1){t||this.state.selectedIds.clear(),this.state.selectedIds.add(e),this.updateVisualSelection(),this.notifyChange()}deselect(e){this.state.selectedIds.delete(e),this.updateVisualSelection(),this.notifyChange()}deselectAll(){this.state.selectedIds.clear(),this.updateVisualSelection(),this.notifyChange()}isSelected(e){return this.state.selectedIds.has(e)}getSelectedIds(){return Array.from(this.state.selectedIds)}hasSelection(){return this.state.selectedIds.size>0}updateVisualSelection(){document.querySelectorAll("[data-editor-id]").forEach(e=>{e.classList.remove("slide-editor-selected")}),this.state.selectedIds.forEach(e=>{let t=document.querySelector(`[data-editor-id="${e}"]`);t&&t.classList.add("slide-editor-selected")})}notifyChange(){if(this.onSelectionChange){let e=this.getSelectedIds().map(t=>this.getElementInfo(t)).filter(t=>t!==null);this.onSelectionChange(e)}}getElementInfo(e){let t=document.querySelector(`[data-editor-id="${e}"]`);if(!t)return null;let r=t.getBoundingClientRect(),o=t.closest(".slide")?.getBoundingClientRect()||{left:0,top:0};return{id:e,type:this.getElementType(t),x:r.left-o.left,y:r.top-o.top,width:r.width,height:r.height,content:t.textContent||void 0,src:t.src||void 0,styles:this.extractStyles(t)}}getElementType(e){let t=e.tagName.toLowerCase();return t==="img"?"image":
...[truncated 26 chars]

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · test/debug.html (reported line 92)May include surrounding context.

html
</script>


<!-- SLIDE_EDITOR_START -->
<script>
// SLIDE_EDITOR_BUNDLE
"use strict";var SlideEditor=(()=>{var P=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var Y=(h,e)=>{for(var t in e)P(h,t,{get:e[t],enumerable:!0})},F=(h,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of X(e))!U.call(h,r)&&r!==t&&P(h,r,{get:()=>e[r],enumerable:!(i=O(e,r))||i.enumerable});return h};var K=h=>F(P({},"__esModule",{value:!0}),h);var V={};Y(V,{SlideEditor:()=>z});var x=class{state;onSelectionChange=null;constructor(e){this.state=e}setOnSelectionChange(e){this.onSelectionChange=e}select(e,t=!1){t||this.state.selectedIds.clear(),this.state.selectedIds.add(e),this.updateVisualSelection(),this.notifyChange()}deselect(e){this.state.selectedIds.delete(e),this.updateVisualSelection(),this.notifyChange()}deselectAll(){this.state.selectedIds.clear(),this.updateVisualSelection(),this.notifyChange()}isSelected(e){return this.state.selectedIds.has(e)}getSelectedIds(){return Array.from(this.state.selectedIds)}hasSelection(){return this.state.selectedIds.size>0}updateVisualSelection(){document.querySelectorAll("[data-editor-id]").forEach(e=>{e.classList.remove("slide-editor-selected")}),this.state.selectedIds.forEach(e=>{let t=document.querySelector(`[data-editor-id="${e}"]`);t&&t.classList.add("slide-editor-selected")})}notifyChange(){if(this.onSelectionChange){let e=this.getSelectedIds().map(t=>this.getElementInfo(t)).filter(t=>t!==null);this.onSelectionChange(e)}}getElementInfo(e){let t=document.querySelector(`[data-editor-id="${e}"]`);if(!t)return null;let i=t.getBoundingClientRect(),s=t.closest(".slide")?.getBoundingClientRect()||{left:0,top:0};return{id:e,type:this.getElementType(t),x:i.left-s.left,y:i.top-s.top,width:i.width,height:i.height,content:t.textContent||void 0,src:t.src||void 0,styles:this.extractStyles(t)}}getElementType(e){let t=e.tagName.toLowerCase();return t==="img"?"image":
...[truncated 26 chars]

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · test/presentation-clean.html (reported line 68)May include surrounding context.

html
showSlide(0);
  </script>

<!-- SLIDE_EDITOR_START -->
<script>
// SLIDE_EDITOR_BUNDLE
"use strict";var SlideEditor=(()=>{var w=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var q=(d,e)=>{for(var t in e)w(d,t,{get:e[t],enumerable:!0})},D=(d,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of P(e))!R.call(d,r)&&r!==t&&w(d,r,{get:()=>e[r],enumerable:!(i=z(e,r))||i.enumerable});return d};var N=d=>D(w({},"__esModule",{value:!0}),d);var B={};q(B,{SlideEditor:()=>M});var u=class{state;onSelectionChange=null;constructor(e){this.state=e}setOnSelectionChange(e){this.onSelectionChange=e}select(e,t=!1){t||this.state.selectedIds.clear(),this.state.selectedIds.add(e),this.updateVisualSelection(),this.notifyChange()}deselect(e){this.state.selectedIds.delete(e),this.updateVisualSelection(),this.notifyChange()}deselectAll(){this.state.selectedIds.clear(),this.updateVisualSelection(),this.notifyChange()}isSelected(e){return this.state.selectedIds.has(e)}getSelectedIds(){return Array.from(this.state.selectedIds)}hasSelection(){return this.state.selectedIds.size>0}updateVisualSelection(){document.querySelectorAll("[data-editor-id]").forEach(e=>{e.classList.remove("slide-editor-selected")}),this.state.selectedIds.forEach(e=>{let t=document.querySelector(`[data-editor-id="${e}"]`);t&&t.classList.add("slide-editor-selected")})}notifyChange(){if(this.onSelectionChange){let e=this.getSelectedIds().map(t=>this.getElementInfo(t)).filter(t=>t!==null);this.onSelectionChange(e)}}getElementInfo(e){let t=document.querySelector(`[data-editor-id="${e}"]`);if(!t)return null;let i=t.getBoundingClientRect(),o=t.closest(".slide")?.getBoundingClientRect()||{left:0,top:0};return{id:e,type:this.getElementType(t),x:i.left-o.left,y:i.top-o.top,width:i.width,height:i.height,content:t.textContent||void 0,src:t.src||void 0,styles:this.extractStyles(t)}}getElementType(e){let t=e.tagName.toLowerCase();return t==
...[truncated 26 chars]

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · test/presentation-debug.html (reported line 84)May include surrounding context.

html
</script>


<!-- SLIDE_EDITOR_START -->
<script>
// SLIDE_EDITOR_BUNDLE
"use strict";var SlideEditor=(()=>{var P=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var U=(p,e)=>{for(var t in e)P(p,t,{get:e[t],enumerable:!0})},F=(p,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of X(e))!Y.call(p,r)&&r!==t&&P(p,r,{get:()=>e[r],enumerable:!(i=O(e,r))||i.enumerable});return p};var K=p=>F(P({},"__esModule",{value:!0}),p);var V={};U(V,{SlideEditor:()=>k});var b=class{state;onSelectionChange=null;constructor(e){this.state=e}setOnSelectionChange(e){this.onSelectionChange=e}select(e,t=!1){t||this.state.selectedIds.clear(),this.state.selectedIds.add(e),this.updateVisualSelection(),this.notifyChange()}deselect(e){this.state.selectedIds.delete(e),this.updateVisualSelection(),this.notifyChange()}deselectAll(){this.state.selectedIds.clear(),this.updateVisualSelection(),this.notifyChange()}isSelected(e){return this.state.selectedIds.has(e)}getSelectedIds(){return Array.from(this.state.selectedIds)}hasSelection(){return this.state.selectedIds.size>0}updateVisualSelection(){document.querySelectorAll("[data-editor-id]").forEach(e=>{e.classList.remove("slide-editor-selected")}),this.state.selectedIds.forEach(e=>{let t=document.querySelector(`[data-editor-id="${e}"]`);t&&t.classList.add("slide-editor-selected")})}notifyChange(){if(this.onSelectionChange){let e=this.getSelectedIds().map(t=>this.getElementInfo(t)).filter(t=>t!==null);this.onSelectionChange(e)}}getElementInfo(e){let t=document.querySelector(`[data-editor-id="${e}"]`);if(!t)return null;let i=t.getBoundingClientRect(),o=t.closest(".slide")?.getBoundingClientRect()||{left:0,top:0};return{id:e,type:this.getElementType(t),x:i.left-o.left,y:i.top-o.top,width:i.width,height:i.height,content:t.textContent||void 0,src:t.src||void 0,styles:this.extractStyles(t)}}getElementType(e){let t=e.tagName.toLowerCase();return t==="img"?"image":
...[truncated 26 chars]

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · test/presentation.html (reported line 84)May include surrounding context.

html
</script>


<!-- SLIDE_EDITOR_START -->
<script>
// SLIDE_EDITOR_BUNDLE
"use strict";var SlideEditor=(()=>{var P=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var U=(p,e)=>{for(var t in e)P(p,t,{get:e[t],enumerable:!0})},F=(p,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of X(e))!Y.call(p,r)&&r!==t&&P(p,r,{get:()=>e[r],enumerable:!(i=O(e,r))||i.enumerable});return p};var K=p=>F(P({},"__esModule",{value:!0}),p);var V={};U(V,{SlideEditor:()=>k});var b=class{state;onSelectionChange=null;constructor(e){this.state=e}setOnSelectionChange(e){this.onSelectionChange=e}select(e,t=!1){t||this.state.selectedIds.clear(),this.state.selectedIds.add(e),this.updateVisualSelection(),this.notifyChange()}deselect(e){this.state.selectedIds.delete(e),this.updateVisualSelection(),this.notifyChange()}deselectAll(){this.state.selectedIds.clear(),this.updateVisualSelection(),this.notifyChange()}isSelected(e){return this.state.selectedIds.has(e)}getSelectedIds(){return Array.from(this.state.selectedIds)}hasSelection(){return this.state.selectedIds.size>0}updateVisualSelection(){document.querySelectorAll("[data-editor-id]").forEach(e=>{e.classList.remove("slide-editor-selected")}),this.state.selectedIds.forEach(e=>{let t=document.querySelector(`[data-editor-id="${e}"]`);t&&t.classList.add("slide-editor-selected")})}notifyChange(){if(this.onSelectionChange){let e=this.getSelectedIds().map(t=>this.getElementInfo(t)).filter(t=>t!==null);this.onSelectionChange(e)}}getElementInfo(e){let t=document.querySelector(`[data-editor-id="${e}"]`);if(!t)return null;let i=t.getBoundingClientRect(),o=t.closest(".slide")?.getBoundingClientRect()||{left:0,top:0};return{id:e,type:this.getElementType(t),x:i.left-o.left,y:i.top-o.top,width:i.width,height:i.height,content:t.textContent||void 0,src:t.src||void 0,styles:this.extractStyles(t)}}getElementType(e){let t=e.tagName.toLowerCase();return t==="img"?"image":
...[truncated 26 chars]

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README instructs users to inject the editor into existing HTML and supports auto-enable behavior, but it does not clearly warn that this modifies user files by adding executable JavaScript to presentations. In the context of an AI-agent-controllable editor, this increases the risk of accidental persistence of active editing code in shared or generated HTML, which may surprise users and expand the attack surface if applied to untrusted content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The AI agent integration example shows reading a bundle and inlining it directly into generated HTML, but it omits a warning that the output will contain executable JavaScript. Because this skill is explicitly designed for AI agent control, the lack of disclosure is more dangerous: agents may mass-produce or distribute HTML artifacts containing active script without operator awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The quick-start and workflow instructions tell the user to run an injector against an existing HTML file, but they do not clearly warn that the original file will be modified in place. This can lead to accidental corruption of source presentations, unintended persistence of injected editor code, or users editing a production artifact when they expected a temporary preview workflow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The delete-slide click handler directly calls this.editor.deleteSlide(current.index) and refreshes the UI with no confirmation dialog, warning message, or explanatory comment. Deleting a slide is a destructive operation, and this file provides no visible disclosure to the user before the action is performed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code automatically sets the editor locale using detectLocale() on startup, which enforces a language/locale choice based on browser settings rather than offering the user an explicit selection or opt-in. The policy for natural-language behavior requires avoiding forced language or locale decisions unless they are clearly documented and justified.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The editor listens for all postMessage events and toggles privileged editing behavior based solely on event.data.type, without validating event.origin or event.source. Any embedding page or opened window can trigger enable/disable, creating a cross-origin UI control channel that can alter document state, induce unwanted downloads/saves, and expose editing capabilities without user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file automatically calls window.__openclawEditor.enable() on load, which visibly rewrites the page into an editable mode, injects UI, and alters DOM element positioning. There is no confirmation prompt or user-facing disclosure near the auto-enable logic, so the file changes page behavior and editability without warning.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This HTML code automatically enables an in-page editor on load, exposing file-modifying actions such as delete, crop, add, and export/save without any user-facing warning, confirmation gate, or disclosure at activation time. Because the file is code and the editor performs potentially destructive content changes, the lack of any visible warning or confirmation for entering edit mode meets the missing user warnings criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The toolbar includes a delete action, and the editor also supports keyboard-triggered deletion, but there is no confirmation prompt, warning message, or explanatory comment aimed at the user before removing selected elements. Since deletion is a destructive operation in code, this lacks the user disclosure expected for safety-critical actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The navigator exposes a delete-slide control that removes slides, but the implementation provides no confirmation prompt or visible warning before the destructive action occurs. Removing an entire slide is irreversible from the user's perspective unless they know to use undo, so it should be disclosed or confirmed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The toolbar wires a direct delete action to this.editor.deleteSelected() and the navigator wires direct slide deletion to this.editor.deleteSlide(...), but there is no confirmation prompt, warning text, or user-facing disclosure around these destructive operations. Although undo exists, the file itself does not warn users that selected elements or entire slides can be deleted immediately.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The toolbar wires a delete action directly to this.editor.deleteSelected(), and the code also supports slide and element deletion elsewhere, but there is no confirmation prompt, warning text, or user-facing disclosure before the deletion occurs. Because deletion can remove user-authored slide content, this is a safety-relevant destructive operation lacking visible warning in the code.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The HTML document declares lang="zh-CN", which sets the page language to Simplified Chinese by default. Under the policy, forcing a specific language or locale without user opt-in is a natural-language policy violation unless the locale restriction is clearly justified, and no such justification appears in this file.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 27)May include surrounding context.

json
"skill.md"
  ],
  "devDependencies": {
    "@types/node": "^20.0.0",
    "esbuild": "^0.20.0",
    "puppeteer": "^24.39.1",
    "typescript": "^5.4.0"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 28)May include surrounding context.

json
],
  "devDependencies": {
    "@types/node": "^20.0.0",
    "esbuild": "^0.20.0",
    "puppeteer": "^24.39.1",
    "typescript": "^5.4.0"
  },

Unverifiable Dependency: esbuild has 2 known advisory(ies) (GHSA-67mh-4wv8-2f99 (esbuild enables any website to send any requests to the development server and r); GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
inject.ts:179