Back to skill

Security audit

Anima

Security checks for vulnerabilities and agentic risk

Overview

The skill’s video-generation purpose is mostly disclosed, but crafted script text, target IDs, paths, or CSV entries can reach shell commands and may execute local commands or overwrite files.

Review before installing. Only run this skill with scripts, CSV files, target IDs, and paths you fully trust, and prefer a sandboxed account. Avoid Feishu delivery or Gemini batch generation until the shell calls are replaced with safe argument-array subprocess calls or native HTTP APIs, and filenames/recipient IDs are validated.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (6)

T09 · Insecure Skill Coding Practices

Error
Location
run.js:93
Finding
Shell Command Injection Through the Target Identifier<![CDATA[ ## Vulnerability Details **File Location**: `run.js:93-95` **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```js if (targetId && !isPreview) { console.log(`🚀 [Anima] Uploading and sending to ${targetId}...`); try { // Pass targetId and video path to send_video_pro.js execSync(`node "${SEND_SCRIPT}" "${targetId}" "${FINAL_VIDEO}"`, { stdio: 'inherit' }); ``` ### Technical Analysis The user-controlled `--target` argument is interpolated into a command string passed to `execSync()`. Because `execSync()` executes the string through a system shell, enclosing the value in double quotes does not safely isolate it. A target containing a quote followed by shell syntax can terminate the intended argument and inject additional commands. No validation restricts the target to a legitimate Feishu identifier format. ### Attack Path 1. An attacker supplies a malicious value through `--target`. 2. Argument parsing stores the value in `targetId`. 3. The value is concatenated into the command at line 95. 4. An embedded quote escapes the quoted argument. 5. The shell interprets the remaining content as commands. 6. The commands execute with the privileges of the Node.js process. For example, a target shaped like `" ; <command> ; #` could escape the argument context and execute an additional command. ### Impact Assessment Successful exploitation provides arbitrary command execution under the account running the Skill. The attacker could read or modify accessible files, obtain API credentials from the local environment or `.env` file, alter generated media, install additional payloads, or access other resources available to that account. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Replace shell-based execution with `execFileSync()` or `spawnSync()` and an argument array: ```js const { execFileSync } = require('child_process'); execFileSync( process.execPath, [SEND_SCRIPT, targetId, FINAL_VIDEO], { stdio: 'inherit' } ); ``` - Validate `targetId` against the exact Feishu identifier grammar and reject unexpected quotes, whitespace, control characters, or shell metacharacters. - Apply length limits to command-line values. - Avoid logging untrusted values without sanitizing control characters. - Run the Skill under a dedicated, minimally privileged operating-system account. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/director.js:45
Finding
Shell Command Injection Through TTS Script Text<![CDATA[ ## Vulnerability Details **File Location**: `src/director.js:45-47, 71-73` **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```js if (!apiKey) { console.warn("⚠️ Fish Audio Key missing! Falling back to macOS 'say' command."); execSync(`say -o "${wavPath}" --data-format=LEF32@24000 "${text}"`); } ``` The API-error fallback contains the same vulnerability: ```js try { execSync(curlCmd); } catch (e) { console.error("Fish Audio API failed:", e); // Fallback execSync(`say -o "${wavPath}" "${text}"`); } ``` ### Technical Analysis Scene text originates from the user-provided JSON script and is directly interpolated into a shell command. Double quotes around `${text}` are not sufficient shell escaping. Text containing a double quote, command substitution, or other shell syntax can change the command structure. The vulnerable path is reached when `FISH_AUDIO_KEY` is absent or when the Fish Audio `curl` command fails. Therefore, an attacker may exploit an installation without Fish Audio configuration or wait for, induce, or benefit from an API failure. ### Attack Path 1. An attacker provides a script containing malicious shell syntax in a scene's `text` field. 2. `run.js` writes the script to a temporary JSON file. 3. `director.js` parses the file and passes `line.text` to `generateAudio()`. 4. Fish Audio is unavailable, unconfigured, or returns an error. 5. `generateAudio()` interpolates the text into the macOS `say` command. 6. The shell executes the injected command with the Skill process's privileges. ### Impact Assessment Exploitation permits arbitrary local command execution. The resulting access includes all files, credentials, environment variables, network destinations, and processes available to the user running the Skill. Because script text is an expected external input, this is a direct trust-boundary violation. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Do not execute TTS text through a shell. - Invoke `say` with an argument array: ```js const { execFileSync } = require('child_process'); execFileSync('say', [ '-o', wavPath, '--data-format=LEF32@24000', text ]); ``` - Use a native Node.js HTTP client for Fish Audio rather than constructing a `curl` command. - Validate that every scene is an object and that `text` is a string with an appropriate maximum length. - Treat API fallback paths as security-critical and subject them to the same input-safety requirements as primary paths. - Consider disabling the fallback on unsupported platforms instead of invoking a shell command. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/send_video_pro.js:29
Finding
Multiple Shell Injection Boundaries in Feishu Delivery<![CDATA[ ## Vulnerability Details **File Location**: `src/send_video_pro.js:29-76` **Vulnerability Type**: OS command injection through arguments, paths, environment values, and API-derived values **Risk Level**: High ### Vulnerable Code The application credentials are embedded in a shell command: ```js const tokenCmd = `curl -s -X POST -H "Content-Type: application/json; charset=utf-8" -d '{"app_id":"${APP_ID}","app_secret":"${APP_SECRET}"}' https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal`; const tokenRes = runCurl(tokenCmd); const token = tokenRes.tenant_access_token; ``` The externally supplied video path is embedded in FFmpeg and curl commands: ```js const durationCmd = `ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${VIDEO_PATH}"`; const durationSec = parseFloat(execSync(durationCmd).toString().trim()); execSync(`ffmpeg -y -i "${VIDEO_PATH}" -ss 00:00:00.500 -vframes 1 "${COVER_PATH}"`, { stdio: 'ignore' }); const uploadVideoCmd = `curl -s -X POST -H "Authorization: Bearer ${token}" -H "Content-Type: multipart/form-data" -F "file_name=anima_demo.mp4" -F "file_type=mp4" -F "duration=${durationMs}" -F "file=@${VIDEO_PATH}" -F "size=${size}" https://open.feishu.cn/open-apis/im/v1/files`; ``` The target identifier is embedded in the message request: ```js const sendCmd = `curl -s -X POST -H "Authorization: Bearer ${token}" -H "Content-Type: application/json; charset=utf-8" -d '{"receive_id": "${TARGET_ID}", "msg_type": "media", "content": "${content}"}' "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id"`; const sendRes = runCurl(sendCmd); ``` All of these commands reach: ```js function runCurl(cmd) { try { const res = execSync(cmd, { maxBuffer: 10 * 1024 * 1024 }).toString(); return JSON.parse(res); } catch (e) { console.error('Curl error:', e); return null; } } ``` ### Technical Analysis The script constructs shell commands by concatenat ...[truncated 1573 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace curl with Node.js `fetch()` and `FormData`; construct JSON bodies with `JSON.stringify()` rather than shell quoting. - Invoke FFprobe and FFmpeg through `execFileSync()` or `spawnSync()` with argument arrays: ```js const duration = execFileSync('ffprobe', [ '-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', VIDEO_PATH ]).toString().trim(); ``` - Validate `TARGET_ID` against the documented Feishu chat-ID format. - Canonicalize `VIDEO_PATH`, require a regular `.mp4` file, and restrict it to an approved output directory where feasible. - Reject symbolic links when the application expects a generated local file. - Never concatenate secrets or bearer tokens into shell commands, where they may also become visible in process listings or error output. - Check for null API results before dereferencing them, such as `tokenRes?.tenant_access_token`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/batch_generator.js:75
Finding
Shell Command Injection Through Gemini API Configuration<![CDATA[ ## Vulnerability Details **File Location**: `src/batch_generator.js:75-76` **Vulnerability Type**: OS command injection through configuration data **Risk Level**: Medium ### Vulnerable Code ```js const cmd = `curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${apiKey}" -H "Content-Type: application/json" -d @"${payloadPath}"`; const response = JSON.parse(execSync(cmd, { maxBuffer: 50 * 1024 * 1024 }).toString()); ``` ### Technical Analysis `apiKey` is loaded from `GEMINI_API_KEY` and inserted into a double-quoted shell argument without shell-safe encoding. A crafted configuration value containing a double quote and shell syntax can escape the URL argument. Although environment configuration is usually administrator-controlled, `.env` files are an input boundary and may be populated by deployment automation, copied configuration, or secret-management systems. Configuration values must not become executable shell content. The API key is also exposed as part of curl's URL argument, potentially making it visible in process listings while curl is running. ### Attack Path 1. An attacker influences `GEMINI_API_KEY` through the environment or the project `.env` file. 2. The batch generator interpolates the value into the curl command. 3. A quote terminates the URL argument. 4. The system shell interprets subsequent syntax as a command. 5. The command executes with the batch generator's privileges. ### Impact Assessment Exploitation permits arbitrary command execution with the privileges of the account generating sprites. The attacker may read local images and credentials, modify project files, or tamper with generated assets. The current construction also unnecessarily exposes the API key to local process inspection. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Send the Gemini request using Node.js `fetch()` rather than curl: ```js const response = await fetch( `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${encodeURIComponent(apiKey)}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: payload } ); ``` - Prefer an authentication header if supported, preventing the key from appearing in the URL. - Validate configuration values and reject control characters. - Ensure `.env` permissions restrict access to the Skill account. - Avoid logging full subprocess errors when they may expose secrets. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/batch_generator.js:35
Finding
Path Traversal Allows Arbitrary File Writes During Sprite Generation<![CDATA[ ## Vulnerability Details **File Location**: `src/batch_generator.js:35-36, 80-87` **Vulnerability Type**: Path traversal and arbitrary file write **Risk Level**: Medium ### Vulnerable Code ```js function generate(row) { const output = path.resolve(__dirname, '../assets/sprites', row.Filename); const prompt = `Same image, change facial expression to ${row.Prompt}. Keep clothes and background exactly same.`; ``` The resolved path is later written without confinement validation: ```js if (imagePart) { const imageData = (imagePart.inlineData || imagePart.inline_data).data; fs.writeFileSync(output, Buffer.from(imageData, 'base64')); return true; } else { console.error(`No image in Gemini response for ${row.ID}`); return false; } ``` ### Technical Analysis `row.Filename` is read from the customizable `assets/production_plan.csv`. `path.resolve()` normalizes the path but does not confine it to `assets/sprites`. Values containing `../` components or an absolute path can therefore escape the intended output directory. The application neither validates the filename grammar nor checks that the canonical destination remains under the sprite directory before calling `fs.writeFileSync()`. ### Attack Path 1. An attacker supplies or modifies a production-plan CSV entry. 2. The entry sets `Filename` to a traversal path such as `../../some-file` or to an absolute path. 3. `path.resolve()` produces a destination outside `assets/sprites`. 4. Gemini returns image data. 5. `fs.writeFileSync()` creates or overwrites the attacker-selected path, provided the process has write permission. ### Impact Assessment An attacker can overwrite arbitrary files writable by the Skill process with Gemini-returned bytes. The scope may include project configuration, application assets, user files, or other data owned by the execution account. Overwriting strategically selected files could cause denial of service or facilitate later code execution. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Restrict filenames to simple PNG basenames: ```js const filenamePattern = /^[A-Za-z0-9_-]+\.png$/; if ( typeof row.Filename !== 'string' || path.basename(row.Filename) !== row.Filename || !filenamePattern.test(row.Filename) ) { throw new Error('Invalid sprite filename'); } ``` - Resolve and verify the destination against the approved directory: ```js const spriteDir = path.resolve(__dirname, '../assets/sprites'); const output = path.resolve(spriteDir, row.Filename); if (!output.startsWith(spriteDir + path.sep)) { throw new Error('Sprite path escapes the output directory'); } ``` - Refuse to overwrite existing files unless explicitly authorized. - Check for symbolic links and use exclusive file creation where appropriate. - Replace the simplistic CSV parser with a standards-compliant parser and validate every field against a schema. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/batch_generator.js:71
Finding
Predictable Temporary Payload File Enables Disclosure and Symlink Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `src/batch_generator.js:71-78` **Vulnerability Type**: Insecure temporary file handling **Risk Level**: Medium ### Vulnerable Code ```js // Write payload to temp file to avoid shell escaping issues const payloadPath = path.resolve(__dirname, '../temp/_gen_payload.json'); fs.writeFileSync(payloadPath, payload); const cmd = `curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${apiKey}" -H "Content-Type: application/json" -d @"${payloadPath}"`; const response = JSON.parse(execSync(cmd, { maxBuffer: 50 * 1024 * 1024 }).toString()); // Clean up payload try { fs.unlinkSync(payloadPath); } catch(e) {} ``` ### Technical Analysis The generator always uses the predictable path `temp/_gen_payload.json`. The file contains the full base image encoded in Base64 together with the generation prompt. `fs.writeFileSync()` follows existing symbolic links and does not use exclusive creation. A local attacker able to access the project directory can pre-create the path as a symbolic link, causing the process to truncate and overwrite another file writable by the Skill account. Cleanup is not placed in a `finally` block. If curl execution or JSON parsing fails, the payload may remain on disk. Default file permissions may also allow unintended local users to read it depending on the process umask and directory permissions. ### Attack Path 1. A local attacker predicts the fixed `_gen_payload.json` path. 2. The attacker monitors the path for creation or pre-creates it as a symbolic link to another writable file. 3. The batch generator writes the prompt and Base64 image payload. 4. The attacker reads the temporary content, or the symlink target is truncated and overwritten. 5. If request execution or parsing fails, cleanup is skipped and the payload remains available. ### Impact Assessment The vulnerability can disclose the complete source sprite and generati ...[truncated 243 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Prefer sending the payload directly with a native HTTP client so no temporary file is required. - If a temporary file is unavoidable: - Create a private temporary directory with `fs.mkdtempSync()`. - Open the file with exclusive creation flags. - Set permissions to `0o600`. - Reject symbolic links. - Remove the file and directory in a `finally` block. - Example hardening pattern: ```js const os = require('os'); const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'anima-')); const payloadPath = path.join(tempDir, 'payload.json'); try { fs.writeFileSync(payloadPath, payload, { flag: 'wx', mode: 0o600 }); // Perform request without invoking a shell. } finally { fs.rmSync(tempDir, { recursive: true, force: true }); } ``` - Ensure the project temporary directory is not writable by untrusted users. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The skill advertises media generation but also documents Feishu authentication, local file processing, cover extraction, and message sending to chat targets. In context, this expands the trust boundary from local rendering to external delivery and secret handling; if unnoticed, it can enable unauthorized data exfiltration or unintended outbound communication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill advertises media generation but also documents Feishu authentication, local file processing, cover extraction, and message sending to chat targets. In context, this expands the trust boundary from local rendering to external delivery and secret handling; if unnoticed, it can enable unauthorized data exfiltration or unintended outbound communication.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill advertises media generation but also documents Feishu authentication, local file processing, cover extraction, and message sending to chat targets. In context, this expands the trust boundary from local rendering to external delivery and secret handling; if unnoticed, it can enable unauthorized data exfiltration or unintended outbound communication.

Ae1

High
Category
analysis-evasion
Content
- `src/batch_generator.js`: Batch sprite generator. Uses Gemini image generation to produce sprite variants.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `src/batch_generator.js`: Batch sprite generator. Uses Gemini image generation to produce sprite variants.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `src/batch_generator.js`: Batch sprite generator. Uses Gemini image generation to produce sprite variants.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `src/batch_generator.js`: Batch sprite generator. Uses Gemini image generation to produce sprite variants.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
const { execSync } = require('child_process');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
const { execSync } = require('child_process');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
const { execSync } = require('child_process');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
const { execSync } = require('child_process');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// Load .env from skill folder only (least-privilege: never read parent .env)
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
const fs = require('fs');
const { execSync } = require('child_process');
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill documents use of shell execution, environment variables, external APIs, and outbound delivery, but declares no explicit tool scope or allowed-tools policy. This weakens containment and review because an agent may grant broader runtime capabilities than the skill's stated interface suggests, increasing the chance of unintended command execution or secret access.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
### 1. System Dependencies
- **ffmpeg** (required for video processing):
  - macOS: `brew install ffmpeg`
  - Linux: `sudo apt install ffmpeg`
  - Windows: Download/Install FFmpeg and add to PATH.

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

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
### 1. System Dependencies
- **ffmpeg** (required for video processing):
  - macOS: `brew install ffmpeg`
  - Linux: `sudo apt install ffmpeg`
  - Windows: Download/Install FFmpeg and add to PATH.

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

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The documented fallback to the macOS `say` command introduces undeclared shell-dependent behavior outside the primary API-based design. Hidden or automatic execution of local system commands increases attack surface, complicates sandboxing, and may produce unexpected data handling or command invocation on the host.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The file uses child_process.execSync to invoke shell commands for both network access and sleeping. Although the stated purpose of the skill does involve image generation and external API calls, constructing a shell command with interpolated data such as the API key introduces unnecessary command-execution risk and expands the attack surface beyond what is needed.

External Transmission

Medium
Category
Data Exfiltration
Content
const payloadPath = path.resolve(__dirname, '../temp/_gen_payload.json');
    fs.writeFileSync(payloadPath, payload);

    const cmd = `curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${apiKey}" -H "Content-Type: application/json" -d @"${payloadPath}"`;
    const response = JSON.parse(execSync(cmd, { maxBuffer: 50 * 1024 * 1024 }).toString());

    // Clean up payload
Confidence
94% confidence
Finding
The script transmits locally sourced content, including a base image and user-controlled prompt data from the CSV, to an external Google Gemini endpoint. External transmission is expected for this skill's purpose, but it still poses data exposure risk, especially because the request is made through curl with the API key embedded in the command line where it may be exposed to process inspection or logs.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
run.js:22

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/batch_generator.js:76

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/director.js:23

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/send_video_pro.js:20