Back to skill

Security audit

Materials Cli

Security checks for vulnerabilities and agentic risk

Overview

The skill’s stated image/schema workflow is mostly coherent, but it depends on unreviewed local code that receives the OpenAI API key and has a Windows launcher pattern that can turn crafted arguments into shell commands.

Review this before installing, especially on Windows or in environments with sensitive OpenAI credentials. Prefer a release that includes or pins all dependency code, removes shell-based launching on Windows, validates render dimensions, and clearly documents what data is sent to the configured OpenAI-compatible endpoint.

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
bin/materials-cli.js:19
Finding

Windows Command Injection Through Shell-Enabled CLI Launcher

Content
View full analysis
{ ``` ### Technical Analysis The launcher appends untrusted command-line arguments directly to the arguments passed to `spawn()`. On Windows, it explicitly enables `shell: true`, causing Node.js to invoke the command through the platform shell rather than executing the Node binary directly. Arguments supplied for prompts, schema paths, output paths, or other CLI options may contain Windows shell metacharacters. When passed through the shell, these characters can be interpreted as command separators or redirection operators instead of remaining literal argument content. This creates a command-injection boundary between CLI input and `cmd.exe`. Although the executable path is fixed to `process.execPath`, that does not eliminate the risk because the untrusted values are included in the shell-parsed command line. ### Attack Path 1. An attacker supplies a crafted CLI argument, schema path, output path, or generation prompt containing Windows shell syntax. 2. A victim invokes `materials` on Windows with the attacker-controlled value. 3. The launcher copies the value from `process.argv.slice(2)` into the spawned argument list. 4. Because `shell` is enabled on Windows, the argument list is converted into a shell command line. 5. The shell interprets embedded metacharacters and executes the injected command. 6. The command runs with the same account and privileges as the user who launched the CLI. ### Impact Assessment Successful exploitation permits arbitrary command execution with the invoking user's privil ...[truncated 374 chars]
Remediation
View remediation
{ console.error(`Failed to launch CLI: ${error.message}`); process.exit(1); }); child.on('exit', (code, signal) => { if (signal) { process.kill(process.pid, signal); } else { process.exit(code ?? 1); } }); ``` Add Windows-specific tests containing spaces, quotes, ampersands, pipes, redirection characters, and command-substitution-like input to verify that all values remain literal arguments. ]]>

T08 · Insecure Dependencies

Warning
Location
package.json:34
Finding

Mutable Local Dependency Receives the OpenAI API Credential

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/commands/render.ts:53
Finding

Unbounded Canvas Dimensions Allow Resource-Exhaustion Denial of Service

Content
View full analysis
{ const schemaWithOptions = { ...schema, width: options.width ?? schema.width ?? 800, height: options.height ?? schema.height ?? 600, output: { type: (options.format === 'jpg' ? 'jpg' : 'png') as 'png' | 'jpg' }, }; const renderer = new NodeRenderer(schemaWithOptions); const buffer = await renderer.draw(); return Buffer.isBuffer(buffer) ? buffer : Buffer.from(await (buffer as Blob).arrayBuffer()); }; ``` ### Technical Analysis Canvas width and height can originate from CLI options, an attacker-controlled schema file, or an AI-generated schema. The values are passed to the rendering engine without enforcing that they are finite, positive integers within safe limits. `parseInt()` alone is not validation. It may accept partially numeric strings, return `NaN`, or produce extremely large values. Schema-derived dimensions are not parsed ...[truncated 1495 chars]
Remediation
View remediation
MAX_DIMENSION || parsedHeight > MAX_DIMENSION || parsedWidth * parsedHeight > MAX_PIXELS ) { throw new Error('Canvas dimensions exceed the permitted rendering limits'); } return { width: parsedWidth, height: parsedHeight }; } ``` Invoke this validation immediately before `new NodeRenderer(schemaWithOptions)` so every rendering path is protected. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (34)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 83)May include surrounding context.

md
- `OPENAI_BASE_URL` - Custom OpenAI API endpoint (optional)
- `OPENAI_MODEL` - Default model to use (optional)

### Using .env File

Copy `.env.example` to `.env` and add your API key:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 89)May include surrounding context.

md
- `OPENAI_BASE_URL` - Custom OpenAI API endpoint (optional)
- `OPENAI_MODEL` - Default model to use (optional)

### Using .env File

Copy `.env.example` to `.env` and add your API key:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 88)May include surrounding context.

Copy .env.example to .env and add your API key:

bash
cp .env.example .env
# Then edit .env and add your OPENAI_API_KEY

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says the skill renders JSON schemas to images and generates schemas from prompts using AI. This code chunk does neither rendering nor AI-based schema generation. Instead, its primary purpose is validating an existing schema loaded from a file, with optional interactive prompting and CLI-style error reporting. While validation could be related to schema tooling, it is a materially different behavior from the declared render/generate purpose, so this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
90% confidence
Finding

The project pulls in form-data 4.0.5 through the openai SDK, and the cited issue allows CRLF injection through unescaped multipart field names. Because this CLI uses AI/networking components and may construct outbound multipart requests from prompts, files, or other user-controlled inputs, the vulnerable dependency can enable request smuggling or header/body manipulation in downstream HTTP interactions.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 25)May include surrounding context.

Ubuntu/Debian

bash
sudo apt-get install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev librsvg2-dev

Windows

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README instructs users to send prompts and potentially schema content to an external AI service, including support for a custom API endpoint, but does not warn that user-supplied content may leave the local environment. This can lead to unintentional disclosure of sensitive prompts, schema data, or proprietary design content, especially when users assume the tool operates locally except for rendering.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
79% confidence
Finding

The skill declares environment-variable requirements, including an OpenAI API key, but does not define any explicit tool scope or permissions boundary. That omission can cause the agent runtime or user to grant broader access than necessary, reducing transparency about what sensitive resources the skill may use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly supports sending user prompts to OpenAI via API key and optional base URL settings, but it does not warn that prompt contents may leave the local environment and be processed by an external service. Users may unknowingly submit sensitive schema content, proprietary designs, or internal data under the assumption that all processing is local.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest says the skill 'generate[s] schemas from prompts', but this command prompts the user to 'Describe the image to generate' and then proceeds as an image-generation flow. Although it later obtains a schema and renders it, the user-facing behavior and documented intent in code are centered on generating an image, which does not cleanly match the manifest's stated schema-generation purpose.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The prompt text says 'Describe the image to generate,' implying direct image generation, but the code calls generateSchema(...) and then renderSchema(...). This is an intent-level contradiction in inline user-facing documentation because the implementation is schema-first, not direct image generation.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · src/utils/canvas.ts (reported line 49)May include surrounding context.

ts
installCmd = 'brew install pkg-config cairo pango jpeg giflib librsvg pixman';
      break;
    case 'linux':
      installCmd = 'sudo apt-get install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev librsvg2-dev';
      break;
    case 'win32':
      installCmd = 'npm install --global --production windows-build-tools';

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · src/utils/errors.ts (reported line 45)May include surrounding context.

ts
installCmd = 'brew install pkg-config cairo pango jpeg giflib librsvg pixman';
      break;
    case 'linux':
      installCmd = 'sudo apt-get install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev librsvg2-dev';
      break;
    case 'win32':
      installCmd = 'npm install --global --production windows-build-tools';

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · src/utils/install.ts (reported line 61)May include surrounding context.

ts
installCmd = 'brew install pkg-config cairo pango jpeg giflib librsvg pixman';
      break;
    case 'linux':
      installCmd = 'sudo apt-get install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev librsvg2-dev';
      break;
    case 'win32':
      installCmd = 'npm install --global --production windows-build-tools';

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · src/utils/install.ts (reported line 62)May include surrounding context.

ts
installCmd = 'brew install pkg-config cairo pango jpeg giflib librsvg pixman';
      break;
    case 'linux':
      installCmd = 'sudo apt-get install libcairo2-dev libjpeg-dev libpango1.0-dev libgif-dev librsvg2-dev';
      break;
    case 'win32':
      installCmd = 'npm install --global --production windows-build-tools';

Known Vulnerable Dependency: esbuild==0.27.3 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The package description says the tool renders JSON schemas to images using declare-render, which suggests a focused rendering CLI. However, the dependency list also includes OpenAI, dotenv, inquirer, and a local materials-agents package, which strongly indicates an additional AI-assisted schema-generation capability beyond rendering alone.

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 28)May include surrounding context.

json
"author": "",
  "license": "ISC",
  "dependencies": {
    "canvas": "^3.2.1",
    "chalk": "^5.3.0",
    "commander": "^12.1.0",
    "declare-render": "^1.1.9",

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 45)May include surrounding context.

json
"author": "",
  "license": "ISC",
  "dependencies": {
    "canvas": "^3.2.1",
    "chalk": "^5.3.0",
    "commander": "^12.1.0",
    "declare-render": "^1.1.9",

Unverifiable Dependency: canvas has 2 known advisory(ies) (CVE-2020-8215 (Buffer overflow in canvas); GHSA-vpq5-4rc8-c222 (Denial of Service in canvas)), 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.

Unverifiable Dependency: canvas has 2 known advisory(ies) (CVE-2020-8215 (Buffer overflow in canvas); GHSA-vpq5-4rc8-c222 (Denial of Service in canvas)), 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.

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 29)May include surrounding context.

json
"license": "ISC",
  "dependencies": {
    "canvas": "^3.2.1",
    "chalk": "^5.3.0",
    "commander": "^12.1.0",
    "declare-render": "^1.1.9",
    "dotenv": "^16.4.5",

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 30)May include surrounding context.

json
"dependencies": {
    "canvas": "^3.2.1",
    "chalk": "^5.3.0",
    "commander": "^12.1.0",
    "declare-render": "^1.1.9",
    "dotenv": "^16.4.5",
    "inquirer": "^9.2.23",

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 31)May include surrounding context.

json
"canvas": "^3.2.1",
    "chalk": "^5.3.0",
    "commander": "^12.1.0",
    "declare-render": "^1.1.9",
    "dotenv": "^16.4.5",
    "inquirer": "^9.2.23",
    "materials-agents": "file:../materials-agents",

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 32)May include surrounding context.

json
"chalk": "^5.3.0",
    "commander": "^12.1.0",
    "declare-render": "^1.1.9",
    "dotenv": "^16.4.5",
    "inquirer": "^9.2.23",
    "materials-agents": "file:../materials-agents",
    "openai": "^4.77.0"

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
bin/materials-cli.js:24

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/utils/install.ts:26