T09 · Insecure Skill Coding Practices
- Location
scripts/main.ts:187- Finding
WeryAI API Key Can Be Disclosed to an Untrusted Image Result URL
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This image-generation skill is mostly coherent, but it needs Review because its runtime can upload arbitrary readable local files as reference images and has unsafe API-key handling around downloads.
Review before installing. Use this only with trusted prompts and batch files, avoid passing local paths as references unless you intend to upload that exact file to WeryAI, prefer an environment variable over persisted key storage on shared machines, and use a trusted installed Bun runtime rather than automatic npx execution where possible.
scripts/main.ts:187WeryAI API Key Can Be Disclosed to an Untrusted Image Result URL
scripts/main.ts:298Arbitrary Readable Local Files Can Be Uploaded as Reference Images
scripts/setup.mjs:124Persisted API Key Files Are Not Created with Owner-Only Permissions
scripts/vendor/weryai-image/run-generate.mjs:22Unpinned Bun Package Is Downloaded and Executed Automatically
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
Handling outputs for videos, audio, lyrics, and cover URLs indicates the runtime may process broader media task types than the character-image description implies. In a narrowly scoped skill ecosystem, that capability expansion matters because it increases the attack surface and may route user data through code paths that were never expected or reviewed for this skill.
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 code accepts an arbitrary --webhook-url and forwards it directly to the upstream generation API. For a character-image generator, this creates an unnecessary outbound callback channel that could be abused to exfiltrate metadata, interact with attacker-controlled endpoints, or enable SSRF-like behavior via the third-party service acting on behalf of the user environment.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
-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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
-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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
-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