T09 · Insecure Skill Coding Practices
- Location
test-gen.mjs:3- Finding
Hard-Coded OpenRouter API Credential in Test Script
- 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 handles API keys unsafely and can send the wrong provider's credential to OpenRouter.
Review before installing. Use only an OpenRouter-specific API key, remove or ignore the bundled test script with the hardcoded key, and do not include secrets, private data, or regulated content in image prompts because prompts are sent to OpenRouter. The GEMINI_API_KEY fallback should be removed before normal use.
test-gen.mjs:3Hard-Coded OpenRouter API Credential in Test Script
index.ts:20Gemini Credential Can Be Forwarded to OpenRouter
package-lock.json:17Dependency Lockfile Uses a Non-Default Registry Mirror
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).
XYwnOyen50rOPHh7Dv9ZNr8q6HD/kmwGcEeCzKEovtnctcZQ57Wns8Pd2yiwbzsmPnMY0TApF/VrIapM+cRqWkbxYJWACzqjzHeCwh7bOwOUJmaiGVVgfD4Gdq7542tTviKj49N5bdKSjq7kaRILKTzXebU2AR4+Sz+WTxtkPoCvEs/CQQCHRwYIfH8nOjdKROe7sSMdvxX9DmoudaHlxceY+e6c0pawIk/Rz+kqWg49UyV7dqK8Bi71Z+4fR4UyXhttLH2r1x02b+aq1QuZDA2InQixM8b+7dSNaJKdpmlXraEoqxFkvFVGdpS90ThnPd/nTuKnCXClB40Tr0Xqfx7SGEGJBLda4T71LG2d0WL7fT052Mr4YU5eHNhXI61RX0dWKcjy90iC2qmcpsPyTUYHvl7OxSPsvHNiiRSxfNjQjdruha2MPlD7F9tD5dKwlc2HjP/HRhIs/G3kwSj1/00sx3mQF9WZcu0xWbxdL/YrNglVVZWXBI2b3ZEyv0iS//yv6ZVVTKN1yOIrPYqA48YGwO216t9vZrDYR8viOW+PXNAtdXbOitWJTtRAo0Vq2iAFmuWIwyry+Gp8UDgdRgOYhldONdTo5v8GnRDvvZzNkIMh2+BK4z6lpIuasefIv1Zu1YDLEkORu4lt6Fz5gTXTJwRCkPtcBDzpEL2cM6oSdhlmrlsHKhr1gGvqKnOIhvgPQB7rkpWUtHOyfyBmLpcUCMrNbJYUf7I7h8ccrYMDpVZv39uXF9vwdefKxwIBAIdBE0P3AN1KmS65TCGDjEFShUSfiA4GbPBBR4LqZC0ukaPCA3rfw/uUI2fNKc6h1nDBE0eqSSTGWiazb3cvXaZSCoAyr57iqFXfaJ1zCs1lbeEdT1hBQB844onmP321Up5IBAIfCWODZWxvBnoQ2VF+OmGaEJvwRWHjzkD+4nkGQEPN1G2rNGu6RdmWy8Y5ueg6bzsAWDvsmrD6x1qeHYzg6ZIZOGQlHdJ6l9AH
This code performs an outbound network request to a third-party API and includes user-controlled prompt content in the request body. External transmission is not inherently malicious, but in this skill context it becomes security-relevant because there is no validation, warning, or policy control around what data the agent may exfiltrate to the remote service.
// OpenRouter Chat Completions Endpoint for Image Generation
// Note: Gemini 2.5 Flash Image uses 'modalities: ["image"]' in the request body
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
The tool sends the user-supplied prompt, including any embedded sensitive or proprietary text, to OpenRouter without any disclosure in the tool metadata that prompt contents leave the local environment. In an agent setting, users may reasonably assume prompts are handled internally, so undisclosed third-party transmission creates a real privacy and data-handling risk even though the behavior appears functionally intended.
This code performs an external network transmission to a third-party API, which is security-relevant because it moves generated content and request metadata outside the local trust boundary. While external calls can be legitimate, in this file they are paired with a hardcoded credential and no guardrails around what may be transmitted.
async function generate() {
console.log("Generating logo...");
try {
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
The file makes a hardcoded outbound call to a third-party model API and embeds a live bearer credential directly in source. This creates two concrete risks: unauthorized external transmission of prompt content to an unvetted service and immediate credential compromise if the code is shared, logged, or committed to a repository.
The skill sends prompt content and an authorization credential to an external provider without any meaningful disclosure, consent flow, or data-handling notice beyond a generic log line. In agent contexts, this can cause users or operators to unknowingly exfiltrate sensitive business data, prompts, or proprietary content to a third party.
The dependency uses a caret range (^3.3.2), which permits automatic installation of newer minor/patch releases. This creates supply-chain risk because a compromised or breaking upstream release could be pulled in without an explicit review, though the package itself is common and there is no direct evidence of malicious intent in this file.
"start": "node index.js"
},
"dependencies": {
"node-fetch": "^3.3.2"
},
"devDependencies": {
"@types/node": "^20.0.0",
The development dependency @types/node is specified with a caret range, allowing unreviewed updates within the major version. While this is lower risk than a runtime package because it is primarily used during development/build time, it still introduces supply-chain exposure and build reproducibility issues.
"node-fetch": "^3.3.2"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}
The TypeScript compiler dependency is also unpinned via a caret range, so newer releases can be installed automatically. A compromised or incompatible compiler release could affect builds, generated output, or CI pipelines, even if it is not shipped directly at runtime.
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}
The comments at L11, L17, and L22 say the intent is to inspect the output.json structure and dump keys to locate image data. However, once image data is found, the script proceeds to decode base64 and write logo.png to disk at L33, which is a materially different side effect than the documented inspection/debugging intent.
The inline console message frames the action as simply 'Generating logo...', but the actual request sends a detailed prompt to a remote multimodal model to design branded visual content. This is a mild intent/documentation divergence because the code is not merely performing a local logo-rendering step; it is delegating creative generation to an external service.
Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal