Skip to content

[security] Beacon Atlas: legacy unauth endpoints bypass the hardened relay controls (XSS + impersonation + reputation forgery) #862

@Scottcjn

Description

@Scottcjn

Adversarial red-team of atlas/beacon_chat.py (3,715-line relay/registry, port 8071). The newer signed endpoints (/relay/ping, /relay/heartbeat/seo, /relay/identity/rotate) are well-hardened (Ed25519 + nonce-replay + agent_id↔pubkey binding), but legacy sibling endpoints writing the same relay_agents table were never retrofitted, so the strong controls are sidestepped.

Critical

  • C1 — Stored XSS on crawlable profile/directory pages (_agent_profile_html, served at /beacon/agent/<id> + /beacon/directory). Agent-controlled name/seo_description/seo_url/model_id/capabilities/preferred_city/offers/needs/topics are interpolated raw (no html.escape anywhere). Reachable anonymously via H1 → arbitrary JS on rustchain.org/beacon/*. (Fix in progress — output escaping PR.)

High

  • H1 — /relay/heartbeat (~1150-1179) auto-registers an unknown agent_id with NO signature and returns a valid relay_token (pubkey defaults to secrets.token_hex). Impersonation + token issuance + Sybil + the XSS delivery vector. Fix: require the same Ed25519 + derived-ID proof as /relay/ping, or remove the auto-register branch.
  • H2 — /relay/register (~1026-1042) verifies the signature only if signature: → unauthenticated identity binding/squatting; ON CONFLICT DO UPDATE lets an unsigned re-register overwrite an existing agent. Fix: signature mandatory.
  • H3 — /beacon/join (~1781-1843) takes agent_id AND pubkey independently (no derivation, no sig) = straight impersonation by design; currently throws (undefined ATLAS_DB_PATH, NameError 500). Fix: delete the route (superseded).
  • H4 — /contracts create + PATCH state (~849-941) unauthenticated → reputation forgery (mark a rival breached = −20) / self-deal inflation. The parallel /api/bounties/* routes ARE admin-gated; contracts were missed. Fix: require the initiating/party agent's relay_token.

Medium / Low

  • M1 get_real_ip() trusts client X-Real-IP/X-Forwarded-For → rate-limit/Sybil bypass + log spoofing (use ProxyFix w/ known hop).
  • M2 /relay/message stores envelopes without verifying the envelope sig/nonce (only the bearer token) → forged inbox messages (compounds H1).
  • M3 /api/dns unauth name→agent_id mapping → name hijack (used in contract targeting).
  • M4 /api/bounties/sync + boot_fetch_swarmhub unauth outbound-fetch + registry seeding (not SSRF — URLs fixed — but abuse/3rd-party write).
  • L1 identity.py from_mnemonic uses raw SHA256(phrase), not BIP39 PBKDF2. L2 relay_token has no absolute max-age.

No SQLi (parameterized), no eval/pickle/SSTI, no hardcoded secrets; admin routes fail-closed. The auth-hardening (H1/H2/H4) needs care — making signatures mandatory may break already-deployed unsigned agents, so coordinate a client+server rollout. C1 (output escaping) and H3 (delete broken route) are safe to fix immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions