Back to skill

Security audit

swagger-skill

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Swagger API helper, but it automatically installs npm packages and can send credentials, API data, and local files to arbitrary endpoints with limited safeguards.

Install only if you are comfortable reviewing the code and controlling where it runs. Use it with trusted Swagger URLs, prefer HTTPS, avoid entering broad tokens or cookies, do not upload sensitive local files unless the destination is verified, and be aware that first import may install npm packages into the skill directory.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
index.js:10
Finding
Automatic Installation of Unpinned Dependencies During Module Import<![CDATA[ ## Vulnerability Details **File Location**: `index.js:10-25` **Vulnerability Type**: Supply-chain exposure through automatic, unpinned dependency installation **Risk Level**: Medium ### Vulnerable Code ```javascript function ensureDependencies() { const deps = ['axios', 'form-data']; const missing = deps.filter(dep => { try { require.resolve(dep); return false; } catch { return true; } }); if (missing.length > 0) { const pkgJsonPath = path.join(__dirname, 'package.json'); try { require.resolve(pkgJsonPath); } catch { execSync(`npm init -y --prefix "${__dirname}" && node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('${pkgJsonPath}','utf8'));p.type='module';fs.writeFileSync('${pkgJsonPath}',JSON.stringify(p,null,2))"`, { stdio: 'pipe' }); } execSync(`npm install --prefix "${__dirname}" ${missing.join(' ')}`, { stdio: 'pipe' }); } } ensureDependencies(); ``` ### Technical Analysis Importing `index.js` immediately invokes `ensureDependencies()`. If `axios` or `form-data` cannot be resolved, the Skill runs `npm install` using package names without pinned versions or lockfile verification. This introduces a supply-chain trust boundary at runtime. The effective package content depends on the npm registry and configuration present when the Skill is imported, rather than on artifacts reviewed with the Skill. npm package installation may also execute package lifecycle scripts with the privileges of the current process. Automatic package installation and creation or modification of `package.json` are import-time side effects. They exceed the minimum privileges necessary for loading an API client module because dependency provisioning can be performed explicitly before execution. ### Attack Path 1. The Skill is imported in an environment where one or both dependencies are absent. 2. `ensureDependencies()` executes automatically. 3. The process resolves the unversioned package names through the config ...[truncated 835 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `ensureDependencies()` and all automatic installation behavior from module initialization. 2. Declare dependencies in a committed `package.json` using reviewed, exact versions. 3. Commit a package-lock file and provision dependencies using `npm ci`. 4. Perform dependency installation as a separate, explicit setup step rather than during import. 5. Use registry integrity verification and automated dependency vulnerability scanning. 6. Consider `npm ci --ignore-scripts` if dependency lifecycle scripts are not required. 7. Run installation and execution under a restricted account with minimal filesystem and network permissions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
index.js:112
Finding
Authentication Credentials Can Be Transmitted Over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Locations**: `index.js:62-67`, `index.js:112-118`, `index.js:240-251`, `index.js:302-310`; documented plaintext usage at `SKILL.md:75-89` **Vulnerability Type**: Plaintext transmission of authentication tokens, cookies, request bodies, and uploaded files **Risk Level**: High ### Vulnerable Code Credential header construction: ```javascript setAuthToken(token, options = {}) { if (!token || typeof token !== 'string') { return { success: false, message: 'Token 必须是非空字符串' }; } const tokenType = options.tokenType || 'Bearer'; const headerName = options.headerName || 'Authorization'; this.authToken = token; this.authHeaders = { ...this.authHeaders, [headerName]: `${tokenType} ${token}` }; return { success: true, message: '认证 Token 已设置' }; } ``` Transmission while fetching the specification: ```javascript let specUrl = url; if (!url.match(/\/(swagger\.json|openapi\.json|api-docs|v3\/api-docs)$/)) { specUrl = url.endsWith('/') ? url + 'swagger.json' : url + '/swagger.json'; } const response = await axios.get(specUrl, { headers: this.authHeaders }); this.swaggerSpec = response.data; this.baseUrl = url.replace(/\/(swagger\.json|openapi\.json|v3\/api-docs)$/, ''); ``` Transmission during API calls: ```javascript const url = this._buildURL(path, params.query); const isFormData = params.isFormData || (params.body instanceof FormData); const config = { method: method.toLowerCase(), url, headers: isFormData ? { ...this.authHeaders, ...params.headers } : { 'Content-Type': 'application/json', ...this.authHeaders, ...params.headers } }; if (params.body) config.data = params.body; if (params.query) config.params = params.query; const response = await axios(config); ``` Transmission during file uploads: ```javascript const url = this._buildURL(path, query); const config = { method: 'post', url, data: form, headers: { ...form.getHeaders(), ...this.authHeaders } }; if (query) config.param ...[truncated 2379 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject non-HTTPS URLs whenever tokens, cookies, custom authorization headers, request bodies, or file uploads are present. 2. If local development requires HTTP, permit it only for verified loopback destinations such as `127.0.0.1`, `::1`, or `localhost`, and require an explicit insecure-transport opt-in. 3. Display a prominent warning before any credential is transmitted over an insecure connection. 4. Disable redirects for authenticated requests or validate every redirect target before following it. 5. Strip all authorization and cookie headers when a redirect changes scheme, hostname, or port. 6. Validate URL schemes and reject unsupported protocols. 7. Replace plaintext HTTP examples in `SKILL.md` with HTTPS examples, except for clearly identified loopback-only development cases. 8. Document the exact destinations to which credentials, request bodies, and files will be sent. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
cli.js:35
Finding
CLI Authentication Secrets Are Echoed in Cleartext During Entry<![CDATA[ ## Vulnerability Details **File Location**: `cli.js:35-58` **Vulnerability Type**: Cleartext display of authentication secrets in an interactive terminal **Risk Level**: Low ### Vulnerable Code ```javascript // 获取 Token(可选) const tokenInput = await prompt('请输入认证 Token (可选,按 Enter 跳过): '); if (tokenInput.trim()) { token = tokenInput.trim(); console.log('✓ Token 已设置\n'); } else { console.log('✓ 未设置 Token\n'); } // 获取 Cookie(可选,JSON 格式) const cookieInput = await prompt('请输入认证 Cookie (JSON 格式,可选,按 Enter 跳过): '); if (cookieInput.trim()) { try { const parsed = JSON.parse(cookieInput); const cookieResult = skill.setAuthCookies(parsed); if (!cookieResult.success) { console.error(`❌ Cookie 设置失败: ${cookieResult.message}`); rl.close(); return; } cookies = parsed; console.log('✓ Cookie 已设置\n'); } catch (e) { console.error('❌ Cookie JSON 格式错误'); rl.close(); return; } } ``` The prompt implementation uses ordinary readline input: ```javascript function prompt(question) { return new Promise(resolve => { rl.question(question, resolve); }); } ``` ### Technical Analysis Node.js `readline.question()` uses normal terminal input and does not suppress character echo. Tokens and serialized cookie values are therefore displayed visibly as the user types them. Although the code does not subsequently print the secret values, the original entry can remain visible in the terminal scrollback and may be captured by terminal session recording, screen sharing, screenshots, or nearby observers. ### Attack Path 1. The user starts the interactive CLI. 2. The CLI requests an authentication token or cookie object. 3. The user types the secret using a normal `readline.question()` prompt. 4. The terminal displays each entered character. 5. A nearby observer, screen-sharing participant, terminal recorder, or captured screenshot obtains the secret. 6. The observer reuses the credential against the associated ...[truncated 400 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use a secret-input routine that disables terminal echo while tokens and cookies are entered. 2. Restore terminal settings in a `finally` block so input remains usable after interruption or errors. 3. Prefer protected environment variables, operating-system credential stores, or restricted file descriptors for automation. 4. Avoid accepting complete cookie JSON objects interactively when a narrower authentication mechanism is sufficient. 5. Ensure secrets are not added to command-line arguments, shell history, logs, error messages, or debug output. 6. Clear in-memory references to CLI credential strings when they are no longer needed. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (14)

Ae1

High
Category
analysis-evasion
Content
import SwaggerAPISkill from './index.js';
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
import SwaggerAPISkill from './index.js';
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
import SwaggerAPISkill from './index.js';
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The skill runs `npm init` and `npm install` at runtime via `execSync`, causing code and package changes on the host without explicit user approval. This expands the trust boundary from the skill code to the npm registry and install scripts, creating supply-chain and arbitrary code execution risk that is unrelated to basic Swagger querying functionality.

Missing User Warnings

High
Confidence
96% confidence
Finding
The upload feature reads arbitrary local file paths using `fs.createReadStream` and posts them over HTTP without disclosure or confirmation. This can exfiltrate sensitive local files if the caller is tricked into invoking uploads against an attacker-controlled or untrusted API endpoint.

External Transmission

Medium
Category
Data Exfiltration
Content
const skill = new SwaggerAPISkill();

// 1. 加载 Swagger 规范
await skill.fetchSwaggerSpec('https://api.example.com/swagger.json');

// 2. 获取所有接口
const allAPIs = skill.getAllAPIs();
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly supports fetching remote Swagger specs, invoking arbitrary APIs, and uploading files, but its safety guidance does not warn users that these operations may transmit sensitive data to third parties or perform state-changing actions on remote systems. In an agent context, missing disclosure increases the chance of unintended data exfiltration, unsafe file transfer, or accidental modification/deletion of remote resources.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The code prompts for a Token and Cookie, stores them, and passes them into fetchSwaggerSpec for a network request. Although the user is asked to provide credentials, there is no explicit disclosure that these sensitive values will be sent to the remote URL they entered, which is a privacy- and safety-relevant operation.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The callAPI flow accepts any path and HTTP method, including POST, PUT, and DELETE, and immediately executes the request after collecting parameters. There is no user-facing warning or confirmation that the action may modify or delete remote data, making safety-critical operations insufficiently disclosed.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The code automatically initializes a package and installs missing dependencies with no disclosure or consent. Even if intended as convenience behavior, it performs privileged environment modification and may trigger package install scripts, which users would not reasonably expect from an API helper skill.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
`fetchSwaggerSpec` can send bearer tokens and cookies to arbitrary URLs supplied to the skill, without validation or user-facing confirmation. In a skill designed to consume external Swagger endpoints, this creates SSRF-style credential exposure and accidental secret transmission risk if an attacker influences the target URL.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The general API execution path sends request bodies, query data, custom headers, and stored authentication headers to whatever endpoint was loaded, with no confirmation or guardrails. Because this skill is expressly built to invoke APIs from natural-language instructions, mistaken endpoint selection or maliciously chosen specs can lead to unintended state-changing requests and credential leakage.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
Nearly all user-facing prompts and status messages are written only in Chinese, with no option to select another language. This creates a natural-language policy concern because the skill imposes a specific locale on all users without opt-in or documented justification.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
The file contains numerous user-facing strings and inline comments in Chinese, such as status/error messages returned to callers, with no indication that language selection is optional. That can violate a language/locale policy when the skill implicitly forces one language without user opt-in or documented regional scope.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
index.js:18