{
  "type": "failure-mode",
  "name": "Unsound recursion and aggregation boundaries",
  "slug": "unsound-recursion-and-aggregation-boundaries",
  "section": {
    "id": "audit",
    "number": "03",
    "title": "Auditing a ZK protocol",
    "url": "https://zkpick.com/audit/"
  },
  "url": "https://zkpick.com/audit/failure-modes/unsound-recursion-and-aggregation-boundaries/",
  "markdown": "https://zkpick.com/md/audit/failure-modes/unsound-recursion-and-aggregation-boundaries.md",
  "detail": "Each layer is individually correct but their composition is not: a value committed in the inner proof is left unconstrained on an early-halt path, or the outer layer fails to check that the inner execution actually terminated. Publicly disclosed zkVM forgeries have come from exactly this pattern — two individually minor gaps at a recursion boundary combining into universal proof forgery.",
  "mitigation": "Treat every recursion and aggregation boundary as its own review target with its own written contract: what the inner proof guarantees, what the outer layer must independently re-check, and what happens on abnormal termination. Do not assume a boundary is covered because both sides were reviewed.",
  "relatedOptions": [],
  "updated": "2026-09-12",
  "version": "1.3",
  "canonical": "https://zkpick.com/audit/failure-modes/unsound-recursion-and-aggregation-boundaries/",
  "license": "https://creativecommons.org/licenses/by/4.0/",
  "authors": [
    "MarketComp"
  ]
}