T09 · Insecure Skill Coding Practices
- Location
scripts/fortytwo_query.py:197- Finding
Unbounded Server-Controlled Payment Authorization
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This paid AI-query skill is mostly transparent about using a crypto wallet, but it signs payment authorizations with insufficient local limits and stores reusable paid-session state insecurely.
Review before installing. Use only a dedicated low-value wallet, understand that user questions are sent to Fortytwo, and do not run paid queries until the skill adds local spending limits, expected token and recipient validation, explicit payment confirmation, safer session storage, and pinned dependencies.
scripts/fortytwo_query.py:197Unbounded Server-Controlled Payment Authorization
scripts/fortytwo_query.py:127Predictable and Insecure Temporary Session File
SKILL.md:93Unpinned Third-Party Dependencies Loaded in Wallet-Signing Process
The declared purpose is question answering, but the documented behavior also includes wallet handling, chain connectivity, balance checks, and payment preflight logic. That mismatch is dangerous because users and orchestration layers may treat this as a normal AI-answering skill while it actually performs financially sensitive operations using a private key and external blockchain infrastructure.
The script reads a blockchain private key from the environment and uses it to sign payment authorizations for an external service. That creates real wallet-spending capability inside a tool presented as a query/inference skill, which materially increases risk if the service, challenge flow, or surrounding runtime is compromised or if users invoke it without understanding payment effects.
The skill instructs the agent to run local Python scripts that access environment variables, write session state to /tmp, and make external network calls, but it declares no explicit tool scope or permissions. This increases the chance of unintended execution with sensitive capabilities, especially because the workflow involves a blockchain private key and paid on-chain actions.
The skill recommends suggesting or using a paid external service for broad categories like 'contested topics,' 'niche expertise,' or whenever the user wants more depth. These triggers are subjective and expansive, which can pressure unnecessary invocation recommendations and increase the likelihood of users being steered into paid or externalized processing without a clear security or necessity basis.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
The script signs on-chain payments using evm_private_key environment variable. Never ask the user to paste the key into chat — it must be set via shell:
export evm_private_key="0x..."
The documentation instructs callers to pass a raw private_key into a helper that immediately derives an account and signs payment authorizations, but it does not include any explicit warning about secure key handling, storage, or the risk of exposing signing material to an agent/runtime. In the context of a paid x402 payment flow, this can normalize unsafe patterns where users or integrators provide hot-wallet secrets directly to tooling, increasing the chance of credential leakage and unauthorized token transfers.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
When using curl, add -N (no-buffer) to receive SSE chunks in real time:
curl -s -N --max-time 600 \
-H "Content-Type: application/json" \
-H "x-session-id: {uuid}" \
-H "x-idempotency-key: $(uuidgen)" \
The code performs blockchain RPC calls and constructs EIP-712 payment signatures even though the skill is described primarily as a multi-agent inference/query service. This mismatch is dangerous because it hides financially sensitive behavior behind an apparently informational tool, reducing informed consent and increasing the chance of unexpected signing or fund exposure.
Loading a private key from an environment variable without explicit user-facing warning or consent creates a hidden sensitive operation path. In agent or automation environments, operators may not realize that invoking this script can exercise wallet authority, which increases the chance of unintended payment authorization.
Automatic reuse of a previously saved session introduces statefulness that is not obvious from the interface and may cause requests to attach to an old paid conversation context. If another local process or user can modify the stored session value, they may redirect usage into an attacker-controlled or unintended session, affecting confidentiality, billing, or result integrity.
rpc_url = NETWORKS[args.network]["rpc"]
# Auto-load saved session unless --no-session
session_id = None if args.no_session else (args.session_id or load_session())
# Step 1: initialize
The script sends user queries and later payment-related data to remote endpoints without an upfront notice about external transmission. For a high-stakes inference tool, undisclosed export of prompts, session IDs, and payment authorization artifacts can expose sensitive business, personal, or operational information.
The skill metadata describes an inference service, but the bundled script performs blockchain wallet derivation and USDC balance checks on specific networks. This mismatch is security-relevant because it requests capabilities unrelated to the user-facing purpose, increasing the chance of over-privileged deployment, secret exposure, and user deception about what the skill actually needs to do.
The script requires a raw EVM private key from an environment variable even though the skill is presented as a multi-agent inference capability. Reading high-sensitivity wallet secrets expands the skill’s privilege boundary unnecessarily, and any compromise, logging mistake, downstream code change, or reuse of this environment could expose funds or enable unauthorized blockchain actions.
The natural-language instruction says to "ALWAYS use" the skill when certain phrases appear, which removes user choice over whether to invoke a paid external service. While not a language-selection issue, this is not enough for SQP-3 unless it reflects a policy violation of forced locale/language, so this file does not clearly meet the stated SQP-3 criteria.
The script stores session identifiers in a fixed file under /tmp, a shared and generally low-assurance location on multi-user systems. While a session ID is less sensitive than a private key, unauthorized reuse or tampering could let another local user hijack or interfere with paid sessions or correlate user activity.