Skip to content
DID.is
Trust

Security model

DID.is turns arbitrary identifiers, URLs and credentials from anonymous clients into network requests and cryptographic decisions. This page says how we keep those decisions correct, what protects the service, and what we do not claim.

Principles

Everything fetched is untrusted

DID documents, logs, status lists, agent cards and MCP servers are treated as attacker-controlled, including on well-known hosts.

Unknown is never a pass

If a mechanism is unsupported or a check cannot be completed, the result says INDETERMINATE or UNSUPPORTED. It never falls back to a guess.

Evidence, not scores

Each dimension is evaluated and reported on its own. Nothing is averaged into a number, and a real-world organisation is never inferred from a resolved document.

Verification cannot be bought

No plan, payment or listing changes a verdict or a claim. Directory listings require proof of control and opt-in.

Threats and mitigations

Each mitigation is covered by automated tests in the resolver.

ThreatExampleMitigation
Server-side request forgerydid:web:169.254.169.254, internal hostnames, DNS answers or redirects pointing inwardIP literals and localhost refused by syntax; every DNS answer must be public; the connection is pinned to the validated address; special-purpose IPv4/IPv6 ranges blocked; at most two redirects, each re-validated, never HTTPS → HTTP
DNS rebindingA second lookup returning a private addressValidated addresses are pinned for the connection; there is no second lookup
Resource exhaustionHuge or slow bodies, decompression bombs, unbounded logsStreaming size caps per document type, decompression cap, 4 s upstream timeout, bounded concurrency and fail-fast admission (503 with Retry-After)
Forged evidenceLinkage credentials from another DID, keys outside the document, fake did:webvh logsIssuer = subject = DID; keys taken only from the DID's own verification relationships; webvh SCID, hash chain and update-key proofs; strict id equality
Signature downgradealg: none, unknown crit, unsupported suites treated as validnone, crit and b64: false refused; unsupported suites reported as UNSUPPORTED; Data Integrity verified per cryptosuite
Revocation bypassUnreachable or forged status listsFail-closed: the status list credential must verify with the same issuer and matching purpose, and be unexpired
Delegation escalationWidened capabilities, broken links, cyclesSignatures by capabilityDelegation keys, proof-hash linkage, attenuation, time containment, acyclicity, depth ≤ 8, trusted roots
Tool poisoningMCP servers changing tools after reviewPer-tool fingerprints (RFC 8785), drift against previous observations; declared and heuristic side-effect classes shown separately
Identifier confusionDouble percent-decoding changing a DID between layersRaw-path forwarding; identifiers are decoded exactly once
Misleading presentationReading "resolved" as "trusted"Every dimension states what it proves and what it does not; verdicts list their limits

Controls

Network egress

  • HTTPS only; userinfo in URLs refused
  • All DNS answers must be public; connections pinned
  • Per-type body caps (1 MiB documents, 4 MiB webvh logs)
  • TLS chain, validity and hostname enforced in the handshake

Public API

  • Allowlisted routes and methods only; no admin routes
  • 512 KiB request bodies
  • Per-client token buckets; 429 with Retry-After
  • RFC 9457 problems with stable codes; no-store responses

Cryptography

  • Ed25519, ECDSA P-256 and secp256k1 with point validation
  • RFC 8785 canonicalisation for Data Integrity
  • No remote @context retrieval; offline context catalogue
  • Private JWK members rejected in did:jwk

Accounts and keys

  • API keys stored as hashes and shown once
  • Webhooks signed with HMAC-SHA256 over timestamp and raw body
  • Private resolutions bypass public history and shared cache
  • No IP address or user agent stored with sessions

Web

  • X-Frame-Options DENY, nosniff, strict referrer and permissions policies
  • Remote data rendered as text, never as HTML
  • No service secrets in the browser
  • No third-party trackers

Runtime

  • Resolver runs without published ports on an internal network
  • Non-root, read-only filesystem, all capabilities dropped
  • Encrypted off-host backups with a rollback point per release
  • Host and off-host health alerts

What remains

  • Split view on did:web: an origin can serve different documents to different resolvers. did:web has no defence; did:webvh witnesses mitigate it for witnessed versions.
  • Withheld did:webvh entries: a host can omit newer log entries. Witnesses and watchers reduce this risk but do not remove it.
  • TLS evidence relies on the public WebPKI root store.
  • MCP side-effect classes are heuristics and are labelled as such.
  • Webhook signing secrets must be recoverable to sign deliveries; they are stored server-side, not in a hardware key store.
  • No external penetration test or formal verification has been performed yet. We will publish one here when it exists.

Report a vulnerability

Email [email protected] with steps to reproduce. We acknowledge within 2 business days and will not pursue good-faith research that respects the acceptable use policy. Please do not test against other people's accounts or degrade the service.