Back to skill

Security audit

Image Generation

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real image-generation wrapper, but it needs Review because its handling of local files, API keys, and runtime setup creates avoidable credential and data exposure risks.

Review before installing. Use a dedicated, low-quota WeryAI API key, avoid persisting it unless necessary, and do not pass sensitive local files as --ref or in batch files. Prefer a preinstalled/pinned Bun runtime over npx -y bun, and treat generated result URLs and webhook URLs as external network destinations.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.ts:170
Finding
API Bearer Token Can Be Disclosed to an Arbitrary Result URL<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.ts:170-203` **Duplicate Location**: `scripts/vendor/shared-image-generation/scripts/main.ts:170-203` **Vulnerability Type**: Credential disclosure through an untrusted network destination **Risk Level**: High ### Vulnerable Code ```ts async function fetchImageBytes(url: string, quiet: boolean): Promise<FetchResult> { 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") ); }; 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 download URL is obtained from the gateway's task response and passed directly to `fetchImageBytes`. The code first makes an unauthenticated request and then ...[truncated 1920 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never send the API credential to arbitrary result URLs. 2. Parse URLs with `new URL(url)` and require `protocol === "https:"`. 3. Maintain an explicit allowlist of WeryAI-controlled API and CDN hostnames. 4. Send authorization only when the exact origin is approved and protected downloads genuinely require it. 5. Disable automatic redirects or validate every redirect target before following it. 6. Do not retry general network exceptions with credentials. 7. Reject loopback, private, link-local, and metadata-service addresses after DNS resolution where feasible. 8. Apply the same correction to the duplicated vendored implementation. 9. Add tests proving that attacker-controlled hosts never receive an `Authorization` header. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.ts:302
Finding
Arbitrary Local Files Can Be Encoded and Uploaded as Reference Images<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.ts:302-311`, `scripts/main.ts:926-933`, and `scripts/main.ts:1004-1007` **Duplicate Location**: Corresponding code in `scripts/vendor/shared-image-generation/scripts/main.ts` **Vulnerability Type**: Unrestricted local file read and network exfiltration **Risk Level**: High ### Vulnerable Code ```ts function toImagePayloadValue(pathOrUrl: string): string { const t = pathOrUrl.trim(); if (/^https?:\/\//i.test(t)) return t; const abs = resolve(t); if (!existsSync(abs)) throw new Error(`Reference image not found: ${abs}`); const buf = readFileSync(abs); const mime = mimeForExt(extname(abs)); return `data:${mime};base64,${buf.toString("base64")}`; } ``` ```ts async function validateReferenceImages(paths: string[]): Promise<void> { 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 body: Record<string, unknown> = referenceImages.length > 0 ? { ...baseBody, images: referenceImages.map(toImagePayloadValue) } : baseBody; ``` ### Technical Analysis A reference argument that does not begin with `http://` or `https://` is treated as a local path. The path is resolved, read in full, base64-encoded, and inserted into the request body sent to WeryAI. The validation only establishes that the path is accessible. It does not: - Restrict the file to the project or another approved directory. - Require an actual regular file. - Prevent symbolic-link traversal outside an approved directory. - Verify the file's magic bytes or image format. - Enforce a maximum input size. - Require explicit approval before uploading a local file. The MIME type is inferred only from the extension. A sensitive file can therefore be renamed or supplied directly ...[truncated 1574 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Decide on and document one consistent policy: - Reject all local references and accept only approved HTTPS URLs; or - Support local images through a tightly constrained upload policy. 2. If local files remain supported: - Require explicit user approval for each local file. - Restrict files to an approved workspace or upload directory. - Resolve real paths and verify containment after resolving symbolic links. - Require a regular file and reject devices, sockets, directories, and symlinks. - Validate image magic bytes using a trusted image parser. - Allow only explicitly supported image formats. - Enforce conservative file-size and image-dimension limits. - Stream content where possible instead of loading arbitrary files fully into memory. 3. Reject plain HTTP reference URLs unless there is a documented exceptional need. 4. Align `SKILL.md` with actual behavior so users understand which files may leave the machine. 5. Add negative tests for `.env`, SSH keys, symlink escapes, non-image files, and oversized inputs. 6. Patch both the primary and duplicated vendored implementation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.mjs:114
Finding
API Key Persistence Uses Plaintext Files Without Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.mjs:20-27`, `scripts/setup.mjs:53-58`, and `scripts/setup.mjs:114-131` **Duplicate Location**: Corresponding code in `scripts/vendor/shared-image-generation/scripts/setup.mjs` **Vulnerability Type**: Insecure secret handling and plaintext credential storage **Risk Level**: Medium ### Vulnerable Code ```js function printHelp() { console.log(`Usage: node scripts/setup.mjs [options] Options: --project <path> Project directory to write/read .image-skills config (default: cwd) --workflow <name> Optional focus: general|cover|rednote|infographic|comic|article|compress --force-models Overwrite MODELS.json if it already exists --api-key <secret> Write IMAGE_GEN_API_KEY into local skill config --persist-api-key Persist current IMAGE_GEN_API_KEY from env into local skill config --scope <target> Where to write the local .env: project or home (default: project) --json Print JSON output -h, --help Show help ``` ```js for (let i = 0; i < argv.length; i++) { const current = argv[i]; if (current === "--project") args.project = argv[++i] ?? args.project; else if (current === "--workflow") args.workflow = argv[++i] ?? args.workflow; else if (current === "--force-models") args.forceModels = true; else if (current === "--api-key") args.apiKey = argv[++i] ?? null; else if (current === "--persist-api-key") args.persistApiKey = true; ``` ```js function writeApiKeyConfig({ project, homeDir, scope, apiKeyInput }) { const envPath = resolveEnvPath({ project, homeDir, scope }); if (!apiKeyInput.requested) { return { ok: true, wrote: false, path: envPath, status: "not-requested", source: apiKeyInput.source }; } if (!envPath) { return { ok: false, wrote: false, path: null, status: "missing-home-dir", source: apiKeyInput.source }; } if (!apiKeyInput.value) { return { ok: false, wrote: false, path: envPath, stat ...[truncated 2241 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--api-key <secret>` option. 2. Accept secrets through a protected environment variable, concealed interactive input, or standard input that is not recorded in command history. 3. Prefer an operating-system credential store where available. 4. Create the configuration directory with mode `0700`. 5. Create the `.env` file atomically with mode `0600`. 6. If the file already exists, verify and correct its ownership and permissions before writing. 7. Use a temporary file in the same private directory, set its permissions before adding secret content, then atomically rename it. 8. Warn when the project configuration directory is inside a version-controlled workspace and ensure `.env` is ignored. 9. Add tests that verify effective permissions and confirm the secret never appears in output or process arguments. 10. Apply the same hardening to the duplicated vendored setup script. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/vendor/weryai-image/run-generate.mjs:35
Finding
Unpinned Remote Bun Package Is Downloaded and Executed Through npx<![CDATA[ ## Vulnerability Details **File Location**: `scripts/vendor/weryai-image/run-generate.mjs:35-46` **Related Locations**: `scripts/package.json:7`, `SKILL.md:140`, and `scripts/vendor/shared-image-generation/scripts/package.json:7` **Vulnerability Type**: Unpinned third-party runtime execution **Risk Level**: High ### Vulnerable Code ```js const npxCommand = process.platform === "win32" ? "npx.cmd" : "npx"; const result = spawnSync(npxCommand, ["-y", "bun", entryScript, ...args], { stdio: "inherit", env: { ...process.env, IMAGE_PROJECT_ROOT: projectRoot, IMAGE_SKILL_NAMESPACE: skillNamespace || process.env.IMAGE_SKILL_NAMESPACE, IMAGE_SKILL_LABEL: process.env.IMAGE_SKILL_LABEL || skillNamespace, }, }); process.exit(result.status ?? 1); ``` The related package script also invokes an unpinned package: ```json { "scripts": { "test": "npx -y bun test" } } ``` ### Technical Analysis `npx -y bun` may resolve and download the current registry version of the `bun` package and execute it without an interactive confirmation. No exact version or integrity value is specified, and no lockfile was identified in the audited project. Therefore, the code executed during generation can change after the Skill has been reviewed. This creates a supply-chain trust gap: package-registry compromise, account takeover, malicious version publication, or registry-resolution manipulation could introduce arbitrary code into the Agent process. The launcher passes the full inherited environment to the downloaded runtime. That environment may include `IMAGE_GEN_API_KEY` and other unrelated credentials. A malicious dependency would consequently execute with the same filesystem, network, and environment access as the Skill. ### Attack Path 1. The user or Agent runs the generation command. 2. `run-generate.mjs` invokes `npx -y bun`. 3. `npx` resolves the package from its configured registry because no exact version is pinned. 4. A compromised or m ...[truncated 872 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer a trusted, preinstalled runtime and fail safely if it is unavailable. 2. If automatic retrieval is required, pin an audited exact package version rather than using the mutable `bun` tag. 3. Commit an appropriate lockfile and verify package integrity. 4. Use an approved registry and enforce integrity or signature verification where supported. 5. Do not use `npx -y` for security-sensitive runtime acquisition. 6. Minimize the environment passed to the child process. Explicitly forward only variables required for generation. 7. Avoid forwarding unrelated credentials and tokens to third-party runtime processes. 8. Run downloaded or third-party tooling in a sandbox with constrained filesystem and network access. 9. Incorporate dependency provenance and version review into release procedures. 10. Pin or remove all related `npx -y bun` invocations, including test and duplicated vendor scripts. ]]>
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (75)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared purpose is specifically about image generation functionality (text-to-image/image-to-image, polling, download handling). The actual code does not generate, poll for, or download images. It only queries the generation balance endpoint and returns credit information. That is a materially different primary purpose and an undeclared capability related to account balance lookup, so this is a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill is for generating images through a gateway CLI, including async request handling, polling, and downloads. However, the supplied code only retrieves the model registry and returns available models for text-to-image or image-to-image modes. Its primary purpose is model enumeration, not image creation. This is a material description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents a broader skill that supports both text-to-image and image-to-image workflows, plus polling and download handling. The supplied code chunk only implements submission for image-to-image generation via POST to /v1/generation/image-to-image. It validates and normalizes input, consults a model registry, supports dry-run request preview, and returns task IDs from the submission response. There is no evidence here of text-to-image generation, asynchronous polling/status checks, or downloading generated images. Because the declared purpose materially overstates the capabilities shown in this code chunk, this is a mismatch.

Ae1

High
Category
analysis-evasion
Content
| Base URL | `https://api.weryai.com` (hard-coded in `scripts/main.ts`) |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
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/image-generation/.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:
Confidence
89% confidence
Finding
The skill explicitly handles an API key and permits persisting it into local `.env` files, which creates credential exposure risk if file permissions, repository hygiene, or workspace boundaries are weak. Any skill that reads and stores secrets needs tight scoping, because compromise of the project directory or later tooling can disclose the key.

Credential Access

High
Category
Privilege Escalation
Content
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) {
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
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) {
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
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) {
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
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) {
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
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) {
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
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) {
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
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) {
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
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) {
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
}

function applyStylePreset(prompt: string, style: StylePreset | null | undefined): string {
  if (!style) return prompt;
  return `${prompt.trim()}\n\nStyle preset (${style}): ${STYLE_PRESETS[style]}.`;
}
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
}

function applyStylePreset(prompt: string, style: StylePreset | null | undefined): string {
  if (!style) return prompt;
  return `${prompt.trim()}\n\nStyle preset (${style}): ${STYLE_PRESETS[style]}.`;
}
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Credential Access

High
Category
Privilege Escalation
Content
-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
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
-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
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
-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
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
-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
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
-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
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
-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
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
91% confidence
Finding
The skill explicitly requires environment access and outbound network access, but it does not declare a restrictive tool scope such as allowed tools or permissions. In an agent ecosystem, that weakens containment and makes it easier for the skill to access secrets and make external requests beyond what a reviewer or runtime may expect.

Session Persistence

Medium
Category
Rogue Agent
Content
---
name: image-generation
description: Single-gateway image generation CLI for async text-to-image and image-to-image, with polling, download handling, and request alignment to the current gateway OpenAPI. Use when the user asks to generate an image, create a picture, draw something, or make a visual from a text prompt.
version: 0.5.0
metadata: { "pattern": ["tool-wrapper"], "openclaw": { "emoji": "🎨", "primaryEnv": "IMAGE_GEN_API_KEY", "requires": { "env": ["IMAGE_GEN_API_KEY"], "anyBins": ["bun", "npx"], "bins": ["node", "npm"] } } }
---
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger phrases are broad enough to match many ordinary user requests, which can cause the skill to activate in contexts where users did not intend external network use or secret-dependent tooling. Over-broad activation increases the chance of surprise API calls, unintended secret handling, or unnecessary environment modification.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
npm run ensure-ready -- --project . --workflow <workflow>
```

This readiness step is not optional. It checks the local toolchain, reads the local doctor report, and automatically runs `bootstrap` when local script dependencies are missing.

**First-trigger user behavior**:
Confidence
84% confidence
Finding
The skill instructs the agent to automatically run readiness/bootstrap behavior, which can modify the environment before the user fully understands what will happen. Autonomous setup actions are risky because they may install dependencies or change local state in a way that expands the trust boundary.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.potential_exfiltration

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/bootstrap.mjs:86

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/doctor.mjs:56

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/smoke-check.mjs:18

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/shared-image-generation/scripts/bootstrap.mjs:86

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/shared-image-generation/scripts/doctor.mjs:56

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/shared-image-generation/scripts/smoke-check.mjs:18

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/weryai-image/discover-models.mjs:9

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/weryai-image/doctor.mjs:9

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/weryai-image/main.ts:15

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/weryai-image/recommend-model.mjs:9

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/weryai-image/run-generate.mjs:39

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/weryai-image/setup.mjs:9

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/main.ts:51

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/vendor/shared-image-generation/scripts/main.ts:51

File read combined with network send (possible exfiltration).

Warn
Code
suspicious.potential_exfiltration
Location
scripts/main.ts:6

File read combined with network send (possible exfiltration).

Warn
Code
suspicious.potential_exfiltration
Location
scripts/vendor/shared-image-generation/scripts/main.ts:6