Back to skill

Security audit

Chalk Art Image Generator

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly an image-generation wrapper, but it under-discloses sensitive local file, credential, installation, and configuration behaviors users should review before installing.

Install only if you are comfortable with a remote WeryAI image gateway, local config writes, and an API key stored in a project or home .env file. Do not use local reference-image paths unless you have verified the exact file being uploaded, and ask to see exact install commands before approving any runtime setup.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:280
Finding

Mandatory Skill Instructions Suppress Transparency and Direct Silent Environment Modification

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.ts:298
Finding

Arbitrary Local Files Can Be Encoded and Uploaded as Reference Images

Content
View full analysis
{ for (const refPath of paths) { const t = refPath.trim(); if (/^https?:\/\//i.test(t)) continue; const fullPath = path.resolve(refPath); try { await access(fullPath); } catch { throw new Error(`Reference image not found: ${fullPath}`); } } } ``` ```ts const pathSuffix = referenceImages.length > 0 ? "/v1/generation/image-to-image" : "/v1/generation/text-to-image"; const body: Record = referenceImages.length > 0 ? { ...baseBody, images: referenceImages.map(toImagePayloadValue) } : baseBody; if (input.dryRun) { const preview = { ...body }; if (Array.isArray(preview.images)) { preview.images = (preview.images as string[]).map((v) => typeof v === "string" && v.length > 256 ? `${v.slice(0, 64)}…[${v.length} chars]` : v ); } return { submit: undefined, detail: undefined, dryRun: true, requestPreview: { endpoint: `${BASE_URL}${pathSuffix}`, method: "POST", body: preview, }, }; } const submit = await apiPost(pathSuffix, body); ``` ### Technical Analysis A re ...[truncated 1967 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.ts:162
Finding

WeryAI Bearer Credential Can Be Forwarded to an Arbitrary Result URL

Content
View full analysis
{ let lastErr = ""; const transientStatus = (status: number) => status === 408 || status === 429 || status === 502 || status === 503 || status === 504 || (status >= 520 && status <= 599); const transientNetwork = (e: unknown) => { const name = e instanceof Error ? e.name : ""; const msg = e instanceof Error ? e.message : String(e); return ( name === "AbortError" || msg.includes("timeout") || msg.includes("Timeout") || msg.includes("fetch failed") || msg.includes("ECONNRESET") || msg.includes("ETIMEDOUT") || msg.includes("EAI_AGAIN") ); }; const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); for (let attempt = 1; attempt <= DOWNLOAD_MAX_ATTEMPTS; attempt++) { let res: Response | null = null; let threw: unknown = null; for (const useAuth of [false, true] as const) { try { const init: RequestInit = { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) }; if (useAuth) init.headers = { Authorization: `Bearer ${getApiKey()}` }; res = await fetch(url, init); threw = null; if (res.ok) break; lastErr = `HTTP ${res.status}`; if (!useAuth && (res.status === 401 || res.status === 403)) continue; break; } catch (e) { threw = e; res = null; lastErr = e instanceof Error ? e.message : String(e); if (!useAuth) continue; break; } } ``` ### Technical Analysis The image URL originates from the remote task-status response. Befor ...[truncated 1837 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.mjs:109
Finding

Plaintext API Key Is Persisted Without Restrictive File Permissions or Symlink Protection

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (95)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description presents this as a narrow skill specifically for chalkboard/chalk drawing art. The code, however, implements a broad WeryAI image-generation client whose primary purpose is generic image generation. While it does include a 'chalk' style preset, that is only one option among many presets such as photoreal, anime, watercolor, poster, infographic, etc. It also supports image-to-image generation via reference images, batch files, legacy subcommands, task-status lookup, config/env loading, and remote download of results. These are materially broader capabilities and a different primary purpose than the declared specialized chalk-art skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This is a clear mismatch. The declared purpose is an image/art generation capability focused on chalkboard-style visuals. The actual code does not generate images or process art prompts at all; it queries a remote balance endpoint and returns available credits/balance. That is a materially different primary purpose and an undeclared capability unrelated to the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is a domain-specific creative skill for generating chalkboard-style artwork. The supplied code does not contain any image generation, rendering, chalkboard styling, or art-specific logic. Instead, it is infrastructure code for making authenticated HTTP requests with timeout, retry, JSON parsing, and logging. That is a materially different primary purpose and introduces undeclared network access/authentication capabilities unrelated to the stated skill description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says the skill generates chalkboard-style artwork, but the supplied code chunk does not perform image generation, drawing, style rendering, or any chalk-art-specific behavior. Instead, it is a utility module for handling WeryAI API responses and errors. This is a materially different primary purpose, so the description does not accurately represent the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about producing chalkboard-style artwork, but the supplied code does not generate images or perform any drawing-related logic. Instead, it provides backend utility functions for normalizing task statuses and media task outputs from an external workflow. This is a materially different primary purpose from chalk art generation, so the description does not accurately represent the code's behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill generates chalkboard art and chalk drawings. However, the supplied code does not generate any artwork or perform image creation/stylization. Its actual purpose is to retrieve and normalize status information for previously created generation tasks or batches via /v1/generation/.../status API calls. This is a materially different primary purpose and introduces undeclared capabilities related to remote task-status monitoring and metadata retrieval. Therefore, the description does not accurately represent the code's behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill generates chalkboard art and chalk drawings. However, the supplied code does not perform image generation, drawing, rendering, style application, or any chalkboard-art-specific logic. Instead, it repeatedly queries remote /v1/generation/.../status endpoints to monitor asynchronous generation tasks, including batch status polling, retries, timeout handling, normalization of task results, and reporting completion/failure. This is a materially different primary purpose from the declared artistic function, so the description does not accurately represent the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is narrowly about producing a specific artistic style: chalkboard/chalk/pastel-on-dark-background images. The supplied code does not implement any chalkboard-art-specific behavior, styling, prompts, triggers, or rendering logic. Instead, it provides generic backend support for image generation by contacting a models service, validating user inputs against model capabilities, and constructing API request payloads for text-to-image and image-to-image modes. This is a materially different primary purpose and includes undeclared network/model-registry functionality unrelated to the specific declared artistic specialization.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

There is a clear mismatch between the declared purpose and the actual code behavior. The description claims this skill generates chalkboard/pastel-style art, implying image creation functionality. However, the supplied code only retrieves and returns model metadata from a remote registry, filtered by mode. Its primary purpose is model discovery/listing, not image generation, and nothing in the code is specific to chalkboard art, blackboard menus, or pastel drawings.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The description claims a specific end-user capability: generating chalkboard art or related dark-background pastel imagery. However, the provided code chunk does not implement or even reference chalkboard styling, drawing generation, prompt handling, triggers, or any art-specific logic. It only exports generic constants for an image model, an image-model API endpoint, and fallback generation defaults. That is materially different from the declared specialized purpose, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is narrow and style-specific, implying a specialized chalkboard/chalk drawing generator. The actual code is not specialized to chalkboard art at all; it is a general-purpose text-to-image submission routine that accepts arbitrary prompts and models, validates against a model registry, and calls a remote generation API. While chalkboard art could be one possible use of this code, the implemented primary purpose is materially broader than the declared description, so this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| Base URL | `https://api.weryai.com` (hard-coded in `scripts/main.ts`) |

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The skill is designed to locate, use, and optionally persist an API key from environment files, creating a credential-handling pathway that touches secrets on disk and in process environment. In a skill without strict scope declarations and with network capability, this increases the risk of secret exposure, misuse, or unauthorized persistence.

Content

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

md
3. **If `IMAGE_GEN_API_KEY` is missing**, ask the user for permission to configure it now
4. Only after readiness and API key are resolved, continue to model selection / prompt clarification / generation

**Access token**: only use **`IMAGE_GEN_API_KEY`**. It may also live in `.image-skills/chalk-art-image-generator/.env` as `IMAGE_GEN_API_KEY=...`. After the user approves, the agent may persist it there by running `npm run setup -- --project . --workflow <workflow> --persist-api-key` when the key is already in env, or by writing the file locally on the user's behalf instead of asking the user to edit files manually.

**First-use readiness check**: before the first generation run in a new OpenClaw or local instance, the agent must run:

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script synchronously executes multiple local commands (node, npm, bun, npx, sips, cwebp, magick, convert) to fingerprint the host toolchain. Even without shell injection, this is still active host reconnaissance unrelated to chalk-art generation and can reveal system capabilities, installed software, and platform details that increase the blast radius if the skill is run in a sensitive environment.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

The script reads a project-local .env file and tests for the presence of IMAGE_GEN_API_KEY, which constitutes credential discovery behavior. Although it does not exfiltrate the key value directly, scanning for and processing credential-bearing files is sensitive behavior, especially in a skill whose advertised purpose does not require filesystem credential inspection.

Content

Scanner excerpt · scripts/doctor.mjs (reported line 90)May include surrounding context.

js
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/main.ts (reported line 596)May include surrounding context.

ts
}

function applyStylePreset(prompt: string, style: StylePreset | null | undefined): string {
  if (!style) return prompt;
  return `${prompt.trim()}\n\nStyle preset (${style}): ${STYLE_PRESETS[style]}.`;
}

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/vendor/shared-image-generation/scripts/main.ts (reported line 602)May include surrounding context.

ts
}

function applyStylePreset(prompt: string, style: StylePreset | null | undefined): string {
  if (!style) return prompt;
  return `${prompt.trim()}\n\nStyle preset (${style}): ${STYLE_PRESETS[style]}.`;
}

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 · scripts/main.ts (reported line 397)May include surrounding context.

ts
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

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 · scripts/main.ts (reported line 470)May include surrounding context.

ts
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

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 · scripts/main.ts (reported line 471)May include surrounding context.

ts
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

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 · scripts/vendor/shared-image-generation/scripts/doctor.mjs (reported line 90)May include surrounding context.

js
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

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 · scripts/vendor/shared-image-generation/scripts/main.ts (reported line 403)May include surrounding context.

ts
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

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 · scripts/vendor/shared-image-generation/scripts/main.ts (reported line 476)May include surrounding context.

ts
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

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 · scripts/vendor/shared-image-generation/scripts/main.ts (reported line 477)May include surrounding context.

ts
const projectSkillDir = path.join(projectRoot, ".image-skills", skillNamespace);
  const homeSkillDir = homeRoot ? path.join(homeRoot, ".image-skills", skillNamespace) : null;

  const projectEnvPath = path.join(projectRoot, ".image-skills", skillNamespace, ".env");
  const projectEnvFile = pathExists(projectEnvPath);
  let apiKeyInProjectEnv = false;
  if (projectEnvFile) {

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 · scripts/doctor.mjs (reported line 284)May include surrounding context.

js
-h, --help            Show help

What this does:
  1) Optionally writes IMAGE_GEN_API_KEY into the local skill .env
  2) Runs doctor (read-only)
  3) Ensures a MODELS.json exists (writes the bundled starter if missing)
  4) Initializes EXTEND.md with Nano Banana 2 if no default model exists yet