Back to skill

Security audit

Vast Ai

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real VAST.ai GPU rental wrapper, but it can create paid cloud instances without code-enforced confirmation, limits, or teardown support.

Review carefully before installing. Use a limited VAST.ai API key if possible, keep DEBUG unset, rotate the key if it has appeared in logs, and only run rent after manually verifying the offer, hourly price, balance, and how you will stop or destroy the instance. The publisher should add code-level confirmation, spending limits, safer logging, dependency updates, and an exposed teardown path before this is treated as low risk.

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

T09 · Insecure Skill Coding Practices

Warning
Location
src/adapter.ts:14
Finding

Billable GPU Rentals Bypass Documented Confirmation and Balance Safeguards

Content
View full analysis

Vulnerability Details

File Location: src/adapter.ts:14-16
Vulnerability Type: Missing authorization and financial precondition enforcement
Risk Level: Medium

Vulnerable Code

typescript
case 'rent':
    // params: { id: number, image: string }
    return await client.rent(params.id, params.image);

The safeguards that should precede this operation appear only in SKILL.md:10-17:

markdown
- **Pre-flight Check**: Before renting, call `balance` to ensure the user has sufficient funds.
- **Step 2**: Search for offers and present the top 3 cheapest options to the user.
- **Step 3**: Upon confirmation, call `rent`.
- **Reporting**: If credit is below $5.00, warn the user after every successful rental.

Technical Analysis

The rent action creates a billable VAST.ai instance, but the adapter does not enforce the documented user-confirmation or balance-check requirements. It accepts an action and parameters from its caller and immediately invokes client.rent().

Security-sensitive and financially consequential controls cannot safely rely solely on natural-language agent instructions. A direct API caller, an incorrectly behaving agent, or manipulated upstream input can invoke the adapter without following SKILL.md. The implementation also does not reject malformed or unexpected rental identifiers and does not enforce a minimum balance or spending limit.

Attack Path

  1. An attacker or erroneous upstream agent gains the ability to invoke VastSkill.execute() with the victim's execution context.
  2. The caller submits the rent action with an offer ID and optional image:
    typescript
    VastSkill.execute("rent", { id: 12345, image: "pytorch/pytorch" }, context)
    
  3. The adapter does not require proof of user confirmation.
  4. The adapter does not call getBalance() or verify that sufficient credit is available.
  5. VastClient.rent() issues a PUT request t ...[truncated 685 chars]
Remediation
View remediation

Remediation Suggestions

  1. Enforce confirmation in code rather than relying on agent instructions. Require a short-lived, server-generated confirmation token bound to the selected offer, image, price, account, and expiration time.
  2. Query the current account balance immediately before creating the instance and reject the operation if the configured minimum balance or spending policy is not satisfied.
  3. Obtain the authoritative offer price immediately before rental and enforce an explicit user-approved maximum hourly price.
  4. Validate params.id as a positive safe integer and restrict image values to an approved allowlist or require explicit confirmation for custom images.
  5. Add account-level controls such as maximum hourly burn, maximum concurrent instances, and per-operation spending limits.
  6. Return the required low-credit warning from the implementation so it cannot be omitted by the calling agent.
  7. Record a security audit event for each attempted and completed rental without recording the API key.
  8. Add automated tests proving that rentals fail without confirmation, with expired or mismatched confirmation tokens, and when financial limits are exceeded.

T09 · Insecure Skill Coding Practices

Warning
Location
src/cli.ts:33
Finding

Debug Error Logging Can Expose the VAST.ai Bearer Token

Content
View full analysis

Vulnerability Details

File Location: src/cli.ts:33-35
Related Secret Assignment: src/DynamicApi.ts:180-182
Vulnerability Type: Sensitive credential exposure through verbose error logging
Risk Level: Medium

Vulnerable Code

src/cli.ts:33-35 logs the complete error object when DEBUG is enabled:

typescript
} catch (error: any) {
    console.error('Error executing action:', error.message || error);
    // Print full error if verbose
    if (process.env.DEBUG) console.error(error);
    process.exit(1);
}

The bearer credential is assigned to Axios's default request headers in src/DynamicApi.ts:180-182:

typescript
setAuthToken(token: string) {
    this.axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${token}`;
}

Technical Analysis

Axios errors commonly include the request configuration used for the failed operation. That configuration can contain request headers, including the Authorization header populated by setAuthToken().

Printing the complete error object without redaction can therefore disclose the VAST.ai API key to stderr. In production, CI, container, or agent environments, stderr is often retained by centralized logging systems and may be accessible to more users or services than the original secret.

The ordinary error message at line 33 is substantially safer, but the conditional full-object logging at line 35 defeats that protection whenever the DEBUG environment variable is set to any non-empty value.

Attack Path

  1. The CLI starts with a valid VAST_API_KEY and a non-empty DEBUG environment variable.
  2. VastClient places the API key in Axios's default Authorization header.
  3. An API request is made to VAST.ai.
  4. A network failure, timeout, rejected request, rate-limit response, or other Axios error occurs. An attacker who can influence network conditions or request parameters may deliberately trigger su ...[truncated 1010 chars]
Remediation
View remediation

Remediation Suggestions

  1. Never log the complete Axios error object. Emit only an allowlisted set of fields, such as error name, safe message, error code, and HTTP status.
  2. Implement centralized recursive redaction for Authorization, Proxy-Authorization, cookies, API keys, tokens, and sensitive request bodies before any diagnostic object is logged.
  3. Replace the current debug block with sanitized output, for example:
    typescript
    if (process.env.DEBUG) {
        console.error({
            name: error?.name,
            message: error?.message,
            code: error?.code,
            status: error?.response?.status
        });
    }
    
  4. Ensure logging infrastructure applies an additional secret-redaction layer before retaining or forwarding output.
  5. Treat any key that may already have appeared in debug logs as compromised: revoke or rotate it and remove exposed log records according to the organization's incident-response policy.
  6. Add tests using a synthetic bearer token to verify that neither normal nor debug error output contains the token or the Authorization header.
  7. Limit access to CI, container, and centralized logs and configure appropriate retention periods.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (16)

Known Vulnerable Dependency: axios==1.13.4 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding

The lockfile pins axios 1.13.4, and the supplied advisory set includes high-severity issues such as NO_PROXY normalization bypass leading to SSRF and prototype-pollution-related man-in-the-middle or credential theft scenarios. Because this is a network client library commonly used to make outbound HTTP requests, a vulnerable version can directly affect request routing, proxy handling, header safety, and trust boundaries in an agent skill.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
93% confidence
Finding

The lockfile contains form-data 4.0.5, which is flagged for CRLF injection through unescaped multipart field names and filenames. If any part names or filenames can be influenced by external input, an attacker may be able to inject malformed multipart headers or manipulate downstream parsers, potentially leading to request smuggling-style effects, header injection, or unexpected server-side behavior.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: axios==1.13.4 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
98% confidence
Finding

The package explicitly depends on axios 1.13.4, and the static analysis reports multiple known advisories affecting that version, including SSRF-related and prototype-pollution/MITM-adjacent issues. Because this skill appears to interact with an external service (vast.ai), a vulnerable HTTP client increases the chance that hostile input, proxy settings, or request handling edge cases could be abused to leak credentials, bypass network controls, or tamper with traffic.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly documents a rent command that creates GPU instances but does not warn that this action provisions billable cloud resources and can incur ongoing charges. In an agent-skill context, omission of cost/safety warnings is more dangerous because an LLM-driven agent or inattentive user may execute the command directly, leading to unintended financial loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code defines safety-impacting remote actions, including creating and deleting cloud instances, but provides no confirmation prompt, logging, print statement, or explanatory docstring/comment warning the user about those effects. These operations can incur cost or destroy running resources, so the absence of any disclosure matches the missing-warning criterion for code files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code reads an API credential from context.API_KEY to initialize the VAST client, but there is no user-facing log, prompt, comment, or docstring disclosing that sensitive credential material is being used. Under the code-file criteria, access to sensitive environment variables or credentials should be flagged when there is no visible disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The rent action performs a billable, state-changing operation immediately from caller-supplied parameters with no confirmation, authorization check, policy gate, spending limit, or dry-run safeguard. In an agent setting, ambiguous prompts, prompt injection, or accidental tool invocation could cause unintended GPU rentals and direct financial loss.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: follow-redirects==1.15.11 — 1 advisory(ies): CVE-2026-40895 (follow-redirects leaks Custom Authentication Headers to Cross-Domain Redirect Ta)

Low
Category
Supply Chain
Confidence
91% confidence
Finding

The lockfile includes follow-redirects 1.15.11, which is flagged for leaking custom authentication headers across cross-domain redirects. In an agent or integration context, outbound requests may carry API keys or bearer tokens, so improper redirect handling can expose credentials to attacker-controlled destinations if redirects are followed automatically.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 14)May include surrounding context.

json
"license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "axios": "^1.13.4",
    "limiter": "^3.0.0",
    "minimist": "^1.2.8"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 15)May include surrounding context.

json
"type": "commonjs",
  "dependencies": {
    "axios": "^1.13.4",
    "limiter": "^3.0.0",
    "minimist": "^1.2.8"
  },
  "devDependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 16)May include surrounding context.

json
"dependencies": {
    "axios": "^1.13.4",
    "limiter": "^3.0.0",
    "minimist": "^1.2.8"
  },
  "devDependencies": {
    "@types/minimist": "^1.2.5",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 19)May include surrounding context.

json
"minimist": "^1.2.8"
  },
  "devDependencies": {
    "@types/minimist": "^1.2.5",
    "@types/node": "^25.2.0",
    "typescript": "^5.9.3"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 20)May include surrounding context.

json
},
  "devDependencies": {
    "@types/minimist": "^1.2.5",
    "@types/node": "^25.2.0",
    "typescript": "^5.9.3"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 21)May include surrounding context.

json
"devDependencies": {
    "@types/minimist": "^1.2.5",
    "@types/node": "^25.2.0",
    "typescript": "^5.9.3"
  }
}

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The getBalance method retrieves account-level information including credit, email, and account ID from the remote API, which is sensitive user/account data. In this file there is no user-facing warning, logging, or docstring/comment disclosing that such account data will be accessed and returned.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.