Back to skill

Security audit

acestep-simplemv

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real music-video renderer, but its rendering script builds shell commands from user-controlled paths and options, creating a practical local command-execution risk.

Install only if you are comfortable running a local Remotion/Node rendering tool and can control the inputs. Avoid rendering untrusted audio filenames, output paths, codec values, or browser paths until the shell execution is changed to argument-array execution. Prefer npm ci from a reviewed lockfile, consider using the official npm registry, and run rendering in a low-privilege workspace because copied audio and rendered outputs may remain on disk.

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/render.mjs:159
Finding
Command Injection Through the Audio File Path## Vulnerability Details **File Location**: `scripts/render.mjs:159-162` **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```js function getAudioDuration(filePath) { try { const result = execSync( `ffprobe -v error -show_entries format=duration -of csv=p=0 "${filePath}"`, {encoding: 'utf-8'} ).trim(); return parseFloat(result); } catch { return null; } } ``` ### Technical Analysis The `filePath` value is derived from the user-controlled `--audio` argument and inserted directly into a shell command passed to `execSync()`. Although the value is enclosed in double quotes, embedded quotes, command substitutions, and shell metacharacters are not escaped. Node.js executes the string through a command shell. Consequently, a malicious audio filename can terminate the quoted argument and append another shell command. The wrapper verifies that the supplied audio file exists, but this does not prevent exploitation because filenames on supported operating systems can contain quotes and shell metacharacters. ### Attack Path 1. An attacker creates or supplies an accessible audio file whose path contains shell syntax. 2. The attacker passes that path through the documented `--audio` option. 3. `resolveFilePath()` resolves the path without removing shell metacharacters. 4. The audio is copied into `public/`, preserving its basename. 5. `getAudioDuration()` embeds the resulting path in the `ffprobe` command string. 6. `execSync()` invokes a shell, which interprets the injected syntax and executes the appended command. A conceptual malicious filename could contain syntax equivalent to: ```text song.mp3"; attacker-command; # ``` ### Impact Assessment Successful exploitation provides arbitrary command execution with the privileges of the user or service running the Skill. The attacker could read or modify files accessible to that accoun ...[truncated 293 chars]
Remediation
## Remediation Suggestions Replace shell-string execution with an API that passes each argument directly to the executable: ```js import {execFileSync} from 'child_process'; function getAudioDuration(filePath) { try { const result = execFileSync( 'ffprobe', [ '-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', filePath, ], { encoding: 'utf-8', shell: false, } ).trim(); const duration = Number.parseFloat(result); return Number.isFinite(duration) && duration > 0 ? duration : null; } catch { return null; } } ``` Additional hardening should include: - Resolve `ffprobe` to a trusted executable or use a controlled executable search path. - Verify that the input is a regular file before processing it. - Apply file size and media-duration limits to reduce denial-of-service exposure. - Do not attempt to make shell interpolation safe through manual escaping; avoid invoking a shell entirely.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/render.mjs:311
Finding
Command Injection Through Remotion Render Arguments## Vulnerability Details **File Location**: `scripts/render.mjs:311-334` **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```js const cmd = [ 'npx remotion render', 'MusicVideo', `"${output}"`, `--props="${propsFile}"`, `--codec=${codec}`, '--log=error', browserExe ? `--browser-executable="${browserExe}"` : '', chromeMode !== 'headless-shell' ? `--chrome-mode=${chromeMode}` : '', ].filter(Boolean).join(' '); console.log(`\nRendering video...`); console.log(` Audio: ${args.audio}`); console.log(` Title: ${inputProps.title}`); console.log(` Duration: ${duration.toFixed(1)}s`); console.log(` Lyrics: ${lyrics.length} lines`); console.log(` Output: ${output}`); console.log(` Codec: ${codec}`); if (browserExe) console.log(` Browser: ${browserExe}`); if (chromeMode !== 'headless-shell') console.log(` Chrome mode: ${chromeMode}`); console.log(''); try { const result = execSync(cmd, {encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe']}); ``` ### Technical Analysis The Remotion command is assembled as a single shell string. Several values originate from command-line arguments or the environment: - `output` originates from `--output`. - `codec` originates from `--codec`. - `browserExe` can originate from `--browser` or `BROWSER_EXECUTABLE`. These values are interpolated without shell-safe argument handling. The `codec` option is documented as accepting only four values, but no allowlist validation is implemented. Quoting `output` and `browserExe` does not mitigate the issue because an embedded quote can end the quoted argument. ### Attack Path 1. An attacker invokes the Skill with a malicious `--output`, `--codec`, or browser path. 2. Argument parsing stores the supplied value without security validation. 3. The value is incorporated into the `cmd` array as text. 4. The array is joined into one command string. 5. `execSync( ...[truncated 996 chars]
Remediation
## Remediation Suggestions Do not construct the Remotion invocation as a shell command. Invoke a fixed executable with an argument array and disable shell processing: ```js import {execFileSync} from 'child_process'; const allowedCodecs = new Set(['h264', 'h265', 'vp8', 'vp9']); if (!allowedCodecs.has(codec)) { throw new Error(`Unsupported codec: ${codec}`); } const remotionArgs = [ 'remotion', 'render', 'MusicVideo', output, `--props=${propsFile}`, `--codec=${codec}`, '--log=error', ]; if (browserExe) { remotionArgs.push(`--browser-executable=${browserExe}`); } if (chromeMode !== 'headless-shell') { remotionArgs.push(`--chrome-mode=${chromeMode}`); } const result = execFileSync( process.platform === 'win32' ? 'npx.cmd' : 'npx', remotionArgs, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], shell: false, } ); ``` Further hardening should include: - Prefer Remotion's programmatic rendering API where practical. - Enforce the codec allowlist before execution. - Validate `duration` and `offset` as finite values within reasonable limits. - Restrict output paths to an approved output directory when callers are untrusted. - Resolve and validate the browser executable as a regular executable file. - Run rendering in a sandboxed, non-privileged account with filesystem and network restrictions.

T08 · Insecure Dependencies

Warning
Location
scripts/package-lock.json:21
Finding
Dependency Installation Relies Predominantly on a Third-Party Registry Mirror## Vulnerability Details **File Location**: `scripts/package-lock.json:21-28` **Additional Locations**: `SKILL.md:21-26`, `scripts/package-lock.json:1352-1357` **Vulnerability Type**: Software supply-chain exposure **Risk Level**: Medium ### Vulnerable Code The setup instructions direct users to execute dependency installation: ```bash # 1. Check Node.js node --version # 2. Install npm dependencies cd {project_root}/{.claude or .codex}/skills/acestep-simplemv/scripts && npm install # 3. Check ffprobe ffprobe -version ``` The lockfile resolves most audited packages through a third-party mirror: ```json "node_modules/@babel/parser": { "version": "7.24.1", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.24.1.tgz", "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "license": "MIT", "bin": { "parser": "bin/babel-parser.js" } } ``` The dependency graph also includes a package with an installation script: ```json "node_modules/esbuild": { "version": "0.25.0", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.0.tgz", "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "hasInstallScript": true, "license": "MIT" } ``` ### Technical Analysis The committed lockfile directs npm to retrieve most artifacts from `registry.npmmirror.com` rather than the official npm registry. This introduces an additional supply-chain trust dependency. Integrity hashes provide significant protection against accidental or opportunistic package substitution, but installation still relies on the availability, security, and correct behavior of the mirror. The instructions use `npm install` rather than `npm ci`. Direct dependencies also use caret ranges in `package.json`, although the current lockfile fixes resolved ver ...[truncated 1725 chars]
Remediation
## Remediation Suggestions - Regenerate and review the lockfile using the official npm registry: ```bash npm config set registry https://registry.npmjs.org/ rm package-lock.json npm install ``` - Commit the reviewed lockfile and document `npm ci` rather than `npm install` for reproducible deployment. - Pin direct dependency versions exactly instead of using caret ranges where stable, controlled builds are required. - Use a trusted internal registry proxy if organizational policy requires mirroring, with provenance verification and access controls. - Review packages that execute lifecycle scripts and use `npm ci --ignore-scripts` where feasible, followed by explicit execution of only required installation steps. - Run dependency installation in an isolated, non-privileged build environment without unnecessary credentials. - Add automated dependency vulnerability, provenance, and lockfile-drift checks to the release process.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (28)

Known Vulnerable Dependency: browserslist==4.28.1 — 2 advisory(ies): CVE-2026-73088 (Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.); CVE-2026-73089 (Browserslist: Unbounded memory growth (no cache eviction) via distinct query res)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: extract-zip==2.0.1 — 2 advisory(ies): CVE-2026-19693 (extract-zip allows arbitrary file writes through symlink archive entries); CVE-2026-56876 (extract-zip unvalidated symlink path traversal)

High
Category
Supply Chain
Confidence
93% confidence
Finding
extract-zip has known arbitrary file write and symlink traversal issues during archive extraction. In this dependency tree it is pulled by @remotion/renderer, so if the renderer or related tooling ever downloads and extracts archives in the local environment, a crafted archive could overwrite files outside the intended directory and compromise the host or build workspace.

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: nanoid==3.3.11 — 3 advisory(ies): CVE-2026-67214 (nanoid: non-secure generators can loop indefinitely with negative size); CVE-2026-67213 (nanoid: custom generators can loop indefinitely when size is zero); CVE-2026-73086 (nanoid: Integer Overflow or Wraparound)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: postcss==8.5.6 — 4 advisory(ies): CVE-2026-45623 (PostCSS: Arbitrary file read and information disclosure via attacker-controlled ); CVE-2026-69153 (PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi); CVE-2026-41305 (PostCSS has XSS via Unescaped </style> in its CSS Stringify Output) +1 more

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: serialize-javascript==6.0.2 — 2 advisory(ies): GHSA-5c6j-r48x-rmvq (Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.to); CVE-2026-34043 (Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like)

High
Category
Supply Chain
Confidence
88% confidence
Finding
serialize-javascript has a documented RCE class issue and CPU exhaustion risk when serializing crafted objects in affected versions. It is present through terser-webpack-plugin/webpack in the build toolchain, so if untrusted data is ever passed into bundling or serialization paths, compromise of the build process or denial of service is possible.

Known Vulnerable Dependency: ws==8.17.1 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
86% confidence
Finding
ws has high-severity advisories for memory disclosure and memory-exhaustion DoS in WebSocket handling. It is brought in by @remotion/renderer, and if any renderer/studio/server component opens WebSocket endpoints during local rendering or development, a reachable vulnerable WebSocket stack could expose memory or allow resource exhaustion.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill documents use of environment variables and external executables, but it does not declare any explicit tool scope or permissions boundaries. In an agent setting, missing scope metadata can cause the skill to be invoked with broader ambient capabilities than intended, increasing the chance of unreviewed access to environment configuration or local system resources.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The manifest description says to use the skill when users mention "MV generation, music video rendering, creating video from audio/lyrics, or visualizing songs." Several of these phrases are broad natural-language descriptions rather than a narrowly defined invocation scope, which can cause the skill to match general conversation about music or videos.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
If ffprobe is not available, install ffmpeg (which includes ffprobe):
- **Windows**: `choco install ffmpeg` or download from https://ffmpeg.org/download.html and add to PATH
- **macOS**: `brew install ffmpeg`
- **Linux**: `sudo apt-get install ffmpeg` (Debian/Ubuntu) or `sudo dnf install ffmpeg` (Fedora)

## Quick Start
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
The script builds and executes `npx remotion render`, which allows `npx` to resolve and potentially fetch an unpinned package version at runtime. In a supply-chain compromise or dependency confusion scenario, this could execute attacker-controlled code on the host during rendering. The skill context increases risk because this is a media-processing CLI likely to be run locally with access to user files and network connectivity.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The note that absolute-path audio files are automatically copied into `public/` indicates implicit file duplication of user-supplied content without an explicit warning or consent step. In a local agent workflow, this can create unintended retention, broader accessibility to sensitive media within the project tree, and accidental disclosure if the directory is later served or shared.

Known Vulnerable Dependency: ajv==6.12.6 — 1 advisory(ies): CVE-2025-69873 (ajv has ReDoS when using `$data` option)

Low
Category
Supply Chain
Confidence
60% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: ajv==8.17.1 — 1 advisory(ies): CVE-2025-69873 (ajv has ReDoS when using `$data` option)

Low
Category
Supply Chain
Confidence
60% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: baseline-browser-mapping==2.9.19 — 1 advisory(ies): CVE-2026-45819 (baseline-browser-mapping process termination on invalid input causes denial of s)

Low
Category
Supply Chain
Confidence
60% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: postcss-selector-parser==7.1.1 — 1 advisory(ies): CVE-2026-9358 (postcss-selector-parser allows denial of service through uncontrolled AST recurs)

Low
Category
Supply Chain
Confidence
60% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: webpack==5.96.1 — 2 advisory(ies): CVE-2025-68157 (webpack buildHttp HttpUriPlugin allowedUris bypass via HTTP redirects → SSRF + c); CVE-2025-68458 (webpack buildHttp: allowedUris allow-list bypass via URL userinfo (@) leading to)

Low
Category
Supply Chain
Confidence
60% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "@remotion/cli": "^4.0.417",
    "@remotion/media-utils": "^4.0.417",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"type": "commonjs",
  "dependencies": {
    "@remotion/cli": "^4.0.417",
    "@remotion/media-utils": "^4.0.417",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "remotion": "^4.0.417"
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"dependencies": {
    "@remotion/cli": "^4.0.417",
    "@remotion/media-utils": "^4.0.417",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "remotion": "^4.0.417"
  },
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"@remotion/cli": "^4.0.417",
    "@remotion/media-utils": "^4.0.417",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "remotion": "^4.0.417"
  },
  "devDependencies": {
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"@remotion/media-utils": "^4.0.417",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "remotion": "^4.0.417"
  },
  "devDependencies": {
    "@types/react": "^19.2.13",
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"remotion": "^4.0.417"
  },
  "devDependencies": {
    "@types/react": "^19.2.13",
    "typescript": "^5.9.3"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "devDependencies": {
    "@types/react": "^19.2.13",
    "typescript": "^5.9.3"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The script writes input properties, including lyrics, title, subtitle, and credit text, into a temporary .render-props.json file on disk. Although it later deletes the file, the user-facing usage comments and earlier logging do not disclose this intermediate file write before it happens.