Back to skill

Security audit

Agent Security Auditor

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed ERC-8004 audit tool, but it can fetch attacker-controlled URLs from the user's environment and overstates some security checks.

Review before installing or running against untrusted agents. Use an isolated environment with limited network reachability, avoid credential-bearing RPC URLs on the command line, and do not rely on this tool as proof that endpoints or reputation were verified until those checks are implemented or clearly marked as skipped.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/audit.js:300
Finding
Server-Side Request Forgery Through Attacker-Controlled Agent URI## Vulnerability Details **File Location**: `scripts/audit.js`, lines 300–329; request helper at lines 155–171 **Vulnerability Type**: Unrestricted server-side request forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```js async function fetchJson(url, timeout = 10000) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } catch (error) { clearTimeout(timeoutId); throw error; } } ``` ```js let agentURI; try { agentURI = await identityRegistry.tokenURI(agentId); report.metadata.agentURI = agentURI; console.log(` Agent URI: ${agentURI}`); } catch (error) { findings.push({ severity: SEVERITY.CRITICAL, title: 'Missing Agent URI', description: 'Could not retrieve agent URI from registry', recommendation: 'Contact agent owner to set agentURI' }); report.summary.critical++; console.log(` ${colors.red}✗ Error: ${error.message}${colors.reset}`); return report; } let registration; try { if (agentURI.startsWith('data:')) { const base64Data = agentURI.replace('data:application/json;base64,', ''); const jsonStr = Buffer.from(base64Data, 'base64').toString('utf-8'); registration = JSON.parse(jsonStr); } else { registration = await fetchJson(agentURI); } ``` ### Technical Analysis The agent owner controls the `tokenURI` returned by the on-chain registry. Every URI not beginning with `data:` is passed directly to the built-in `fetch` API. No validation is performed on: - The URI scheme. - The destination hostname. - The destination's resolved IPv4 or IPv6 addresses. - Lo ...[truncated 2131 chars]
Remediation
## Remediation Suggestions 1. Allow only explicitly supported URI schemes, such as `https:` and strictly validated `data:application/json;base64`. 2. Implement IPFS access through a configured trusted gateway rather than passing `ipfs:` URIs to generic `fetch`. 3. Resolve destination hostnames before connecting and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 4. Explicitly reject cloud metadata destinations, including link-local metadata addresses. 5. Disable automatic redirects or validate the scheme, hostname, and resolved address at every redirect. 6. Reject URLs containing embedded usernames or passwords. 7. Apply a strict response-size limit before parsing JSON. 8. Retain the timeout and add limits for redirect count and decompressed response size. 9. Consider routing metadata requests through an isolated egress proxy with no access to internal networks. 10. Validate the response content type and registration schema before adding it to the report.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/audit.js:198
Finding
Credential-Bearing RPC URL Disclosed Through Console Logging## Vulnerability Details **File Location**: `scripts/audit.js`, lines 75 and 198–220 **Vulnerability Type**: Sensitive information exposure through logging **Risk Level**: Medium ### Vulnerable Code ```js if (args[i] === '--rpc' && args[i + 1]) { options.rpc = args[i + 1]; i++; } ``` ```js console.log(`${colors.blue}=== ERC-8004 Agent Security Auditor ===${colors.reset}\n`); console.log(`Agent Address: ${agentAddress}`); console.log(`RPC Endpoint: ${options.rpc}`); console.log(`Chain ID: ${options.chainId}\n`); const findings = []; const report = { agentAddress, timestamp: new Date().toISOString(), chainId: options.chainId, identityRegistry: IDENTITY_REGISTRY_ADDRESS, metadata: {}, findings: [], summary: { critical: 0, high: 0, medium: 0, low: 0, info: 0 } }; try { const provider = new ethers.JsonRpcProvider(options.rpc); ``` ### Technical Analysis The script accepts an arbitrary RPC URL from the command line and prints the complete value to standard output. Hosted Ethereum RPC URLs commonly contain API keys in their path, query string, or URL user-information component. For example, provider URLs often use credential-bearing forms conceptually equivalent to: ```text https://provider.example/v3/API_KEY https://provider.example/rpc?apiKey=API_KEY ``` Printing the complete URL can expose the credential to CI output, centralized log collectors, terminal recording systems, support bundles, or users with access to captured logs. Connecting to a user-selected RPC service is necessary for the declared functionality. Logging the secret-bearing URL is not necessary and exceeds the minimum disclosure required to report connection status. ### Attack Path 1. A user invokes the script with a private provider URL through `--rpc`. 2. The command-line parser stores the complete URL in `options.rpc`. 3. The audit function prints the ...[truncated 936 chars]
Remediation
## Remediation Suggestions 1. Do not print the complete RPC URL. 2. Log only a sanitized origin or provider hostname. 3. Remove URL user information, query values, and sensitive path components before logging. 4. Use a dedicated redaction function that replaces likely credentials with `[REDACTED]`. 5. Support reading credential-bearing RPC URLs from a protected environment variable or secret manager. 6. Warn users that command-line arguments may also be visible in process listings and shell history. 7. Configure provider-side origin, IP, method, spending, and quota restrictions so accidental exposure has limited impact.

other

Warning
Location
scripts/audit.js:447
Finding
Advertised Endpoint Verification and Reputation Checks Are Not Implemented## Vulnerability Details **File Location**: `scripts/audit.js`, lines 187–188, 447–448, and 494–501 **Vulnerability Type**: Misleading security assurance caused by incomplete validation **Risk Level**: Medium ### Vulnerable Code ```js return { available: false, message: 'Reputation Registry address not configured - reputation check skipped' }; ``` ```js if (registration.registrations) { // Check if endpoint domain matches any verified registration // This is a simplified check - real verification would fetch .well-known/agent-registration.json unverifiedEndpoints++; } ``` ```js report.metadata.reputation = { note: 'Reputation Registry check requires separate deployment address' }; console.log(` ${colors.dim}Reputation check requires Reputation Registry deployment${colors.reset}`); ``` ### Technical Analysis The Skill documentation advertises endpoint verification, domain-control checks, reputation querying, and reputation summaries. The implementation does not perform those checks: - `queryReputationRegistry` always returns `available: false` and is not used to obtain reputation data. - HTTPS endpoint verification only increments a local `unverifiedEndpoints` counter. - The counter is not converted into a finding or included in the report. - The documented `/.well-known/agent-registration.json` proof is never retrieved or validated. - No cryptographic or on-chain relationship between an endpoint and the agent owner is established. This creates a security-assurance gap. A user may interpret a completed audit with few findings as evidence that the endpoint has been verified or has acceptable reputation, even though those controls were skipped. ### Attack Path 1. An attacker publishes an agent registration containing an HTTPS endpoint they do not control, or an endpoint with no domain-control proof. 2. The attacker advertises a supported trust model such as reputation withou ...[truncated 1046 chars]
Remediation
## Remediation Suggestions 1. Implement domain-control verification using the specified `/.well-known/agent-registration.json` mechanism. 2. Validate that the proof identifies the audited agent, registry, chain, and endpoint. 3. Define and configure authoritative Reputation Registry addresses per supported chain. 4. Invoke the reputation query and include count, score, decimals, filtering criteria, and registry address in the report. 5. Convert every skipped security control into an explicit report finding or a clearly visible `not_checked` status. 6. Include verification state for each endpoint, such as `verified`, `unverified`, `failed`, or `not_supported`. 7. Until implemented, revise `SKILL.md`, `registration.json`, and console output so they do not claim that verification or reputation analysis is performed. 8. Add automated tests confirming that an unverified endpoint cannot be reported as verified and that skipped checks are visible in the final report.
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 (7)

Ae1

High
Category
analysis-evasion
Content
node scripts/audit.js <agent-address> [options]
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/audit.js <agent-address> [options]
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/audit.js <agent-address> [options]
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/audit.js <agent-address> [options]
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

Low
Confidence
90% confidence
Finding
The skill explicitly performs external RPC queries and off-chain metadata fetches, but the description does not clearly warn users that agent addresses, queried endpoints, and related interaction data will be transmitted to third-party services. This is a genuine privacy/transparency issue because users may unknowingly expose sensitive investigation targets or operational metadata when running the audit.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"author": "",
  "license": "MIT",
  "dependencies": {
    "ethers": "^6.13.0"
  },
  "engines": {
    "node": ">=18.0.0"
Confidence
90% confidence
Finding
The dependency version is specified with a caret range (^6.13.0), which allows newer minor and patch releases to be installed. This can introduce supply-chain risk by pulling in unreviewed upstream changes or a compromised release, reducing build reproducibility for a security-auditing tool where deterministic behavior is especially important.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The manifest sets `"language": "en"`, which is a natural-language locale constraint. Under the policy rule, forcing a specific language without offering user choice or documenting a justified regional limitation is a language/locale policy concern.

Static analysis

No suspicious patterns detected.