T09 · Insecure Skill Coding Practices
- Location
references/http-api.md:119- Finding
Guardian signatures are not cryptographically bound to requested actions and lack enforced replay protection
- Content
View full analysis
Vulnerability Details
File Location:
references/http-api.md, lines 119–141 and 1078–1086
Vulnerability Type: Authorization replay and signature-context confusion
Risk Level: HighVulnerable documentation excerpt:
markdown - **Signature fields are always**: `signature`, `message`, **`signerAddress`**. - The server verifies `verifyMessage({ address: signerAddress, message, signature })` and then checks the signer is a **guardian** of the empire: - `signerAddress` must equal `empires.owner` **or** be included in `empires.co_emperors` for the target empire. - **Message format:** for leaderboard creates the backend **does not enforce a specific template**; it only verifies the signature against the provided `message`. **Recommended canonical message template (agent-side):** Use a consistent, human-readable message to make signatures auditable and easy to debug. Suggested format: ```text Empire Builder — Create Leaderboard type: <leaderboard_path_suffix> empireId: <tokenAddress> name: <name> timestamp: <ISO-8601> nonce: <random-uuid>Notes:
leaderboard_path_suffix: e.g.csvLeaderboards,tokenHoldersLeaderboards,farcasterChannelLeaderboards- Include
timestamp+nonceto reduce replay risk and make logs unambiguous (server currently does not enforce these, but they help operators).
text The general signing guidance further states: ```markdown ### What is `message`? - Unless an endpoint explicitly enforces an exact template (currently **only** `deploy-empire-tokenless`), `message` can be any plain text. - Recommended pattern (to prevent replay confusion): include endpoint + empire id + a short nonce/timestamp, e.g. ```text Empire Builder: create leaderboard for <empire_id> at 2026-04-30T00:00:00Ztext ### Technical Analysis The server reportedly verifies only that the supplied EIP-191 signature matches the in ...[truncated 3069 chars]- Remediation
View remediation
Remediation Suggestions
- Define a versioned, endpoint-specific authorization schema for every signed operation.
- Reconstruct the signed payload server-side from normalized request fields rather than trusting a caller-supplied free-form
message. - Bind every signature to:
- Application name and version.
- Exact endpoint and HTTP method.
- Empire ID and vault address.
- Chain ID where applicable.
- Every security-sensitive request parameter.
- Signer address.
- Issued-at and expiration timestamps.
- A cryptographically random, single-use nonce.
- Store consumed nonces atomically and reject replayed, expired, future-dated, or incorrectly scoped authorizations.
- Prefer EIP-712 typed structured data over arbitrary EIP-191 text so wallets can display the exact action and parameters being authorized.
- Use distinct domain separators and action types for leaderboard creation, booster changes, staking activation, deployment, and distribution preparation.
- Invalidate old arbitrary-message authorization behavior after a migration period; do not silently continue accepting legacy signatures.
- Redact signatures, API keys, and signed messages from logs and telemetry.
- Add tests proving that changing any protected field, endpoint, empire ID, chain ID, timestamp, or nonce invalidates authorization.
