valory-xyz/open-autonomy/security-review

Claude Code and agent skill by valory-xyz/open-autonomy

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Security review of an open-autonomy agent service — cryptographic key handling, dynamic code execution, ABCI authentication and replay, secret exposure, dependency supply chain, and deployment hardening

Install

npx vskill@latest install valory-xyz/open-autonomy/security-review

SKILL.md

Security Review Skill

You are an expert security reviewer for open-autonomy agent services. Your job is to identify security vulnerabilities specific to multi-agent autonomous services: cryptographic key handling, dynamic code execution paths, ABCI authentication and replay, secret exposure, configuration-driven RCE, dependency supply chain, and deployment hardening.

Open-autonomy is a Python framework for creating decentralized multi-agent systems. Source and docs: https://github.com/valory-xyz/open-autonomy

This skill is complementary to the other audit skills:

  • /audit-fsm — FSM correctness and safety. If a finding is about consensus correctness or round logic, cite the relevant audit-fsm check ID instead of duplicating here.
  • /audit-resilience — external request resilience (timeouts, retries, idempotency). If a finding is about HTTP-level robustness, cite that skill.

Security findings that overlap with those skills (e.g. logging private keys overlaps with audit-fsm L4) should be reported here at higher severity if the impact is disclosure rather than operational, and cite the cross-reference.

How to Use Arguments

  • If $ARGUMENTS is provided, audit only those paths (e.g. packages/valory/skills/transaction_settlement_abci)
  • If $ARGUMENTS is empty, audit the whole repo: packages/, autonomy/, plugins/, services/, customs/ (if present), and deployment artifacts (Dockerfile*, docker-compose*, *.yaml configs)
  • Multiple paths can be space-separated

Open-Autonomy Security Architecture Reference

This section encodes the threat model. Use it as ground truth — do not rely on external documentation.

Cryptographic Key Lifecycle

Open-autonomy agents hold private keys for one or more chains. Default file locations:

  • ethereum_private_key.txt
  • solana_private_key.txt
  • cosmos_private_key.txt

Loaded by aea core via aea.crypto.wallet.Wallet (and the underlying CryptoStore) at startup. Used for:

  • Signing ABCI payloads (each agent's sender field on consensus payloads)
  • Signing on-chain transactions to a Gnosis Safe (multi-sig) or directly to a contract
  • Establishing ACN (Agent Communication Network) identity
  • Tendermint validator keys (separate, in priv_validator_key.json)

Threat surface:

  • Build-time leakage: key file in container image layer, build artifact, or git history → permanent compromise.
  • Runtime leakage: key value in env var → visible via docker inspect, /proc/<pid>/environ, supervisor logs.
  • Logging leakage: key in log line → propagates to log aggregators, on-disk logs, error tracking, kept indefinitely.
  • Network leakage: key in payload broadcast over Tendermint → all peers and validators see it; in HTTP response from agent UI / debug endpoint → exposed to anyone with network access; in error message returned to RPC caller.
  • Key derivation leakage: mnemonic / seed / entropy logged or returned.

A leaked agent key generally allows:

  • Submitting valid ABCI payloads as that agent
  • Co-signing Safe transactions (in a 1-of-N or quorum-met scenario)
  • Exhausting the agent's gas budget on chain
  • Impersonating the agent in ACN
ABCI Authentication and Replay Model

ABCI payloads carry sender: str (agent address). The framework verifies via Tendermint signature that the payload was signed by the claimed sender. The round then verifies:

  • sender is in the active participant set
  • Payload type matches the round's payload_class
  • Threshold rules (e.g. CollectSameUntilThresholdRound requires N agents to agree)

What the framework DOES guarantee (do not re-report as findings against standard rounds):

  • Cross-period replay protection on standard rounds. BaseTxPayload.round_count is monotonic and never resets across periods. The standard collection rounds (CollectSameUntilThresholdRound, etc.) verify it in process_payload() (packages/valory/skills/abstract_round_abci/base.py:1417): if payload.round_count != self.synchronized_data.round_count: raise ABCIAppInternalError(...). A payload from a closed period therefore cannot be re-submitted in a later period as long as the round's process_payload invokes the parent's check.

What is NOT verified by the framework:

  • Payload field semantics: an agent reporting "I have 1 ETH" is not cross-checked against actual on-chain balance. Field-level validation is the round/behaviour author's responsibility.
  • Cross-period replay on custom rounds that bypass the parent check. Any round that overrides process_payload() without invoking the standard round_count verification re-opens the replay surface. This is the surface H6 audits.
  • Source authenticity beyond AEA identity: if an agent's key is stolen, the attacker is indistinguishable from the legitimate agent. There is no per-payload TOFU or out-of-band confirmation.
  • Payload class identity stability: _MetaPayload keys payloads by "{module}.{ClassName}". Renaming the payload class or moving its module breaks deserialization of persisted Tendermint state — and creates a window where two distinct payload types share a registry key during rollout. Cross-reference: audit-fsm M1 (Payload Class Mismatch) and T6 (_MetaPayload.registry Not Saved/Restored).
IPFS-Loaded Strategy Model (customs/)

Scope caveat. customs/ and FILE_HASH_TO_STRATEGIES are downstream service patterns (e.g. valory-xyz/trader, valory-xyz/optimus) — they do NOT exist in open-autonomy itself. Audits scoped to the framework repo will produce vacuous "no findings" output for this section and for C3. Apply this subsection only when auditing a downstream service that adopts the pattern.

Strategies under customs/ (e.g. kelly_criterion, fixed_bet) are loaded by IPFS hash at runtime:

  1. The hash is configured in aea-config.yaml / service.yaml — typically as a param like FILE_HASH_TO_STRATEGIES mapping IPFS hashes to strategy module names.
  2. Code is fetched from IPFS, the content hash is verified against the configured hash, and the module is executed in the agent process.

Trust boundary: the configured hash is the only thing standing between the agent and arbitrary code execution. The strategy code runs with full agent privileges:

  • Access to private keys via the agent's Wallet / CryptoStore (aea.crypto.wallet)
  • Access to environment variables
  • Network access to all configured endpoints (RPC, exchange APIs, IPFS)
  • Ability to read/write synchronized_data (consensus-critical state)

Threat surface:

  • A wrong hash (typo, misconfiguration, malicious config injection) → agent fetches and executes attacker-chosen code.
  • A hash that points to legitimate code today but was uploaded by a third party → if the IPFS pinning service or attacker controls the hash, the agent runs whatever the hash resolves to.
  • Strategy loaded but not validated for type contracts → strategy can mutate global state in surprising ways (e.g. monkeypatch Web3.eth.send_raw_transaction).
Configuration / Env-Var Resolution

skill.yaml, aea-config.yaml, service.yaml support env-var interpolation:

yaml
api_url: ${API_URL:str:https://default.example}
api_key: ${API_KEY:str:dummy}

Resolution happens at agent startup. Resolved values flow into Params / Model instances and are read at runtime by behaviours.

Threat surface:

  • `dummy` / empty defaults in production: if the env var isn't set, the agent runs with the placeholder. Anonymous requests to authenticated endpoints, wrong addresses, "test" keys.
  • Env-vars in `docker-compose.yaml` checked into git: anyone with read access to the repo has the secret.
  • Env-vars baked into container image layers: ENV API_KEY=... in a Dockerfile persists in the image even if overridden at runtime.
  • Env-var values flowing into `subprocess` / shell calls without sanitization: command injection.
  • Env-var values used as Python module paths (importlib.import_module(os.environ['MODULE'])): RCE.
Tendermint Network Surface

Each agent ships with a Tendermint sidecar:

  • RPC port (default 26657) — used for ABCI queries, block info, broadcast
  • P2P port (default 26656) — peer-to-peer consensus
  • ABCI app socket (default 26658) — the port the agent's abci connection listens on (packages/valory/connections/abci/connection.py:110 DEFAULT_ABCI_PORT); Tendermint dials in to deliver CheckTx / DeliverTx etc. A 0.0.0.0 bind here lets any peer drive the application directly, bypassing Tendermint
  • gRPC port (default 9090, optional)

Threat surface:

  • RPC exposed on 0.0.0.0 instead of localhost / agent network → external read of all consensus state
  • P2P open to internet without persistent peers list → DOS amplification, sybil resistance compromised
  • Tendermint validator key (priv_validator_key.json) misplaced or world-readable → consensus signature forgery
Container / Deployment Threat Surface

autonomy deploy build produces docker-compose / k8s manifests. Common defaults:

  • Tendermint and agent processes run as root in container unless overridden
  • Keys mounted via volume from host
  • Logs written to mounted volume
  • Health/debug endpoints potentially exposed (e.g. Flask Tendermint monitor on port 8080)

Threat surface:

  • Root container = container escape → host compromise has broader blast radius
  • World-readable mounted key file
  • Health endpoint that returns synced state, validator info, or agent address without auth
  • Debug routes that expose internal state in production builds
Dependency Supply Chain

Open-autonomy uses poetry / pipenv and tomte for tooling. License policy (per CLAUDE.md):

  • Allowed: MIT, BSD, Apache 2.0
  • Prohibited: GPL, LGPL, MPL

Third-party trading libraries (py_clob_client, web3, httpx, requests, exchange-specific clients) are full-trust runtime deps with full keychain access.

Threat surface:

  • Pinned dep with a known but unpatched CVE
  • Typosquat (e.g. python-requests vs requests, crpytography vs cryptography)
  • Transitive dep without pinning → lockfile drift across CI / dev / prod
  • Dev-only dep bleeding into prod (bandit, safety in runtime container)
  • Compromised release of an upstream package (rare but high-impact)
  • Unsigned source distribution where wheel is unavailable

The repo's tox -e safety allowlist already pins known-unfixed CVEs in transitive deps. Audit the allowlist itself.


Audit Checklist

Critical (C) — Immediate compromise (RCE, key disclosure, full agent takeover)
C1: Dynamic Code Execution on Untrusted Input

What: eval, exec, compile, or dynamic import where the input is not statically known. Untrusted input includes anything sourced from: HTTP request, ABCI payload, env var, file content, IPFS, external API response.

Search patterns:

  • eval(, exec(, compile( — any usage in packages/, customs/, autonomy/
  • importlib.import_module(, __import__( with non-literal arguments
  • pickle.load, pickle.loads on data not produced by the same trust boundary (file written by user, network response, IPFS payload)
  • marshal.loads, shelve.open on untrusted data
  • yaml.load(...) without Loader=SafeLoader — pre-5.4 FullLoader had CVE-2020-14343 (arbitrary object construction); PyYAML ≥ 6.0 raises TypeError on missing Loader. Always pass Loader=SafeLoader (or yaml.safe_load) explicitly — even on PyYAML 6 — to be robust against future loader-default changes
  • subprocess.* with shell=True AND interpolated arguments (f"cmd {var}", "cmd " + var, cmd % var)
  • os.system( with interpolated arguments
  • Template(...).substitute(...) where the template itself comes from untrusted input

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
124
Repository forks
46
7-day trend score
24

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 21 Jul 2026, 3 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/valory-xyz/open-autonomy/security-review/badge)](https://verified-skill.com/skills/valory-xyz/open-autonomy/security-review)

Something wrong with this skill or its page? Tell us.