T09 · Insecure Skill Coding Practices
- Location
scripts/main.ts:183- Finding
WeryAI API Key Can Be Forwarded to an Untrusted Result URL
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real WeryAI image-generation skill, but it has under-disclosed local-file and API-key handling that should be reviewed before installation.
Review this skill carefully before installing. Use it only in trusted projects, avoid untrusted batch files, local reference paths, and arbitrary webhook URLs, prefer an environment variable over persisted API keys, and consider preinstalling a trusted Bun version. The publisher should align the docs with actual reference-image behavior, restrict or remove local-file uploads, validate result-download origins before sending credentials, and harden secret-file permissions.
scripts/main.ts:183WeryAI API Key Can Be Forwarded to an Untrusted Result URL
scripts/main.ts:297Arbitrary Readable Local Files Can Be Encoded and Uploaded as Reference Images
scripts/setup.mjs:124Persisted API Key Is Written Without Enforcing Owner-Only Permissions
scripts/vendor/weryai-image/run-generate.mjs:22Unpinned Bun Package Is Automatically Downloaded and Executed Through npx
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
A generic text-to-image client backed by a model registry is broader than the manifest suggests. Misrepresenting a general-purpose generation tool as a narrow children’s-book helper can lead to inappropriate approval, insufficient guardrails, and accidental transmission of prompts or content outside the intended domain.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
}
function applyStylePreset(prompt: string, style: StylePreset | null | undefined): string {
if (!style) return prompt;
return `${prompt.trim()}\n\nStyle preset (${style}): ${STYLE_PRESETS[style]}.`;
}
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
}
function applyStylePreset(prompt: string, style: StylePreset | null | undefined): string {
if (!style) return prompt;
return `${prompt.trim()}\n\nStyle preset (${style}): ${STYLE_PRESETS[style]}.`;
}
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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) {
The --webhook-url option allows arbitrary callback destinations to be supplied and forwarded to the external API. This creates an unexpected outbound data flow channel that can leak task metadata/results to attacker-controlled endpoints and is unnecessary for a children's illustration skill.
The --scope home option allows the script to write API credentials into a file under the user's home directory, broadening the blast radius from one project to the entire user environment. A home-scoped secret file is more likely to be consumed by unrelated processes or survive long after the skill is removed, making unintended credential exposure and cross-project leakage more serious.
Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.potential_exfiltration