Back to skill

Security audit

Api Generator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent API code generator, but some generated authentication code is unsafe enough that users should review it carefully before using it.

Install only if you treat the output as scaffolding, not production-ready code. Review and harden generated auth before use, especially JWT secrets and API-key validation, validate generator inputs, and be aware that scripts/script.sh can write local usage history if invoked.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (5)

other

Note
Location
scripts/apigen.sh:7
Finding
Undisclosed Promotional Content Injected into Generated Artifacts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/apigen.sh`, lines 7, 76, 136, 188, 251, 321, 435, 540, 620, and 638 **Vulnerability Type**: Undisclosed output manipulation **Risk Level**: Low ### Vulnerable Code ```bash BRAND="Powered by BytesAgain | bytesagain.com | hello@bytesagain.com" # Appended by the different generation branches: echo "// $BRAND" echo "# $BRAND" ``` ### Technical Analysis The generator automatically appends a promotional domain and email address to generated source code and specifications. This behavior applies to the normal `rest`, `graphql`, `swagger`, `client`, `mock`, `auth`, `rate-limit`, and `test` generation paths. The documented output behavior states that generated code is printed to standard output, but it does not disclose that promotional content will be inserted into artifacts. This is output manipulation rather than instruction hijacking because it does not alter the AI agent's goals or safety constraints. ### Attack Path 1. A user invokes a documented generator command, such as: ```bash bash scripts/apigen.sh auth jwt > auth.js ``` 2. The script generates the requested code. 3. The script automatically appends the promotional domain and email address. 4. Because output is redirected, the promotional content becomes a persistent part of the user's source file. 5. The content may subsequently be committed, distributed, or deployed without the user intentionally adding it. ### Impact Assessment The behavior modifies user-owned generated artifacts and may cause unintended attribution, external promotion, policy violations, or source-code pollution. It does not provide system privileges, execute a remote payload, or expose credentials. The scope is limited to generated output. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Do not append promotional material to generated artifacts by default. - If attribution is required, clearly disclose it in `SKILL.md`. - Make branding explicitly opt-in through an option such as `--include-branding`. - Keep informational branding in terminal diagnostics sent to standard error rather than generated source sent to standard output. - Add automated tests confirming that generated code contains only the requested artifact unless branding is explicitly enabled. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/apigen.sh:333
Finding
Generated JWT Authentication Uses a Publicly Known Default Signing Secret<![CDATA[ ## Vulnerability Details **File Location**: `scripts/apigen.sh`, lines 333–365 **Vulnerability Type**: Predictable cryptographic secret and fail-open security configuration **Risk Level**: High ### Vulnerable Code ```javascript const jwt = require('jsonwebtoken'); const SECRET = process.env.JWT_SECRET || 'change-me-in-production'; // Generate token function generateToken(user) { return jwt.sign( { id: user.id, email: user.email, role: user.role }, SECRET, { expiresIn: '24h' } ); } // Auth middleware function authMiddleware(req, res, next) { const header = req.headers.authorization; if (!header || !header.startsWith('Bearer ')) { return res.status(401).json({ error: 'No token provided' }); } try { const decoded = jwt.verify(header.split(' ')[1], SECRET); req.user = decoded; next(); } catch (err) { return res.status(401).json({ error: 'Invalid token' }); } } ``` ### Technical Analysis The generated authentication module uses the static string `change-me-in-production` whenever `JWT_SECRET` is absent. This value is visible in the distributed generator and is therefore known to every attacker. JWT integrity depends on the signing key remaining unpredictable. Because both token generation and verification use the fallback value, an application deployed without a configured environment variable accepts attacker-created tokens signed with that public string. The token payload includes a client-controllable `role` claim, enabling privilege forgery where authorization relies on `requireRole`. ### Attack Path 1. A developer generates the JWT template: ```bash bash scripts/apigen.sh auth jwt > auth.js ``` 2. The developer deploys the generated module without setting `JWT_SECRET`. 3. The application silently uses `change-me-in-production`. 4. An attacker creates a JWT containing a forged identity and privileged role, such as `admin`. 5. The attacker signs the token using the known fallback secret. 6 ...[truncated 502 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the fallback secret entirely. - Fail application startup if `JWT_SECRET` is absent or empty. - Require a cryptographically random secret of sufficient entropy, or use asymmetric signing with properly managed private keys. - Validate the permitted JWT algorithm explicitly during verification. - Validate issuer, audience, expiration, and other application-specific claims. - Avoid trusting authorization roles solely because they are present in a token; validate current account status and privileges where appropriate. - Add deployment documentation and tests proving that the application refuses to start without secure key configuration. - Establish signing-key rotation and token revocation procedures. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/apigen.sh:418
Finding
Generated API-Key Middleware Accepts Every Nonempty Key<![CDATA[ ## Vulnerability Details **File Location**: `scripts/apigen.sh`, lines 418–429 **Vulnerability Type**: Authentication bypass caused by omitted credential validation **Risk Level**: Critical ### Vulnerable Code ```javascript // Auth middleware function apiKeyAuth(req, res, next) { const key = req.headers['x-api-key'] || req.query.api_key; if (!key) { return res.status(401).json({ error: 'API key required' }); } // Validate against database: // const valid = await ApiKey.findOne({ key, active: true }); // if (!valid) return res.status(401).json({ error: 'Invalid API key' }); next(); } module.exports = { generateApiKey, apiKeyAuth }; ``` ### Technical Analysis Credential validation is present only as commented example code. The executable middleware checks whether a value exists but never verifies whether it is valid, active, unexpired, or associated with an authorized principal. It then unconditionally calls `next()`. As a result, any arbitrary nonempty header or query parameter satisfies the authentication middleware. Accepting API keys through the query string also increases accidental exposure through access logs, browser history, analytics systems, referrer data, and intermediary infrastructure. ### Attack Path 1. A developer generates the API-key authentication template: ```bash bash scripts/apigen.sh auth apikey > api-key-auth.js ``` 2. The generated middleware is attached to protected API routes without implementing the commented database lookup. 3. An unauthenticated attacker sends: ```http X-API-Key: arbitrary-value ``` 4. The nonempty value passes the only active check. 5. The middleware invokes `next()`. 6. The attacker reaches routes that were intended to require a valid API key. ### Impact Assessment This flaw causes complete authentication bypass for every endpoint protected solely by the generated middleware. An attacker obtains the same API access as an authenticated key holder. Depending on t ...[truncated 162 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Generate mandatory, executable key-validation logic rather than commented placeholders. - Deny access unless the presented key matches an active, unexpired credential. - Store only cryptographic hashes of API keys and compare them using an appropriate constant-time strategy. - Associate keys with principals, scopes, expiration times, revocation state, and audit metadata. - Return an authorization error when database access or validation fails; never fail open. - Accept API keys only through a designated header, not query parameters. - Apply rate limiting and monitoring to repeated invalid-key attempts. - Clearly mark scaffolding as incomplete if it cannot safely operate without application-specific persistence. - Add tests proving that missing, arbitrary, revoked, and expired keys are rejected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/apigen.sh:5
Finding
Unvalidated Resource Names Permit Injection into Generated Source Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/apigen.sh`, lines 5 and 11–18, with equivalent interpolation in other generator branches **Vulnerability Type**: Source-code generation injection **Risk Level**: Medium ### Vulnerable Code ```bash ARG="${2:-resource}" rest) python3 - "$ARG" << 'PYEOF' import sys name = sys.argv[1] if len(sys.argv) > 1 else "resource" cap = name.capitalize() print("""// ===== {cap} RESTful API (Express.js) ===== const express = require('express'); const router = express.Router(); // GET /{name}s - List all router.get('/{name}s', async (req, res) => {{ ``` The template is finalized with direct formatting: ```python """.format(name=name, cap=cap)) ``` ### Technical Analysis The command-line resource name is passed safely from Bash to Python as an argument, so this is not shell command injection in the generator process itself. However, the value is inserted without context-specific validation or escaping into generated JavaScript strings, JavaScript identifiers, Python identifiers, GraphQL identifiers, comments, and route paths. A resource name containing quotes, line breaks, delimiters, or source-language syntax can terminate an intended string or identifier and introduce attacker-controlled source text. The generated artifact may execute that text when a developer later saves and runs it. The same underlying pattern appears across the `rest`, `graphql`, `client`, `mock`, and `test` templates. A single transformed value such as `cap = name.capitalize()` does not make the value a safe source-code identifier. ### Attack Path 1. An attacker supplies, recommends, or places a crafted resource name into an automated invocation. 2. A developer generates code and redirects it into a project file: ```bash bash scripts/apigen.sh rest "$UNTRUSTED_NAME" > routes.js ``` 3. The generator inserts the value directly into source-language contexts without validation or escaping. 4. The crafted value breaks out of ...[truncated 636 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Validate resource names before generation using a strict allowlist appropriate for identifiers, such as: ```text ^[A-Za-z][A-Za-z0-9_]*$ ``` - Reject control characters, quotes, whitespace, path separators, source delimiters, and line breaks. - Treat route paths, comments, string literals, and identifiers as separate contexts with separate escaping rules. - Use language-aware code-generation libraries or abstract syntax trees instead of free-form string interpolation. - Derive identifiers and route names through explicit normalization functions and reject values that cannot be represented safely. - Add adversarial tests covering quotes, backticks, braces, parentheses, newlines, comment delimiters, Unicode control characters, and reserved words. - Do not automatically execute generated artifacts when any input may originate from an untrusted party. ]]>

other

Note
Location
scripts/script.sh:5
Finding
Secondary Script Performs Undisclosed Persistent Usage Logging<![CDATA[ ## Vulnerability Details **File Location**: `scripts/script.sh`, lines 5–6, 40, 81, and 99 **Vulnerability Type**: Undisclosed local data retention and filesystem side effects **Risk Level**: Low ### Vulnerable Code ```bash DATA_DIR="${APIGEN_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/api-generator}" mkdir -p "$DATA_DIR/projects" ``` ```bash _log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; } ``` ```bash _log "init" "$name ($fw)" ``` ```bash _log "crud" "$resource" ``` ### Technical Analysis The secondary script creates a persistent data directory immediately at startup, regardless of the selected command. Its `init` and `crud` commands append timestamps and user-supplied project or resource names to `history.log`. The primary documentation states that generated code prints to standard output and does not describe persistent history logging. Although no external transmission was observed, project names and resource names may reveal confidential product, customer, or internal service information to other local processes or users if filesystem permissions are permissive. The configured data directory can also be redirected through `APIGEN_DIR`. The script relies on the process umask rather than explicitly restricting permissions on the directory and history file. ### Attack Path 1. A user invokes `scripts/script.sh`. 2. The script creates a persistent directory under the user's data directory before command processing. 3. The user runs `init` or `crud` with a potentially sensitive project or resource name. 4. The script appends that identifier and a timestamp to `history.log`. 5. The information remains after command completion and may be included in backups or accessed by another local principal where permissions allow. ### Impact Assessment The issue does not create a startup backdoor and therefore is not system persistence under T06. It causes unexpected cross-run retention of usage metadata. The affected informatio ...[truncated 146 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Disable persistent history logging by default. - If logging is necessary, require explicit opt-in and document the collected fields, location, purpose, and retention period. - Create the data directory and history file only when logging is enabled. - Apply restrictive permissions, such as `0700` for the directory and `0600` for the history file. - Avoid storing raw project and resource names, or redact/hash them where operationally appropriate. - Validate `APIGEN_DIR` and document that it controls a write destination. - Provide a command to inspect and delete retained history. - Ensure help-only and generation-only operations do not modify the filesystem unexpectedly. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
}}
}});

// DELETE /{name}s/:id - Delete
router.delete('/{name}s/:id', async (req, res) => {{
  try {{
    // await {cap}.findByIdAndDelete(req.params.id);
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
}}
}});

// DELETE /{name}s/:id - Delete
router.delete('/{name}s/:id', async (req, res) => {{
  try {{
    // await {cap}.findByIdAndDelete(req.params.id);
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill exposes shell execution and likely network/environment access via `bash scripts/apigen.sh ...`, but it does not declare any tool scope such as `permissions` or `allowed-tools`. This creates an unnecessary trust gap: a consumer cannot tell in advance what capabilities the skill may exercise, and any downstream script changes could broaden behavior without a corresponding manifest restriction.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This shell skill generates client code that issues HTTP GET/POST/PUT/DELETE requests, including sending request bodies and deleting resources, but the generated output only contains neutral docstrings like 'Delete a resource' and no warning that data will be transmitted to a remote API or that delete is destructive. Under the code-file criteria, these safety-relevant operations lack meaningful disclosure beyond their functional names.

Static analysis

No suspicious patterns detected.