Security at Animica
How to report a vulnerability, what the project defends against and what it does not, how the post-quantum algorithm set is governed, and what you can do to keep your own keys safe.
Reporting a vulnerability
Email security@animica.org. Do not open a public GitHub issue. Include the affected component and version or commit, reproduction steps or a proof of concept, your impact assessment, and how you would like to be credited (or that you prefer not to be). For sensitive reports, encrypt with the PGP key referenced from /.well-known/security.txt; the machine-readable record also lists the canonical contact and policy URLs and its own expiry date. English is preferred; Spanish is accepted.
| Step | Commitment |
|---|---|
| Acknowledgement | within 3 business days |
| Initial assessment and severity (CVSS v3.1) | within 7 days |
| Fix window | typically 30 to 90 days depending on severity |
| Embargo | may be requested while patches roll out |
| Credit | with your consent, in release notes |
These commitments come from docs/legal/SECURITY_POLICY.md. If you do not receive an
acknowledgement, re-send or use a second channel; the top-level SECURITY.md lists the
same address. We will keep you informed if a timeline has to change because of downstream
coordination.
Scope
In scope: all first-party software and services, including the node (core/,
consensus/, p2p/, rpc/, mempool/,
execution/, vm_py/, da/, proofs/,
randomness/, aicf/, l2/), the wallets (browser extension,
Flutter, Qt, web), the explorer, Studio, the SDKs, installers and update flows, and the hosted
surfaces under *.animica.org and *.animica.dev.
Out of scope, or handled outside coordinated timelines: third-party forks and sites we do not operate, social engineering of maintainers, physical attacks, volumetric DDoS that does not bypass rate limits, SPF/DMARC findings without a practical exploit, self-XSS, best-practice suggestions without a concrete vulnerability, and issues that only affect end-of-life or rooted environments. If you are unsure, ask at the same address before testing.
Safe harbour
Good-faith research that avoids privacy violations, service degradation and data exfiltration, respects rate limits and the law, and uses test networks and accounts where feasible is welcome. If you follow the policy we will not initiate legal action over your research and will work with you on remediation.
Severity guidance
| Severity | Examples |
|---|---|
| Critical | Key exfiltration, remote code execution, signature forgery, consensus safety breaks, reorgs beyond the stated bound |
| High | Transaction malleability with fund loss, VM sandbox escape, policy bypass enabling unauthorised state changes |
| Medium | Persistent DoS via an unauthenticated path, inaccurate economic accounting without loss, information disclosure aiding exploitation |
| Low | UI spoofing mitigated by confirmation, minor input validation without impact, documentation gaps |
Threat model in brief
The full model (docs/security/THREAT_MODEL.md) names the assets it protects:
consensus safety and fork-choice correctness, liveness, execution determinism, economic
accounting (fees, rewards, AICF payouts), key handling, and user safety against phishing and
secret leakage. It assumes an honest majority of work over time windows, treats the P2P network as
byzantine with Sybils expected, trusts verification logic and pinned root stores but not providers,
and keeps all secrets client-side (no server-side signing anywhere). It considers three adversary
classes, from opportunistic spammers through economically motivated cartels to nation-state
attackers capable of route hijacking and supply-chain compromise.
| Surface | Threats considered | Mitigations |
|---|---|---|
| Consensus and PoIES | Grinding on the u-draw, ψ over-weighting, cap bypass, nullifier reuse, retarget oscillation, shallow reorgs | Strict hash domains; per-proof, per-type and global caps; nullifier TTLs; EMA retarget with clamps; 100-block reorg bound since 75,000 |
| P2P | Sybil and eclipse, flooding, handshake downgrade, compression bombs | Kyber-768 + lattice-signed mutual handshake, AEAD sessions, peer scoring and rate limits, pinned checkpoints |
| Mempool and fees | Spam, replacement griefing, underpriced transaction kinds | Admission checks (chain id, signature, balance, fee floor, size), duplicate-id rejection |
| Execution and VM | Non-determinism, gas accounting bugs, reentrancy-like syscall patterns | Validated Python subset, static gas bound plus metering, no I/O or time, bounded integers |
| Wallets and SDKs | Phishing, blind signing, mnemonic theft, address-encoding confusion | Structured signing summaries, origin prompts, bech32m with scheme id in the payload, no server-side signing |
| RPC, explorer, website | CORS bypass, SSRF, artifact poisoning, XSS | POST-only RPC, rate limits, static site with no secrets, strict headers guidance in docs |
| Build and release | Dependency and registry compromise, signing-key misuse | Checksums on downloads, signed wallet builds, supply-chain notes in docs/security/SUPPLY_CHAIN.md |
Explicit non-goals: content moderation of user data or contract logic, privacy beyond what the
base protocol provides, and strong side-channel resistance on commodity hardware. On the last
point, SECURITY.md is candid that pure Python cannot be constant-time; the project
uses constant-time comparison helpers and normalised verification paths to mitigate local timing
channels, and relies on network jitter and rate limiting for remote ones.
Two honest residuals worth knowing. Header state roots are armed but not sealed by the reference miner, so header roots are not yet a guarantee you can rely on; validity comes from every node executing every block. And the useful-work verification rule runs in shadow mode on mainnet and does not force a miner to run a model; do not read "useful work" as an enforced property today.
Post-quantum algorithm policy
The canonical algorithm set and its lifecycle are defined in docs/pq/POLICY.md and
docs/governance/PQ_POLICY.md: a preferred lattice signature (Dilithium3 lineage,
standardised as ML-DSA-65 and the only scheme mainnet accepts since block 40,000), Kyber-768 for
the P2P handshake KEM, and a deprecation ladder of Active → Deprecating (at least 12 months) →
Sunset (hard reject), with the whole policy object hashed into an alg-policy Merkle root published
in chain parameters. Rotation cadence is semi-annual with a staging window and a grace period, and
emergency levers exist to disable a broken algorithm without halting the chain. SPHINCS+ appears in
the policy documents as a backup but is consensus-stranded on mainnet; it is not a usable
alternative today.
Key handling for users
- The mnemonic is the wallet. Write the 12 or 24 words down offline. Anyone with them has your ANM; nobody without them, including us, can recover it.
- Verify every address character by character. Mainnet accounts are 66 characters starting
anim1zqp; bech32m catches typos, not substitutions. Use an address book for recurring recipients. - Never blind-sign. The wallets show chain id, sender, recipient, amount, fee and gas limit for every signature; read them. Blind mode is for development only.
- Pin the chain id and the RPC URL. A malicious RPC can lie about state; cross-check large transfers on the explorer and use simulation (
mempool.simulateAdmission) before signing. - Install only from official sources and check the published SHA-256 checksums on Downloads. Connect only to dapps you trust; connecting is not the same as approving a spend.
- Separate roles. Use a different key for a mining payout address, an AICF worker and your savings.
- Ignore "support" on chat platforms. We run no Discord or Telegram. Official channels are this site, GitHub and @animicaorg.
Release integrity
Releases ship on PyPI as animica and as signed wallet and miner builds with published
checksums. docs/security/SUPPLY_CHAIN.md describes SBOM and attestation practice. One
gotcha the project documents for itself: the PyPI wheel builds from the working tree rather than
from git, so release engineering checks both git status and git ls-files
before publishing.
Sources
docs/legal/SECURITY_POLICY.md · SECURITY.md · docs/security/RESPONSIBLE_DISCLOSURE.md · docs/security/THREAT_MODEL.md · docs/pq/POLICY.md · docs/governance/PQ_POLICY.md · docs/wallets/SECURITY.md · consensus/finality.py · website/public/.well-known/security.txt