Back to skill

Security audit

Freeapi

Security checks for vulnerabilities and agentic risk

Overview

This skill is a plausible OpenAPI client, but it handles API keys in ways that can expose them to untrusted specs, local files, or unintended network destinations.

Review carefully before installing. Only use trusted OpenAPI specs, avoid entering API keys into chat, do not store valuable tokens in a project `.env`, and do not run this against specs or servers you would not trust with the selected credentials. Prefer narrowly scoped tokens and revoke any credential that may have been used with an untrusted spec.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
index.js:111
Finding
Credential Exfiltration Through Attacker-Controlled OpenAPI Specifications<![CDATA[ ## Vulnerability Details **File Location**: `index.js:45-49`, `index.js:111-114`, `index.js:151-173` **Vulnerability Type**: Untrusted credential-to-origin binding **Risk Level**: Critical ### Vulnerable Code ```js if (specPath.startsWith('http')) { const res = await fetch(specPath); if (!res.ok) throw new Error(`Failed to fetch spec: ${res.statusText}`); content = await res.text(); } ``` ```js let url = spec.servers?.[0]?.url || 'http://localhost'; if (!url.startsWith('http')) url = `https://${url}`; // Default to https if relative or missing protocol ``` ```js // Simple Auth Injection (Bearer/API Key from ENV) // This is a heuristic: match security scheme names to ENV vars if (spec.components?.securitySchemes) { for (const [schemeName, scheme] of Object.entries(spec.components.securitySchemes)) { const envVarName = schemeName.toUpperCase().replace(/[^A-Z0-9]/g, '_'); // e.g., api_key -> API_KEY const token = process.env[envVarName] || process.env[`${envVarName}_TOKEN`] || process.env[`${envVarName}_KEY`]; if (token) { if (scheme.type === 'http' && scheme.scheme === 'bearer') { headers['Authorization'] = `Bearer ${token}`; } else if (scheme.type === 'apiKey' && scheme.in === 'header') { headers[scheme.name] = token; } } } } console.error(`Executing ${selectedMethod.toUpperCase()} ${fullUrl}`); // Log to stderr to keep stdout clean for JSON output const res = await fetch(fullUrl, { method: selectedMethod, headers, body: ['POST', 'PUT', 'PATCH'].includes(selectedMethod.toUpperCase()) ? JSON.stringify(body) : undefined, }); ``` ### Technical Analysis The OpenAPI specification controls both the destination in `servers[0].url` and the security-scheme name used to select an environment variable. The implementation converts the scheme name into an environment-variable name and automatically attaches any matching local secre ...[truncated 2069 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove heuristic environment-variable discovery based on untrusted security-scheme names. 2. Require an explicit configuration that binds each credential to: - A fixed environment-variable name. - An exact HTTPS origin. - An expected authentication scheme and header name. 3. Do not send any credential unless the final request origin exactly matches the credential's configured origin. 4. Maintain an explicit allowlist of trusted API hosts. 5. Show the user the destination host and credential identity, without exposing the credential value, before first use. 6. Reject cross-origin redirects and revalidate every redirect target. 7. Treat remotely downloaded OpenAPI documents as untrusted data. 8. Default to unauthenticated requests when a specification has not been explicitly trusted. 9. Consider requiring cryptographic verification or pinned hashes for approved specifications. 10. Add security tests using malicious specifications that attempt to map scheme names to unrelated environment variables. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.js:111
Finding
Arbitrary Network Access and Internal-Service Request Capability<![CDATA[ ## Vulnerability Details **File Location**: `index.js:45-49`, `index.js:111-114`, `index.js:168-173` **Vulnerability Type**: Unrestricted server-side request destination **Risk Level**: High ### Vulnerable Code ```js if (specPath.startsWith('http')) { const res = await fetch(specPath); if (!res.ok) throw new Error(`Failed to fetch spec: ${res.statusText}`); content = await res.text(); } ``` ```js let url = spec.servers?.[0]?.url || 'http://localhost'; if (!url.startsWith('http')) url = `https://${url}`; // Default to https if relative or missing protocol ``` ```js console.error(`Executing ${selectedMethod.toUpperCase()} ${fullUrl}`); // Log to stderr to keep stdout clean for JSON output const res = await fetch(fullUrl, { method: selectedMethod, headers, body: ['POST', 'PUT', 'PATCH'].includes(selectedMethod.toUpperCase()) ? JSON.stringify(body) : undefined, }); ``` ### Technical Analysis The Skill accepts an arbitrary OpenAPI specification and uses its first server URL without destination restrictions. It can issue `GET`, `POST`, `PUT`, `DELETE`, and `PATCH` requests to the resulting URL. No controls prevent access to loopback addresses, private networks, link-local addresses, cloud metadata services, local administration interfaces, or other endpoints reachable only from the agent's environment. There is also no DNS resolution validation or redirect-target validation. This gives an untrusted specification access to network privileges beyond those necessary for connecting to an explicitly selected public API. The behavior breaks least-privilege boundaries because the specification can select resources available from the host's trusted network position. ### Attack Path 1. An attacker creates an OpenAPI document whose server URL points to a sensitive internal endpoint. 2. The attacker defines an operation and path targeting an internal API, local service, or cloud metadata endpoint. 3. The victim supplies the document to the `run` ...[truncated 1026 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict request destinations to an explicit allowlist of approved API origins. 2. Require HTTPS and reject unsupported URL schemes. 3. Resolve destination hostnames before connecting and block: - Loopback addresses. - Private IPv4 and IPv6 ranges. - Link-local ranges. - Multicast and unspecified addresses. - Known cloud metadata addresses. 4. Revalidate the destination after every DNS resolution and redirect. 5. Disable automatic redirects or permit only same-origin redirects. 6. Require explicit user approval before communicating with a new origin. 7. Separate remote-spec retrieval permissions from API execution permissions. 8. Apply outbound network sandboxing where possible. 9. Add tests for DNS rebinding, alternate IP representations, IPv6 destinations, redirects, and metadata endpoints. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
index.js:111
Finding
API Credentials Can Be Transmitted Over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `index.js:111-114`, `index.js:151-173` **Vulnerability Type**: Sensitive data transmitted without transport encryption **Risk Level**: High ### Vulnerable Code ```js let url = spec.servers?.[0]?.url || 'http://localhost'; if (!url.startsWith('http')) url = `https://${url}`; // Default to https if relative or missing protocol ``` ```js if (spec.components?.securitySchemes) { for (const [schemeName, scheme] of Object.entries(spec.components.securitySchemes)) { const envVarName = schemeName.toUpperCase().replace(/[^A-Z0-9]/g, '_'); // e.g., api_key -> API_KEY const token = process.env[envVarName] || process.env[`${envVarName}_TOKEN`] || process.env[`${envVarName}_KEY`]; if (token) { if (scheme.type === 'http' && scheme.scheme === 'bearer') { headers['Authorization'] = `Bearer ${token}`; } else if (scheme.type === 'apiKey' && scheme.in === 'header') { headers[scheme.name] = token; } } } } console.error(`Executing ${selectedMethod.toUpperCase()} ${fullUrl}`); // Log to stderr to keep stdout clean for JSON output const res = await fetch(fullUrl, { method: selectedMethod, headers, body: ['POST', 'PUT', 'PATCH'].includes(selectedMethod.toUpperCase()) ? JSON.stringify(body) : undefined, }); ``` ### Technical Analysis The protocol check only adds `https://` when the server value does not start with the text `http`. An explicitly provided `http://` URL is accepted unchanged. Authentication headers and request bodies are then sent to that URL without checking whether transport encryption is active. Bearer tokens and API keys generally function as reusable credentials. Sending them over plaintext HTTP exposes them to passive network observers and active intermediaries. Request bodies may also contain confidential business or personal data. ### Attack Path 1. A supplied OpenAPI specification ...[truncated 916 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse server values with the standard `URL` class rather than using a string-prefix check. 2. Permit only the exact `https:` protocol for remote authenticated requests. 3. Refuse to attach authentication headers to any plaintext connection. 4. Reject HTTPS-to-HTTP redirects and validate the final URL after redirects. 5. Allow HTTP only for narrowly defined loopback development scenarios, with authentication disabled and an explicit opt-in warning. 6. Clearly report transport-security failures instead of silently modifying malformed server values. 7. Add automated tests confirming that credentials are never transmitted over HTTP. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:239
Finding
API Keys Are Persisted in Plaintext Without Enforced File Protections<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:18-21`, `index.js:239-255` **Vulnerability Type**: Insecure local secret storage **Risk Level**: Medium ### Vulnerable Documentation ```md 2. **Prompt**: "Please provide your API key for [Service]. I will save it securely to your local `.env` file." 3. **Action**: Use the `write` or `edit` tool to append the key to `.env`. * *Format:* `SERVICE_NAME_KEY=value` (e.g., `GITHUB_TOKEN=ghp_...`) 4. **Confirm**: "Key saved. You can now use freeAPI with [Service]." ``` ### Vulnerable Code ```js const envPath = path.resolve(process.cwd(), '.env'); let envContent = ''; if (fs.existsSync(envPath)) { envContent = fs.readFileSync(envPath, 'utf8'); } for (const service of selectedServices) { const { key } = await inquirer.prompt([ { type: 'password', name: 'key', message: `Enter API Key for ${service.name} (${service.key}):`, mask: '*' } ]); if (key) { // Simple append, could be smarter about replacing existing keys if (!envContent.includes(`${service.key}=`)) { fs.appendFileSync(envPath, `\n${service.key}=${key}`); console.log(`Saved ${service.key} to .env`); } else { console.log(`${service.key} already exists in .env. Skipping.`); } } } ``` ### Technical Analysis The Skill describes `.env` persistence as secure, but stores credentials as plaintext using `appendFileSync` without enforcing restrictive permissions. It does not verify whether `.env` is a regular file rather than a symbolic link, does not create or update it atomically, and does not ensure that it is excluded from version control. The documentation also instructs agents to collect API keys conversationally and write them using general-purpose file-editing tools. This can expose secrets through conversation records or tool-call histories in addition to the filesystem risks. The behavior is unnecessary at its current privilege level: a direct API clien ...[truncated 1295 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer an operating-system credential store or dedicated secrets manager instead of `.env`. 2. Do not request secrets in ordinary conversation where they may enter chat histories. 3. If file storage is explicitly selected: - Create the file atomically with mode `0600`. - Verify that the destination is a regular file and reject symbolic links. - Preserve or tighten permissions when updating an existing file. - Use an atomic read-modify-write operation rather than blind append. 4. Ensure `.env` is listed in `.gitignore` and warn if it is already tracked. 5. Store only credentials required for the currently configured service. 6. Explain accurately that `.env` is plaintext storage rather than describing it as inherently secure. 7. Support short-lived, narrowly scoped credentials and provide revocation guidance. 8. Avoid printing secret values and prevent them from entering logs, errors, telemetry, or command history. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (19)

Ssd 3

High
Confidence
98% confidence
Finding
This onboarding flow directs the agent to request sensitive credentials from the user and then use write/edit capabilities to store them locally. That creates a direct secret-handling pathway inside the agent, which is dangerous because prompt injection, logging, transcript retention, workspace access, or later tool misuse could expose or misuse those credentials.

Ssd 3

High
Confidence
97% confidence
Finding
The example thought process reinforces a norm that when a secret is missing, the correct next step is to ask for it and save it before proceeding. This is risky because examples often become operational behavior, causing agents to habitually solicit and persist high-value credentials rather than using safer out-of-band configuration methods.

Credential Access

High
Category
Privilege Escalation
Content
import YAML from 'yaml';
import inquirer from 'inquirer';

// Load environment variables from .env file
dotenv.config();

const SERVICES = [
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
console.log('\n--- Configuring Keys ---');
    
    const envPath = path.resolve(process.cwd(), '.env');
    let envContent = '';
    if (fs.existsSync(envPath)) {
      envContent = fs.readFileSync(envPath, 'utf8');
Confidence
94% confidence
Finding
Resolving and using .env in the current working directory enables the tool to persist credentials into whichever folder the user happens to be in, which may be a shared repo, synced workspace, or otherwise untrusted location. Because the same application also auto-loads .env and can inject secrets into arbitrary spec-defined requests, this creates a practical credential exposure and misuse path.

Known Vulnerable Dependency: lodash==4.17.23 — 2 advisory(ies): CVE-2025-13465 (lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and ); CVE-2021-23337 (lodash vulnerable to Code Injection via `_.template` imports key names)

High
Category
Supply Chain
Confidence
91% confidence
Finding
The lockfile pins lodash 4.17.23, and the cited advisories describe real classes of risk for applications that expose affected functionality, including prototype pollution in _.unset and code injection through _.template. Even though a lockfile alone does not prove the vulnerable APIs are reachable, shipping a known-vulnerable dependency is a true supply-chain weakness because downstream code or future changes may invoke those paths.

Known Vulnerable Dependency: tmp==0.0.33 — 2 advisory(ies): CVE-2025-54798 (tmp allows arbitrary temporary file / directory write via symbolic link `dir` pa); CVE-2026-44705 (tmp has Path Traversal via unsanitized prefix/postfix that enables directory esc)

High
Category
Supply Chain
Confidence
88% confidence
Finding
The dependency tree includes tmp 0.0.33, and the reported issues indicate unsafe temporary file handling and path manipulation weaknesses that can lead to arbitrary file or directory write when attacker-controlled inputs influence temp paths. In a CLI-oriented package with interactive/editor-related dependencies, temp-file usage is plausible, which makes this more than a theoretical concern if the vulnerable code path is exercised.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
### 1. Onboarding (The "Integral" Method)

Do not ask users to run raw CLI commands unless they prefer it. Instead, **guide them conversationally**:

1.  **Ask**: "Which service do you want to connect? (e.g., GitHub, Stripe, OpenAI)"
2.  **Prompt**: "Please provide your API key for [Service]. I will save it securely to your local `.env` file."
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly instructs the agent to ask users for API keys and write them into a local `.env` file, while assuring users this is secure without discussing risks such as plaintext secret storage, accidental commits, shell/history exposure, or unauthorized local access. In agent contexts, normalizing conversational collection and persistence of secrets increases the chance of unsafe credential handling and secret sprawl.

External Transmission

Medium
Category
Data Exfiltration
Content
When a user asks to perform an action (e.g., "Check my GitHub issues"):

1.  **Locate Spec**: Find the OpenAPI spec URL (e.g., `https://api.github.com/openapi/v3`).
2.  **Check Keys**: Verify the key exists in `.env`. If not, trigger the **Onboarding** flow above.
3.  **Run**: Use `node skills/freeAPI/index.js run` with the spec and parameters.
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The tool prompts for a large set of unrelated third-party service credentials despite having no constrained business purpose or per-service justification. Bulk credential collection expands blast radius significantly: a user may store many high-value secrets that can later be misused by arbitrary spec-driven requests or other local processes.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The CLI presents itself as a bare OpenAPI client but also includes an interactive credential-harvesting/setup workflow that writes secrets into a local .env file. Understating that behavior is risky because users may invoke the tool without realizing it solicits and persists sensitive credentials on disk.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The run command fetches a user-supplied OpenAPI spec and executes arbitrary operations against remote endpoints, while auto-injecting matching environment credentials into requests. Without strong warnings or trust controls, users may unknowingly send sensitive data or authenticated requests to attacker-controlled servers described by a malicious spec.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The setup flow writes API keys directly to a local .env file without prominently warning that secrets are being persisted to disk in the current working directory. This can expose credentials through accidental check-in, insecure file permissions, backups, shell history/workspace sharing, or use in untrusted directories.

Known Vulnerable Dependency: yaml==2.8.2 — 1 advisory(ies): CVE-2026-33532 (yaml is vulnerable to Stack Overflow via deeply nested YAML collections)

Low
Category
Supply Chain
Confidence
80% confidence
Finding
The project directly depends on yaml 2.8.2, and the advisory describes a stack overflow/denial-of-service condition when parsing deeply nested YAML collections. Because this package appears to intentionally process YAML, the skill context increases relevance: if untrusted YAML input is accepted, an attacker may crash the process or degrade availability.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"start": "node index.js"
  },
  "dependencies": {
    "commander": "^11.0.0",
    "dotenv": "^16.3.1",
    "inquirer": "^9.2.12",
    "yaml": "^2.3.1"
Confidence
91% confidence
Finding
The dependency uses a caret version range, which allows newer compatible releases to be installed over time. This can introduce supply-chain risk and reduce build reproducibility, especially if a future upstream release is compromised or introduces a security regression.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "dependencies": {
    "commander": "^11.0.0",
    "dotenv": "^16.3.1",
    "inquirer": "^9.2.12",
    "yaml": "^2.3.1"
  },
Confidence
91% confidence
Finding
The dependency uses a caret version range, which allows newer compatible releases to be installed over time. This can introduce supply-chain risk and reduce build reproducibility, especially if a future upstream release is compromised or introduces a security regression.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"dependencies": {
    "commander": "^11.0.0",
    "dotenv": "^16.3.1",
    "inquirer": "^9.2.12",
    "yaml": "^2.3.1"
  },
  "author": "xethis",
Confidence
91% confidence
Finding
The dependency uses a caret version range, which allows newer compatible releases to be installed over time. This can introduce supply-chain risk and reduce build reproducibility, especially if a future upstream release is compromised or introduces a security regression.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"commander": "^11.0.0",
    "dotenv": "^16.3.1",
    "inquirer": "^9.2.12",
    "yaml": "^2.3.1"
  },
  "author": "xethis",
  "license": "MIT",
Confidence
91% confidence
Finding
The dependency uses a caret version range, which allows newer compatible releases to be installed over time. This can introduce supply-chain risk and reduce build reproducibility, especially if a future upstream release is compromised or introduces a security regression.

Known Vulnerable Dependency: yaml==2.8.2 — 1 advisory(ies): CVE-2026-33532 (yaml is vulnerable to Stack Overflow via deeply nested YAML collections)

Low
Category
Supply Chain
Confidence
60% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
index.js:150