Skip to content

Security: DendraNetwork/dendra-network

Security

SECURITY.md

Security Policy

Status: public research testnet, dendra-testnet. Dendra is experimental software. Testnet DNDR is never sold, Final Testnet Season rewards count as points that convert one for one — each testnet DNDR the season paid becomes one mainnet DNDR, credited in the mainnet genesis to the address that received it, at most 1 500 mainnet DNDR in total — and the chain can be reset. Do not put real value at risk.

What the public endpoint runs. The chain is dendra-testnet, started from a fresh genesis. The previous chain, dendra, was abandoned without a snapshot: no balance, registration, job or history was carried over, and nothing on this chain is promised to survive a future reset — a reset erases balances; the published rankings of the Final Testnet Season are archived before any reset. The network's public endpoints are testnet-api.dendranetwork.com and testnet-proof.dendranetwork.com (the site, dendranetwork.com, publishes the season's rules and rankings); no other host serves the chain.

dendra-testnet launched from a genesis with a single validator, run by the project on one host, which at launch alone orders and finalises every block. A validator set in which one validator holds a third or more of the voting power cannot survive losing that validator: if that validator stops, the chain stops; at launch the network is neither decentralized nor fault-tolerant (ADR-046). Read the current set with curl -s http://testnet-api.dendranetwork.com:26657/validators rather than trusting this page. The genesis sets committee_min_vrf_contributors to 1, and while it is 1, one validator's VRF output carrying at least two thirds of the committing power is enough to seed a draw, so at launch the project's validator alone produces the randomness of every work assignment and audit draw: draws are as fair as that operator is honest, until independent validators join and a governance vote raises the floor. A work assignment or a sampled audit draw runs only on a block whose VRF seed clears both bars — latest_contributors at or above committee_min_vrf_contributors, and contributor_power_bps at or above two thirds of the commit (decentralized_seed.go::MinVrfContributorPowerBps) — which dendrad query jobs committee-seed-health -o json prints side by side (a field missing from that JSON is zero: the chain omits zero values). On a block without such a seed those draws are deferred, never taken on a seed the proposer could choose. The re-adjudication jury of a dispute is the exception: without such a seed it is drawn from the hash of the block that opens the dispute (redo_committee.go::anchorRedoCommittee), which that block's proposer composes.

The rule that gates a verdict. An audit's jury is drawn from the miners of the job's frozen pool that are eligible and present — availability proved in the current or previous window, or registration in one of them (presence.go::minerPresentAt) — excluding the miner under audit, and a verdict needs at least audit_min_quorum drawn jurors to vote. audit_sample_bps sets the base share of settled jobs drawn for re-audit (audit_sampling.go::effectiveAuditBps adds the probation and fee-adaptive terms). Read both with dendrad query jobs params -o json or /dendra/jobs/v1/params rather than trusting a figure on this page; the other queries that decide are in the README.

What happens to a fee. Under a full hold (hold_bps = 10000, the genesis setting) the miner's share and the protocol's cut are retained at settlement. A job the draw does not select is released at finality. A selected job is paid on an upheld verdict; on a conviction the miner is slashed and the client refunded; and if no jury concludes within audit_unwind_blocks, the fee and the cut return to the client. An audit deferred for want of a seed unwinds the same way, and a job that is never served returns its escrow to the client after job_expiry.go::jobExpiryBlocks (a job whose miner cannot be drawn yet, for want of a seed that clears both bars, waits for one first). Because a stranded audit unwinds to the client, a job may open with fewer than audit_min_quorum + 1 present eligible miners when the chain runs in optimistic mode with audit_unwind_blocks above zero and a full hold (pool_freeze.go::enoughEligibleMinersToVerify); an audited job whose drawn jury does not reach audit_min_quorum votes within audit_unwind_blocks ends in that refund.

A report about the verification path is therefore a report about the code: which side of a floor the network stands on is a reading, shown by the queries above, and does not need reporting. A refund to the client after audit_unwind_blocks is the designed outcome, as is the release at finality of a job the draw did not select. A way to make an audit conclude without its drawn jury, to draw a work committee or a sampled audit jury on a seed below either bar, to pay a miner for a selected job without an upheld verdict, or to keep a retention held for ever — neither paid, refunded nor slashed — is very much in scope.

Reporting a vulnerability

Please report security issues privately. Do NOT open a public GitHub issue for a vulnerability.

  • Email: security@dendranetwork.com
  • Include: a description, reproduction steps, affected component (chain module, gateway, miner, relay, judge, Final Testnet Season service), and impact.
  • We aim to acknowledge within a few days. Coordinated disclosure is appreciated; we will credit reporters who wish to be credited.

Scope

In scope: the chain (chain/), the off-chain reference stack (services/) including the Final Testnet Season programme services (services/final_season_*.py), the deployment kits, desktop application and installer (deploy/, docker/).

Particularly valuable reports:

  • Ways to mint supply, or to destroy it outside the protocol's own burns (the invariant is zero mint: the supply starts at 10,000,000 DNDR and never rises).
  • Double-settlement, escrow imbalance, or paying a job twice.
  • Slashing an honest miner (false positive), or letting a prover escape a deserved slash.
  • Leaking plaintext on-chain, at the relay, or in logs: the chain should hold only a salted hash of the prompt, an embedding of the answer, verdicts and counters, and the relay only ciphertext. That the Dendra gateway, the serving miner and, for a job drawn for audit, its jurors read the prompt and the answer is documented in the README, not a finding.
  • Bypassing the regex floor — not by finding content it misses (it misses a great deal by construction, and this project makes no claim that illegal content is filtered out), but by defeating the mechanism itself: making a request skip the filter stage, or disabling it remotely.
  • Faucet drain / Sybil beyond the documented rate limits.
  • Final Testnet Season (rules, ADR-047): making the programme pay an identity its published rules would not pay — past the programme's caps, per day or per season, for a request refunded or not past its audit, for a verdict from a juror the chain did not draw or on a job the programme did not send, for an availability window the chain did not accept, or for presence on a day without a verified request; paying one reward twice; forging or replaying another identity's payout declaration; making a work answer enter the evidence, or a grade count, without the service's internal or grader token; or a published day that final_season_rank.py does not recompute from its evidence.

Out of scope

  • Testnet DNDR being never sold, and the chain being resettable: a reset erases balances by design; the season's published rankings are archived before any reset.
  • The project's validator, the launch genesis's only one, ordering every block and alone producing the randomness of every draw at launch (documented; lifted only by independent validators and a governance vote). A seed accepted below either bar — committee_min_vrf_contributors, or two thirds of the committing power — stays in scope.
  • A client refund after audit_unwind_blocks, and the release at finality of a job the draw did not select (both designed outcomes).
  • Limits the Final Testnet Season rules publish themselves (ADR-047, Consequences) — for instance that a presence proof proves an online operator key, not a model; that one card can serve the programme work of many identities; or that a stake split into many identities collects more presence rewards (one per identity with a verified request that day) and can hold more seats on a programme audit's jury (one per identity).
  • The consumer-GPU tier providing hardened deterrence, not a cryptographic guarantee (this is by design and documented).
  • Denial of service against a single self-hosted node.

Honest posture

We do not claim a cryptographic confidentiality guarantee on consumer GPUs, nor that a prompt is hidden from the gateway, the serving miner or a drawn jury, nor that Dendra outperforms frontier models, nor any fault tolerance on dendra-testnet (its launch configuration is stated at the top of this page). Reports premised on a guarantee we never made are not vulnerabilities — but reports showing we fail a guarantee we did make are very welcome.

There aren't any published security advisories