Back to skill

Security audit

Agent Template

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for an autonomous Solana prediction-market agent, but its setup and default template can execute unverified code and place live wagers too easily.

Install only after reviewing the remote installer or using a local audited setup path. Use a separate minimally funded wallet, avoid valuable keys in .env, start in dry-run or modify the template so it cannot place bets by default, and add hard limits before enabling live wagering or redemption flows.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
README.md:40
Finding
Mutable Remote Script Is Downloaded and Executed Without Verification<![CDATA[ ## Vulnerability Details **File Location**: `README.md:40-43` **Vulnerability Type**: `T03: Remote Payload Retrieval and Execution` **Risk Level**: High ### Vulnerable Code ```bash **One-liner (curl):** ```bash curl -fsSL https://app.twzrd.xyz/raw/wzrd-trade.sh | bash ``` ``` ### Technical Analysis The documented quick-start procedure pipes a remotely downloaded script directly into `bash`. The script is not included in the audited project, pinned to an immutable version, or protected by a published checksum or cryptographic signature. Consequently, the code executed by users can differ from the code available at audit time. TLS protects the connection in transit but does not protect users if the remote application, hosting account, DNS configuration, or deployment pipeline is compromised. The use of `curl -fsSL` also suppresses normal output and follows redirects, while piping directly to `bash` prevents users from reviewing the effective payload before execution. Executing an installer is not inherently unnecessary for setup, but dynamically executing an unverified and mutable remote payload exceeds the minimum privileges required to install the four documented Python dependencies and run the local agent. ### Attack Path 1. An attacker compromises `app.twzrd.xyz`, its deployment infrastructure, DNS, or the endpoint serving `/raw/wzrd-trade.sh`. 2. The attacker replaces the installer or redirects the request to a malicious payload. 3. A user follows the README quick-start command. 4. `curl` retrieves the attacker-controlled content and sends it directly to `bash`. 5. The payload executes with all permissions of the invoking user. 6. The payload can inspect local files and environment variables, including wallet material configured for this project, modify the user account, or install additional malicious software. ### Impact Assessment The remote payload obtains arbitrary code execution with the privileges of the user running the command. Po ...[truncated 679 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `curl | bash` installation command. 2. Include the installer in the repository so it can be audited alongside the Skill. 3. Publish installers only through versioned, immutable releases. 4. Provide a detached cryptographic signature and SHA-256 checksum for each release. 5. Require users to download and verify the installer before execution, for example: ```bash curl -fSLO https://example.invalid/releases/v0.5.0/wzrd-trade.sh curl -fSLO https://example.invalid/releases/v0.5.0/SHA256SUMS sha256sum --check SHA256SUMS less wzrd-trade.sh bash wzrd-trade.sh ``` 6. Document manual installation as the preferred path. 7. Explicitly warn users never to run the installer as root. 8. Ensure the installer does not read or transmit wallet private keys and operates only within a dedicated virtual environment. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
example_agent.py:266
Finding
Default Agent Automatically Places Irreversible Wagers on Every Open Market<![CDATA[ ## Vulnerability Details **File Location**: `example_agent.py:266-325` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: High ### Vulnerable Code ```python def pick_outcome(market: dict) -> bool: """ TODO: implement your prediction logic here. Inputs available on each market dict: market["market_type"] — e.g. "stream_still_live", "stream_viewer_count_gt" market["implied_probability"] — fraction of stakes currently on YES (0.0–1.0) market["odds_yes"] — payout multiplier if YES wins market["odds_no"] — payout multiplier if NO wins market["yes_count"] — number of YES predictions market["no_count"] — number of NO predictions market["parameters"] — market-specific data (thresholds, session age, etc.) market["closes_at"] — ISO8601 close time Parimutuel payout: Lower implied_probability on your side = higher multiplier = better expected value if your edge on that side exceeds the market's implied probability. Return True for YES, False for NO. """ # Default: always YES — replace with your actual strategy return True def should_enter(market: dict) -> bool: """ TODO: implement your market filter here. Filter out markets you don't want to trade. Common filters: - market closes too soon (check market["closes_at"]) - market type not supported - already have a position (tracked in predicted set) - odds not favorable given your edge estimate Return True to enter, False to skip. """ # Default: accept all open markets — replace with your actual filter return market.get("status") == "open" # ── Main loop ───────────────────────────────────────────────────────────────── async def tick( client: WzrdClient, predicted: set[str], user_id: str, ) -> None: # Log current balance via /v1/agent/me (single call: balance + open ...[truncated 3577 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Fail closed by default: ```python def should_enter(market: dict) -> bool: return False ``` 2. Refuse to start live trading until the placeholder strategy has been explicitly replaced or a dedicated `WZRD_LIVE_TRADING=true` option is set. 3. Enable dry-run mode by default and log proposed wagers without submitting them. 4. Require explicit operator confirmation before switching from dry-run to live mode. 5. Implement cumulative controls: - Maximum stake per prediction. - Maximum total stake per session and per day. - Maximum number of open positions. - Minimum account-balance reserve. - Stop-loss and drawdown thresholds. 6. Restrict trading through allowlists for market type, creator, closing-time window, and acceptable odds. 7. Validate that the selected strategy returns a confidence score and require a configurable minimum confidence. 8. Display a prominent startup warning describing the automatic and irreversible nature of predictions. 9. Add tests proving that the default configuration cannot call `predict()`. 10. Consider a separate, minimally funded wallet or account for autonomous operation. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Security-Sensitive Dependencies Are Not Reproducibly Pinned<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-4` **Vulnerability Type**: `T08: Insecure Dependencies` **Risk Level**: Medium ### Vulnerable Code ```text aiohttp>=3.9 base58>=2.1 PyNaCl>=1.5 python-dotenv>=1.0 ``` ### Technical Analysis Every dependency is specified with only a minimum version and no upper bound, exact version, lockfile, or package hash. A future installation can therefore resolve to versions that did not exist when this project was reviewed. This does not prove that any currently named package is malicious. However, it creates an unsafe and non-reproducible supply-chain boundary in a process that loads a wallet signing key and communicates with a financial service. Package installation and import can execute package-controlled Python code, so an incompatible or compromised future release could access process memory, environment variables, or local files. ### Attack Path 1. A user follows the manual setup instructions and runs `pip install -r requirements.txt`. 2. The package resolver selects the latest versions satisfying the lower bounds. 3. A future compromised, malicious, or incompatible package release is selected because no reviewed upper or exact version is enforced. 4. Package installation hooks or imported package code execute in the user's environment. 5. When the agent starts, dependencies run in the same process that contains `WZRD_PRIVATE_KEY` and the derived signing key. 6. Malicious dependency code could read or exfiltrate wallet material, alter network requests, or manipulate prediction behavior. ### Impact Assessment Dependency code executes with the same operating-system privileges as the agent. If a selected dependency release is compromised, potential scope includes: - Reading the wallet private key from environment variables or process state. - Stealing JWTs or authentication signatures. - Modifying API destinations or request contents. - Manipulating prediction decisions and amounts. - R ...[truncated 269 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct and transitive dependency to a reviewed exact version. 2. Generate a lockfile using a tool such as `pip-tools`, Poetry, or uv. 3. Require package hashes during installation, for example with a hash-locked requirements file and: ```bash pip install --require-hashes -r requirements.lock ``` 4. Install dependencies in an isolated virtual environment under a non-privileged user. 5. Use an internal or controlled package mirror where appropriate. 6. Run automated dependency vulnerability and provenance checks in CI. 7. Review dependency updates before regenerating the lockfile. 8. Avoid exposing a valuable wallet key to the agent process; use a minimally funded key or an external signer with narrowly scoped authorization where supported. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (21)

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
Direct execution of a remote shell script is not necessary to explain or use a prediction-market agent template and introduces an unnecessary code-execution channel. In this skill's context, users are likely to run setup on machines that may contain wallet credentials, making arbitrary shell execution materially more dangerous.

External Script Fetching

High
Category
Supply Chain
Content
**One-liner (curl):**
```bash
curl -fsSL https://app.twzrd.xyz/raw/wzrd-trade.sh | bash
```

**Manual setup:**
Confidence
99% confidence
Finding
The command explicitly fetches a shell script from a remote origin and executes it locally. This is a classic software supply-chain risk because compromise of the remote content or delivery path yields immediate arbitrary code execution on user systems.

Chaining Abuse

High
Category
Tool Misuse
Content
**One-liner (curl):**
```bash
curl -fsSL https://app.twzrd.xyz/raw/wzrd-trade.sh | bash
```

**Manual setup:**
Confidence
99% confidence
Finding
The '| bash' construct turns downloaded data into executable commands without validation, creating a dangerous chaining pattern. In this skill's context, the same environment may later hold wallet credentials, so successful exploitation could lead to both host compromise and theft of trading keys or funds.

Credential Access

High
Category
Privilege Escalation
Content
git clone https://github.com/twzrd/twzrd-agent-template
cd twzrd-agent-template
pip install -r requirements.txt
cp .env.example .env
# Edit .env — set WZRD_PRIVATE_KEY to your Ed25519 keypair (base58, JSON array, or hex)
python example_agent.py
```
Confidence
77% confidence
Finding
The presence of .env usage alone is not inherently malicious, but here it is coupled with instructions to store a wallet private key in that file. That creates a real credential-exposure risk because the secret is highly sensitive and directly enables account control if leaked.

Credential Access

High
Category
Privilege Escalation
Content
cd twzrd-agent-template
pip install -r requirements.txt
cp .env.example .env
# Edit .env — set WZRD_PRIVATE_KEY to your Ed25519 keypair (base58, JSON array, or hex)
python example_agent.py
```
Confidence
77% confidence
Finding
This finding refers to the same setup block directing users to create and edit a .env file containing a private key. In the context of a financial agent, credential leakage could let an attacker authenticate as the agent, place trades, and redeem value tied to the wallet.

Credential Access

High
Category
Privilege Escalation
Content
Usage:
  pip install -r requirements.txt
  cp .env.example .env && $EDITOR .env
  python example_agent.py
"""
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Possible Typosquatting: 'PyNaCl' resembles popular package 'pyyaml'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The README instructs users to fetch and immediately execute a remote shell script from the internet. That pattern is dangerous because the fetched content can change at any time, is not pinned or integrity-checked, and would run with the user's local privileges, which is especially risky in a project that also asks users to handle wallet private keys.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Piping curl output straight to bash bypasses normal review and provides no warning about the trust boundary being crossed. If the hosting endpoint, CDN, DNS, or TLS termination were compromised, users could unknowingly execute attacker-controlled commands immediately.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The setup tells users to place a raw Ed25519 private key into a .env file without clear security guidance. Storing long-lived wallet secrets in plaintext environment files increases the risk of accidental disclosure through source control, shell history, backups, logs, or multi-user systems.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill exposes significant networked and wallet-adjacent functionality through an MCP server and authenticated trading/redeem flows, but it does not declare any explicit tool scope such as allowed-tools or permissions. In an agent environment, this weakens containment and informed consent because the runtime may permit broader network or environment access than users expect, increasing the chance of unintended external calls or sensitive context exposure.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
This skill promotes betting, staking-tier registration, swaps, and redemption/claim actions involving points, tokens, and potentially signed on-chain transactions, but it does not present a prominent warning about financial loss, irreversible submissions, or blockchain settlement risk. In an autonomous-agent context, missing risk disclosure is especially dangerous because an agent may treat market actions as routine API calls rather than high-impact financial operations.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README promotes autonomous trading and autonomous purchasing agents with direct financial and account-impact capabilities, but does not place clear, proximate warnings beside those entries about loss of funds, unintended trades, API/account misuse, or the need for human approval. In a catalog of AI skills and agents, this can normalize high-risk automation and encourage unsafe adoption by users who may treat listed resources as vetted or low-risk despite only a general disclaimer at the top.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The agent automatically places predictions using `client.predict(...)` in a continuous loop without any user confirmation, approval threshold, dry-run mode, or hard spending cap beyond the per-bet amount. In this skill’s context, predictions consume account points and can repeatedly execute over time, so a misconfigured strategy or hostile API/market conditions could drain balances or cause unintended trading activity.

Unpinned Dependencies

Low
Category
Supply Chain
Content
aiohttp>=3.9
base58>=2.1
PyNaCl>=1.5
python-dotenv>=1.0
Confidence
95% confidence
Finding
The dependency is specified with a minimum version only, which allows different environments to resolve to different aiohttp releases over time. This weakens build reproducibility and can unexpectedly introduce vulnerable or incompatible versions into a security-sensitive bot or market-facing service.

Unverifiable Dependency: aiohttp has 16 known advisory(ies) (CVE-2024-52303 (aiohttp has a memory leak when middleware is enabled when requesting a resource ); CVE-2026-54279 (aiohttp: Host-Only Cookies Become Domain Cookies After CookieJar Persistence); CVE-2026-34514 (AIOHTTP has CRLF injection through multipart part content type header constructi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding
aiohttp has multiple known advisories, and because no exact version is pinned, it is impossible to verify whether the deployed package is patched. Given this skill appears to support an internet-connected trading or prediction-market bot, an affected aiohttp version could expose the service to request-handling, cookie, or parsing flaws.

Unpinned Dependencies

Low
Category
Supply Chain
Content
aiohttp>=3.9
base58>=2.1
PyNaCl>=1.5
python-dotenv>=1.0
Confidence
94% confidence
Finding
Using base58 with only a lower bound permits unreviewed future versions to be installed, reducing reproducibility and supply-chain assurance. While not an immediate exploit by itself, it increases the chance of unexpected behavior or a compromised release being pulled into deployments.

Unpinned Dependencies

Low
Category
Supply Chain
Content
aiohttp>=3.9
base58>=2.1
PyNaCl>=1.5
python-dotenv>=1.0
Confidence
95% confidence
Finding
PyNaCl is a cryptographic dependency, so leaving it unpinned is more sensitive than a typical utility package because cryptographic behavior and bundled native components can change across versions. An unconstrained upper bound increases supply-chain and compatibility risk for software likely handling keys or signatures on Solana.

Unverifiable Dependency: PyNaCl has 2 known advisory(ies) (CVE-2025-69277 (libsodium has Incomplete List of Disallowed Inputs); CVE-2025-69277 (libsodium has Incomplete List of Disallowed Inputs)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
82% confidence
Finding
PyNaCl has reported advisories, and without version pinning there is no way to confirm whether the installed version includes fixes. Because this package is used for cryptographic operations, any underlying flaw could affect signature validation, key handling, or other security-critical logic in a blockchain-related application.

Unpinned Dependencies

Low
Category
Supply Chain
Content
aiohttp>=3.9
base58>=2.1
PyNaCl>=1.5
python-dotenv>=1.0
Confidence
94% confidence
Finding
python-dotenv with only a minimum version allows uncontrolled version drift, which can pull in releases with security regressions or breaking behavior. In an automation or bot context, environment loading often influences secrets and runtime configuration, so deterministic dependency resolution matters.

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding
python-dotenv has known advisories, and the unpinned requirement makes it unverifiable whether deployments are using a safe release. In services that load secrets and configuration from .env files, a vulnerable version could contribute to file overwrite or unsafe file-handling issues depending on application usage.