Back to skill

Security audit

Swagger V2 Retrofit Generator

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it handles API credentials and generates app source code with too little safety guidance or input hardening.

Install only if you are comfortable reviewing generated Kotlin before it is compiled, and use it only with trusted Swagger documents. Prefer HTTPS URLs, short-lived read-only credentials, and safer secret input methods than command-line passwords or tokens. Avoid query-string API keys and avoid fetching from untrusted or internal-only URLs unless you understand the network exposure.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/fetch_swagger.py:41
Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch_swagger.py:41-44, 78-80` **Vulnerability Type**: Server-Side Request Forgery through unrestricted URL fetching **Risk Level**: High ### Vulnerable Code ```python request_url = url request = urllib.request.Request(request_url, method='GET') request.add_header('Accept', 'application/json') # Authentication handling omitted try: with urllib.request.urlopen(request, timeout=30) as response: data = response.read().decode('utf-8') return json.loads(data) ``` ### Technical Analysis The script passes a user-supplied URL directly to `urllib.request.urlopen()` without validating: - The URL scheme - The destination hostname or port - Resolved IP addresses - Loopback, link-local, private, or reserved address ranges - Redirect destinations - The number of redirects - Response size or expected content type Consequently, the process can be induced to send requests to resources accessible from its own network context. These may include loopback services, private network applications, container-management interfaces, or cloud instance metadata endpoints. The function parses a successful response as JSON, and the caller subsequently writes that data to stdout or a selected output file. Therefore, JSON-compatible internal responses can be returned to the user invoking the Skill. ### Attack Path 1. An attacker supplies a Swagger URL pointing to an internal service, local address, or attacker-controlled redirect. 2. The Agent invokes `fetch_swagger.py` with that URL as part of the Skill's documented workflow. 3. `urlopen()` resolves and accesses the destination using the Agent host's network privileges. 4. If the destination returns valid JSON, the script parses it successfully. 5. The parsed response is printed to stdout or saved to a file. 6. The attacker obtains data from a service that may not have been directly reachable from the attacker's own network position. ### Impact Ass ...[truncated 673 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit only `https://` URLs by default. 2. Parse the URL before opening it and reject unsupported schemes, embedded credentials, malformed hostnames, and unexpected ports. 3. Resolve all destination addresses and reject loopback, private, link-local, multicast, unspecified, and reserved ranges. 4. Disable automatic redirects or validate every redirect destination using the same scheme, hostname, port, and resolved-address rules. 5. Support an explicit hostname allowlist for controlled Agent deployments. 6. Limit response size before reading the entire body into memory. 7. Verify that the response has an expected JSON content type before processing it. 8. Reject URL fragments and normalize hostnames to prevent validation bypasses. 9. Consider requiring explicit user confirmation for destinations outside a configured API domain. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_swagger.py:46
Finding
Authentication Secrets Can Be Exposed Through Plaintext Transport, URLs, and Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch_swagger.py:46-78, 108-126`; `SKILL.md:24-33, 233-247` **Vulnerability Type**: Insecure credential transmission and handling **Risk Level**: High ### Vulnerable Code ```python if auth_type == 'basic': if not username or not password: print('Basic auth requires both --username and --password', file=sys.stderr) sys.exit(2) credentials = base64.b64encode(f"{username}:{password}".encode()).decode() request.add_header('Authorization', f'Basic {credentials}') elif auth_type == 'bearer': if not token: print('Bearer auth requires --token', file=sys.stderr) sys.exit(2) request.add_header('Authorization', f'Bearer {token}') elif auth_type == 'api-key': if not api_key: print('API Key auth requires --api-key', file=sys.stderr) sys.exit(2) if api_key_in == 'header': request.add_header(api_key_name, api_key) else: parsed = urllib.parse.urlsplit(url) query = urllib.parse.parse_qsl(parsed.query, keep_blank_values=True) query.append((api_key_name, api_key)) new_query = urllib.parse.urlencode(query) request_url = urllib.parse.urlunsplit( (parsed.scheme, parsed.netloc, parsed.path, new_query, parsed.fragment) ) request = urllib.request.Request(request_url, method='GET') request.add_header('Accept', 'application/json') try: with urllib.request.urlopen(request, timeout=30) as response: ``` Secrets are also accepted directly as command-line arguments: ```python parser.add_argument( '-p', '--password', help='Password for Basic Authentication' ) parser.add_argument( '--token', help='Token for Bearer Authentication' ) parser.add_argument( '--api-key', help='Value for API Key Authentication' ) ``` The documentation explicitly demonstrates HTTP and literal command-line credentials: ```bash python scripts/fetch_swagger.py htt ...[truncated 2822 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require HTTPS whenever any authentication method is enabled. 2. Reject authenticated requests to plaintext HTTP destinations rather than merely warning. 3. Reject HTTPS-to-HTTP redirects and prevent credentials from being forwarded across origins. 4. Disable query-string API keys by default. If legacy support is unavoidable, require an explicit high-risk opt-in and display a warning. 5. Accept secrets through safer channels, such as: - Interactive hidden prompts with `getpass` - Protected files with restrictive permissions - Environment variables, with documentation about their own exposure risks - Standard input or a dedicated secret-provider integration 6. Avoid including secrets or secret-bearing URLs in diagnostic output. 7. Update every documentation example to use HTTPS. 8. Remove literal example passwords such as `admin` and show secure secret-input methods instead. 9. Clear temporary in-memory references where practical and never persist credentials alongside fetched Swagger documents. 10. Document the required minimum API scope and recommend short-lived, read-only credentials dedicated to documentation retrieval. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_retrofit.py:516
Finding
Untrusted Swagger Fields Can Inject Arbitrary Kotlin Source into Generated Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_retrofit.py:516-530, 543-584, 614, 643` **Vulnerability Type**: Generated-source code injection **Risk Level**: High ### Vulnerable Code Swagger model descriptions and property names are inserted without Kotlin-aware escaping or identifier validation: ```python def generate_model_class(self, model: ModelClass) -> str: """Generate Kotlin data class for a model.""" lines = [] # Doc comment if model.description: lines.append(f'/**') lines.append(f' * {model.description}') lines.append(f' */') lines.append(f'data class {model.name}(') # Properties props = [] for prop in model.properties: doc = f' // {prop.description}' if prop.description else '' props.append(f' val {prop.name}: {prop.type_name}{doc}') lines.append(',\n'.join(props)) lines.append(')') ``` Swagger summaries, descriptions, tags, endpoint paths, and parameter names are also inserted directly: ```python if doc_parts: lines.append(f' /**') for part in doc_parts: lines.append(f' * {part}') lines.append(f' */') # HTTP method annotation annotation = self.HTTP_METHOD_ANNOTATIONS.get(endpoint.method, '@GET') lines.append(f' {annotation}("{endpoint.path}")') # Build parameters params = [] body_param = None for param in endpoint.parameters: param_name = param.get('name', '') param_in = param.get('in', '') required = param.get('required', False) if param_in == 'path': params.append(f'@Path("{param_name}") {param_name}: {parser.get_type(param)}') elif param_in == 'query': param_type = parser.get_type(param) if not required: param_type = f'{param_type}? = null' params.append(f'@Query("{param_name}") {param_name}: {param_type}') elif param_in == 'header': param_type = parser.get_type(param) if not required: param_type = ...[truncated 3219 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all Swagger fields as untrusted input. 2. Validate every generated Kotlin identifier against Kotlin grammar, including: - Property names - Parameter names - Package components - Service interface names - Model names - Method names 3. Handle Kotlin keywords by rejecting them or applying safe backtick escaping. 4. Escape all Kotlin string-literal content, including quotation marks, backslashes, dollar signs, carriage returns, newlines, and control characters. 5. Sanitize KDoc and line comments by neutralizing `*/`, embedded newlines, and other source-terminating sequences. 6. Prefer a structured Kotlin source-generation library rather than manual string concatenation. 7. Reject unexpected control characters and impose reasonable length limits on paths, names, descriptions, summaries, and tags. 8. Detect sanitized-name collisions so different attacker-controlled names cannot resolve to the same generated identifier. 9. Generate into a staging directory rather than directly into an application source tree. 10. Require review or display a warning before generated files from remote specifications are compiled. 11. Add adversarial tests containing quotes, backslashes, newlines, comment terminators, Kotlin keywords, annotations, and declaration syntax in every Swagger-controlled field. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The implemented script accurately covers the fetching/authentication portion of the description, including HTTP retrieval of Swagger v2 docs with none/basic/bearer/api-key auth and optional file output. However, the declared primary purpose is broader and centered on generating Android Retrofit/Kotlin client code from Swagger documentation. No code generation logic exists in this chunk: it neither parses Swagger into Kotlin models nor emits Retrofit service interfaces. Therefore the description materially overstates the code's functionality, making it a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code clearly matches the core code-generation portion of the description: it reads Swagger v2 JSON, parses definitions and paths, supports endpoint filtering/search/tag selection, and generates Retrofit/Kotlin models and service interfaces. However, the declared description materially claims support for fetching Swagger docs via HTTP with multiple auth schemes. This code has no networking logic, no HTTP client usage, no URL input handling beyond a local file path or stdin, and no auth-related implementation. Therefore the description overstates key capabilities that are not present in the supplied code chunk.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill promotes fetching authenticated Swagger documents over plain HTTP without warning that Basic Auth, bearer tokens, or API keys could be transmitted in cleartext. In this context the danger is elevated because the skill specifically supports multiple credential types and demonstrates insecure http:// URLs in examples.

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
使用 `scripts/generate_retrofit.py` 生成代码:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Static analysis

No suspicious patterns detected.