Back to skill

Security audit

x402janus-acp

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but it can spend marketplace funds and send an ACP API key to a configurable endpoint without strong safeguards.

Review before installing. Use this only with an ACP key scoped for buying scans, set JANUS_OFFERING_NAME explicitly, verify price and provider identity before running scans, avoid custom ACP_BASE_URL unless you fully trust it, and fix or isolate the missing dependencies before running the scan command.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/list-offerings.ts:55
Finding

ACP API Credential Can Be Redirected to an Arbitrary Network Endpoint

Content
View full analysis
{ const resp = await fetch(`${baseUrl}/acp/agents?query=${encodeURIComponent(query)}`, { headers: { "x-api-key": apiKey, "Content-Type": "application/json", }, }); ``` ```ts const apiKey = process.env.ACP_API_KEY; if (!apiKey) { console.error("Error: ACP_API_KEY environment variable is not set."); console.error("Get your key from the Virtuals ACP dashboard."); process.exit(1); } const baseUrl = (process.env.ACP_BASE_URL ?? "https://claw-api.virtuals.io").replace(/\/$/, ""); ``` From `scripts/scan-wallet-acp.ts`: ```ts function buildClient(apiKey: string, baseUrl: string): AxiosInstance { return axios.create({ baseURL: baseUrl, headers: { "x-api-key": apiKey }, timeout: 15_000, }); } ``` ```ts const apiKey = options.apiKey ?? process.env.ACP_API_KEY; if (!apiKey) { throw new Error( "ACP_API_KEY environment variable is not set. " + "Get your key at https://claw-api.virtuals.io" ); } const baseUrl = options.baseUrl ?? process.env.ACP_BASE_URL ?? DEFAULT_BASE_URL; const agentWallet = options.agentWallet ?? process.env.ACP_AGENT_WALLET; const offeringName = options.offeringName ?? process.env.JANUS_OFFERING_NAME ?? null; const client = buildClient(apiKey, baseUrl); ``` ### Technical Analysis Both scripts attach the sensitive `ACP_API_KEY` to requests sent through a caller-controlled base URL. Neither implementation parses the URL nor enforces HTTPS, an approved hostname, an allowed port, or a trusted endpoint list. Support for a custom ACP deployment may be legitimate, but a ...[truncated 2213 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/scan-wallet-acp.ts:28
Finding

Runtime Dependencies Are Undeclared and Absent from the Lockfile

Content
View full analysis
Remediation
View remediation
", "dotenv": "" }, "devDependencies": { "@types/node": "^22.0.0", "tsx": "^4.19.2", "typescript": "^5.7.2" } ``` Pin reviewed versions according to the project's dependency-update policy. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/scan-wallet-acp.ts:215
Finding

Paid Offering Is Automatically Selected from Mutable Marketplace Ordering

Content
View full analysis
o.name.toLowerCase() === offeringName.toLowerCase() ); if (!offering) { const names = offerings.map((o) => `"${o.name}"`).join(", "); throw new Error( `Offering "${offeringName}" not found. Available: ${names}` ); } } else { // Default: use the first available offering offering = offerings[0]; } return { agent: janusAgent, offering }; ``` The selected offering is then used to create a job: ```ts const jobId = await createScanJob( client, agent.walletAddress, offering.name, walletAddress, agentWallet ); ``` ### Technical Analysis When neither `options.offeringName` nor `JANUS_OFFERING_NAME` is supplied, the code purchases `offerings[0]`. Marketplace ordering is remote and mutable. The code does not enforce an expected offering name, supported currency, maximum price, or explicit confirmation before creating the job. The implementation requires an exact case-insensitive agent name, which reduces simple search-result spoofing, but a name is not necessarily a stable cryptographic identity. The code does not pin a documented provider ID or wallet address. It also trusts the remote `price` and `priceType` for display without using either value as a policy constraint. Consequently, a marketplace account change, API compromise, custom malicious ACP endpoint, or benign reordering can cause the script to purchase a different or more expensive service than intended. ### Attack Path 1. The user invokes the scan command without `--offering` and has not set `JANUS_OFFERING_NAME`. 2. The ACP endpoint returns an exact-name `x402janus` profile whose first offering is expensive, unintended, or attacker-controlled. ...[truncated 1137 chars]
Remediation
View remediation
maxPrice) { throw new Error(`Offering price exceeds the configured limit.`); } ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises an ACP buyer workflow: purchase a wallet security scan from x402janus, create the job, pay for it, wait for completion, and return results. The supplied code does none of that. It only reads marketplace data by calling the ACP agents search endpoint, selecting the x402janus profile, and printing available offerings, pricing, SLA, descriptions, and requirements. This is a materially different primary purpose: listing offerings rather than buying or running scans. While both involve the ACP marketplace and x402janus, the implemented behavior lacks the core declared capabilities of job creation, payment, execution tracking, and result retrieval.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 56)May include surrounding context.

md
ACP_API_KEY=$KEY npx tsx scripts/list-offerings.ts --json

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 65)May include surrounding context.

md
ACP_API_KEY=$KEY npx tsx scripts/scan-wallet-acp.ts 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 68)May include surrounding context.

md
ACP_API_KEY=$KEY npx tsx scripts/scan-wallet-acp.ts 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 71)May include surrounding context.

md
ACP_API_KEY=$KEY npx tsx scripts/scan-wallet-acp.ts 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 74)May include surrounding context.

md
ACP_API_KEY=$KEY npx tsx scripts/scan-wallet-acp.ts 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 77)May include surrounding context.

md
ACP_API_KEY=$KEY npx tsx scripts/scan-wallet-acp.ts 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares required binaries and environment variables and clearly instructs users to run networked scripts, but it does not declare an explicit tool scope such as permissions or allowed-tools. That weakens sandboxing and review because an agent may grant broader env and network access than users expect, increasing the chance of credential exposure or unintended outbound calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description mentions paying with $VIRTUAL tokens, but it does not prominently warn that invoking the purchase workflow may create paid marketplace jobs and spend user funds. In an agent setting, insufficient spend disclosure can cause unintended financial actions, especially if another system auto-selects skills based on terse descriptions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using 'npx tsx' without pinning a version allows execution of whatever package version resolves at runtime, which can change over time or be replaced by a malicious upstream release. In a skill that handles API keys and makes marketplace/network calls, this creates a supply-chain execution path with access to sensitive credentials and the ability to trigger paid actions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using 'npx tsx' without pinning a version allows execution of whatever package version resolves at runtime, which can change over time or be replaced by a malicious upstream release. In a skill that handles API keys and makes marketplace/network calls, this creates a supply-chain execution path with access to sensitive credentials and the ability to trigger paid actions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using 'npx tsx' without pinning a version allows execution of whatever package version resolves at runtime, which can change over time or be replaced by a malicious upstream release. In a skill that handles API keys and makes marketplace/network calls, this creates a supply-chain execution path with access to sensitive credentials and the ability to trigger paid actions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using 'npx tsx' without pinning a version allows execution of whatever package version resolves at runtime, which can change over time or be replaced by a malicious upstream release. In a skill that handles API keys and makes marketplace/network calls, this creates a supply-chain execution path with access to sensitive credentials and the ability to trigger paid actions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using 'npx tsx' without pinning a version allows execution of whatever package version resolves at runtime, which can change over time or be replaced by a malicious upstream release. In a skill that handles API keys and makes marketplace/network calls, this creates a supply-chain execution path with access to sensitive credentials and the ability to trigger paid actions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using 'npx tsx' without pinning a version allows execution of whatever package version resolves at runtime, which can change over time or be replaced by a malicious upstream release. In a skill that handles API keys and makes marketplace/network calls, this creates a supply-chain execution path with access to sensitive credentials and the ability to trigger paid actions.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/list-offerings.ts:186

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/scan-wallet-acp.ts:390