T09 · Insecure Skill Coding Practices
- 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
