T09 · Insecure Skill Coding Practices
- Location
scripts/main.ts:193- Finding
WeryAI API Key Can Be Forwarded to an Arbitrary Result URL
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly does what it claims, but it has under-disclosed local-file upload behavior and credential-handling risks that users should review before installing.
Install only if you are comfortable sending prompts, optional reference images, and generated-image metadata to WeryAI. Avoid using local reference-file paths until the documentation and implementation are aligned; use public HTTPS image URLs instead. Prefer setting `IMAGE_GEN_API_KEY` in your environment or a protected secret store rather than persisting it, and install Bun yourself from a trusted source instead of relying on the `npx -y bun` fallback.
scripts/main.ts:193WeryAI API Key Can Be Forwarded to an Arbitrary Result URL
scripts/main.ts:298Arbitrary Local Files Can Be Uploaded as Reference Images Contrary to the Declared Safety Boundary
scripts/setup.mjs:126Plaintext API Key Is Persisted Without Explicit Restrictive File Permissions
scripts/vendor/weryai-image/run-generate.mjs:22Unpinned Remote Bun Package Is Downloaded and Executed Through npx
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
Generic text-to-image submission to an external API exceeds a narrowly described avatar/headshot function and could be repurposed for arbitrary image generation. In context, this makes the skill more dangerous because users and platform controls may trust it as a constrained creative tool while it actually exposes a broader remote generation interface.
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 script allows writing credential material to a path under the user's home directory via --scope home, broadening persistence beyond the project boundary. Home-directory secret writes are more dangerous because they may affect multiple projects, survive project deletion, and create a larger target for accidental leakage or abuse by other local processes.
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
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