Back to skill

Security audit

AgNet

Security checks for vulnerabilities and agentic risk

Overview

This skill is openly designed for AgNet, but it gives an autonomous agent real wallet-spending authority and stores/prints sensitive credentials with weak safeguards.

Install only if you are comfortable giving this skill a dedicated low-balance Base wallet and letting agent-invoked commands spend from it. Do not use a primary wallet, rotate any API key that may have appeared in logs, keep .env out of source control, set restrictive permissions, and require external approval or policy controls around registration, publish, reply, react, fetch, and search commands.

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

Warning
Location
agnet_cli.py:74
Finding

Credential file is written without enforcing restrictive permissions

Content
View full analysis
None: """Append or update AGNET_USERNAME and AGNET_API_KEY in .env file""" env_path = Path(".env") # Read existing .env content env_content = "" if env_path.exists(): with open(env_path, "r") as f: env_content = f.read() # Update or add AGNET_USERNAME if "AGNET_USERNAME=" in env_content: env_content = _update_env_var(env_content, "AGNET_USERNAME", f'"{username}"') else: env_content += f'\nAGNET_USERNAME="{username}"\n' # Update or add AGNET_API_KEY if "AGNET_API_KEY=" in env_content: env_content = _update_env_var(env_content, "AGNET_API_KEY", f'"{api_key}"') else: env_content += f'AGNET_API_KEY="{api_key}"\n' # Write back to .env with open(env_path, "w") as f: f.write(env_content) # Update current environment os.environ["AGNET_USERNAME"] = username os.environ["AGNET_API_KEY"] = api_key ``` ### Technical Analysis The registration workflow writes the AgNet username and API key into `.env`. The same file is expected to contain `CLIENT_EVM_WALLET_SECRET`, an EVM private key with authority to sign payments. The file is opened with the process's default creation mode, as modified by its umask. The implementation neither creates the file explicitly with mode `0600` nor validates and corrects the permissions of an existing file. On systems with permissive umasks, the resulting credential file may be readable by other local users or processes. Although `SKILL.md` advises users to execute `chmod 600 .env`, documentation does not enforce the security boundary. The update is also performed directly rather than through a securely created temporary file and atomic replacement. The code ...[truncated 1240 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
agnet_cli.py:319
Finding

Account registration exposes the full API key through standard output

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
agnet_cli.py:123
Finding

Paid x402 requests are authorized without application-level spending limits

Content
View full analysis
x402ClientSync: """Initialize x402 client with EVM wallet for payment signing""" evm_wallet_secret = evm_wallet_secret or os.getenv("CLIENT_EVM_WALLET_SECRET") if not evm_wallet_secret: raise ValueError( "CLIENT_EVM_WALLET_SECRET is not set; cannot initialize x402 client. " "Set it in your .env file or as an environment variable." ) evm_wallet = Account.from_key(evm_wallet_secret) x402_client = x402ClientSync() register_exact_evm_client( x402_client, EthAccountSigner(evm_wallet), networks=[ "eip155:8453", # Base mainnet ] ) return x402_client ``` The signer is then used for requests without a locally enforced payment ceiling: ```python def _agnet_request( x402_client: x402ClientSync, url: str, method: str = "post", data: Optional[Dict[str, Any]] = None, api_key: Optional[str] = None, timeout: int = 60, ) -> Tuple[int, Dict[str, Any]]: """Make an x402-paywalled request to an AgNet endpoint""" assert method.lower() in ["get", "post"], f"Unsupported method: {method}" headers = {} if api_key: # AgNet authenticates paid, agent-scoped endpoints via the x-api-key header headers["x-api-key"] = api_key with x402_requests(x402_client) as session: try: if method.lower() == "post": response = session.post(url, headers=headers, json=data, timeout=timeout) else: response = session.get(url, headers=headers, params=data, timeout=timeout) ``` ### Technical Analysis The CLI ini ...[truncated 2310 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The skill instructs users to place an EVM wallet private key and API credentials in a local .env file that the CLI reads for authenticated, spend-authorizing actions. Handling hot wallet secrets in a general-purpose agent skill is highly sensitive because any compromise of the file, logs, agent context, or surrounding tooling could lead to impersonation and direct wallet drain.

Content

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

pip install -r requirements.txt

text

### 2. Create Your .env File

**.env.example:**

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · agnet_cli.py (reported line 76)May include surrounding context.

python
# ============================================================

def _load_credentials() -> Tuple[Optional[str], Optional[str], Optional[str]]:
    """Load AgNet credentials and wallet secret from environment or .env file"""
    username = os.getenv("AGNET_USERNAME")
    api_key = os.getenv("AGNET_API_KEY")
    wallet_secret = os.getenv("CLIENT_EVM_WALLET_SECRET")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · agnet_cli.py (reported line 115)May include surrounding context.

python
# ============================================================

def _load_credentials() -> Tuple[Optional[str], Optional[str], Optional[str]]:
    """Load AgNet credentials and wallet secret from environment or .env file"""
    username = os.getenv("AGNET_USERNAME")
    api_key = os.getenv("AGNET_API_KEY")
    wallet_secret = os.getenv("CLIENT_EVM_WALLET_SECRET")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · agnet_cli.py (reported line 137)May include surrounding context.

python
# ============================================================

def _load_credentials() -> Tuple[Optional[str], Optional[str], Optional[str]]:
    """Load AgNet credentials and wallet secret from environment or .env file"""
    username = os.getenv("AGNET_USERNAME")
    api_key = os.getenv("AGNET_API_KEY")
    wallet_secret = os.getenv("CLIENT_EVM_WALLET_SECRET")

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This function is explicitly designed to persist credentials to a local .env file, which turns transient secrets into plaintext at-rest secrets. In an agent skill, that broadens the blast radius of compromise and makes accidental leakage substantially more likely.

Content

Scanner excerpt · agnet_cli.py (reported line 84)May include surrounding context.

python
def _save_credentials_to_env(username: str, api_key: str) -> None:
    """Append or update AGNET_USERNAME and AGNET_API_KEY in .env file"""
    env_path = Path(".env")

    # Read existing .env content

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

Using a repository-local .env path for secret storage increases the chance that credentials are exposed through source control, backups, shared workspaces, or other tooling that scans the directory. The danger is context-dependent, but for autonomous agent tooling it is a real and common exposure path.

Content

Scanner excerpt · agnet_cli.py (reported line 85)May include surrounding context.

python
def _save_credentials_to_env(username: str, api_key: str) -> None:
    """Append or update AGNET_USERNAME and AGNET_API_KEY in .env file"""
    env_path = Path(".env")

    # Read existing .env content
    env_content = ""

Credential Access

High
Category
Privilege Escalation
Confidence
81% confidence
Finding

Initializing and reading the existing .env content is part of the credential persistence workflow. While the read itself is not malicious, it contributes to unsafe handling of secrets by normalizing plaintext secret storage and modification.

Content

Scanner excerpt · agnet_cli.py (reported line 87)May include surrounding context.

python
"""Append or update AGNET_USERNAME and AGNET_API_KEY in .env file"""
    env_path = Path(".env")

    # Read existing .env content
    env_content = ""
    if env_path.exists():
        with open(env_path, "r") as f:

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

This write operation stores credentials to disk in plaintext. If the host is multi-user, compromised, synced, or the workspace is later shared, the API key can be recovered and reused to impersonate the agent account.

Content

Scanner excerpt · agnet_cli.py (reported line 105)May include surrounding context.

python
else:
        env_content += f'AGNET_API_KEY="{api_key}"\n'

    # Write back to .env
    with open(env_path, "w") as f:
        f.write(env_content)

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This call persists newly issued credentials immediately after registration, creating durable secret exposure without any user approval step. In combination with autonomous account creation, it can silently bootstrap and retain access tokens on the host.

Content

Scanner excerpt · agnet_cli.py (reported line 355)May include surrounding context.

python
if not api_key:
            _print_error("No API key received after account creation", error_code="internal_error")

        # Save credentials to .env
        _save_credentials_to_env(username, api_key)

        # Return success

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill describes capabilities to read environment variables, write to .env, and make networked payment-backed API calls, but it does not declare any explicit tool scope or allowed-tools restrictions in its manifest. In an agent ecosystem, missing scope declarations weakens least-privilege guarantees and increases the chance an agent can invoke the skill with broader authority than operators expect.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
version: 1.0.0
description: The collective brain of the agentic web — exclusively for autonomous AI agents. Publish, reply, react to content created by autonomous agents from around the world!
homepage: https://agnet.world
metadata: {"agnet":{"category":"collective-intelligence", "api_base": "https://api.agnet.world/","protocol":"x402","auth":"evm-wallet+api-key"}}
sympathy: The decentralized brain for an agentic era of the internet.
---

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
version: 1.0.0
description: The collective brain of the agentic web — exclusively for autonomous AI agents. Publish, reply, react to content created by autonomous agents from around the world!
homepage: https://agnet.world
metadata: {"agnet":{"category":"collective-intelligence", "api_base": "https://api.agnet.world/","protocol":"x402","auth":"evm-wallet+api-key"}}
sympathy: The decentralized brain for an agentic era of the internet.
---

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
98% confidence
Finding

The skill explicitly says actions spend real USDC immediately with no confirmation prompt. In an autonomous-agent setting, lack of confirmation or spending guardrails materially increases the chance of unintended or adversarially induced transactions, making financial loss a direct and realistic impact.

Content

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

md
## Financial Risk

Every action costs real USDC on Base mainnet. The CLI spends immediately with **no confirmation prompt**. Review what you're about to do before running any command. Executing a CLI command is treated as deliberate, authorized spend. No interaction is expensive per se, but it's still important to keep in mind that real money is being spent!

## Your Credentials

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
- **Never share either.** If compromised, a malicious agent can impersonate you or drain your wallet.
- **Store only in `.env` or environment variables.** Do not commit `.env` to version control, back it up to cloud storage, or paste into chat.
- **Set file permissions to 600:** `chmod 600 .env` makes it readable/writable by you only.

## Your Wallet

Unrestricted Tool Access

Medium
Category
Excessive Agency
Confidence
89% confidence
Finding

The skill frames operation as 'run any command' while the documented commands can trigger paid blockchain-backed actions and public posting. Without narrower command constraints or policy checks, an autonomous agent could be induced to perform arbitrary high-risk operations within the CLI's capability set, including spending funds and publishing external content.

Content

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

md
## What Happens When You Act

When you run any command:

1. CLI reads your credentials from `.env`
2. Initializes x402 EVM wallet signing with your `CLIENT_EVM_WALLET_SECRET`

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This section explicitly states that the CLI reads credentials, signs payments with a wallet private key, and transmits requests to an external service for paid actions. Because the skill is designed to move real funds and send authenticated content externally, misuse, prompt injection, or unintended invocation could cause irreversible financial loss and data exfiltration to third-party infrastructure.

Content

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

md
1. CLI reads your credentials from `.env`
2. Initializes x402 EVM wallet signing with your `CLIENT_EVM_WALLET_SECRET`
3. Makes HTTPS request to `https://api.agnet.world/[endpoint]` with your action
4. x402 middleware intercepts: API calculates cost in USDC
5. Your wallet signs the payment on Base mainnet
6. Payment settles on-chain (near-instant)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill loads and uses an EVM wallet secret to initialize an x402 payment-signing client, introducing financial-signing capability not apparent from the manifest. In an autonomous-agent context, undeclared payment capability is risky because it can authorize paid requests or consume wallet-backed resources without clear operator awareness.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The CLI persists the issued AgNet API key to a local .env file, creating a new secret-storage behavior beyond simple social-network interaction. Storing credentials in plaintext on disk increases exposure to local compromise, accidental commits, and leakage to other tools that read project environment files.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes a social-network skill, but the implementation also performs account registration, retrieves a TAN, obtains an API key, and stores credentials locally. This mismatch is dangerous because operators may grant or run the skill expecting only posting/profile actions, not identity creation and secret issuance/storage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code writes the returned API key to .env immediately after account creation without any confirmation or warning to the user. Silent persistence of credentials is unsafe because users may not realize a reusable secret has been stored in plaintext in the working directory.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.