Repository navigation
docs: methodology paper + adoption guide; em-dash pass across prose docs #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,74 @@ | ||||||
| # Adopting the standard: classify a validator-integrity finding | ||||||
|
|
||||||
| The Bundle v1 format and its family vocabulary are published so that adversarial research on validator | ||||||
| infrastructure becomes comparable: one on-disk shape, one labelling scheme, one evaluation methodology, | ||||||
| adoptable on your own data without coordination. This guide shows how to classify a node or client | ||||||
| integrity finding into the vocabulary. It is deliberately short. | ||||||
|
|
||||||
| ## The eleven families | ||||||
|
|
||||||
| | family | what it is | how to tell it apart | | ||||||
| |---|---|---| | ||||||
| | `response_amp` | a small request that returns disproportionately large response bytes | the cost lands on the server's outbound bandwidth | | ||||||
| | `compute_amp` | a small request that triggers disproportionate server-side CPU | parser pathologies, verification fallbacks, sync-over-async wedges | | ||||||
| | `memory_amp` | unbounded accumulation of retained state in process memory | it grows over time, not per request | | ||||||
| | `connection_exhaustion` | a per-connection or per-subscription resource that is never released on disconnect | the leak is the open handle, not the payload | | ||||||
| | `consensus_abuse` | validator-authenticated misbehaviour inside consensus | it presupposes validator key material | | ||||||
| | `gossip_abuse` | unauthenticated peer-to-peer or gossip abuse via public peer endpoints | state-sync floods, request amplification | | ||||||
| | `auth_bypass` | missing or broken authentication on a control, admin, or first-party API | the surface should have required credentials | | ||||||
| | `rate_limiter_bypass` | a defect in the rate-limiter's own logic | fail-open, burst-doubling, or key-collision, not a response-size issue | | ||||||
| | `service_misconfig` | exploitation of a misconfigured co-located daemon | Redis, Grafana, Prometheus, SSH, and similar | | ||||||
| | `reconnaissance` | discovery and target-mapping traffic itself | it is the prior stage, not the exploit | | ||||||
| | `benign` | no attack shape | it trains the "not malicious" boundary | | ||||||
|
|
||||||
| ## How to classify a finding | ||||||
|
|
||||||
| Work top to bottom. The first rule that matches gives the family. | ||||||
|
|
||||||
| 1. If it is only discovery or mapping traffic, with no exploitation, it is `reconnaissance`. | ||||||
| 2. If it requires validator key material to misbehave inside consensus, it is `consensus_abuse`. | ||||||
| 3. If it is unauthenticated abuse of a public peer-to-peer or gossip endpoint, it is `gossip_abuse`. | ||||||
| 4. If it defeats authentication on a surface that should need credentials, it is `auth_bypass`. | ||||||
| 5. If the bug is in the rate-limiter's own logic, it is `rate_limiter_bypass`. | ||||||
| 6. If it is a misconfigured co-located service being exploited, it is `service_misconfig`. | ||||||
| 7. Otherwise it is a resource-amplification shape. Pick by the resource that dominates: large response | ||||||
| bytes from a small request is `response_amp`; large CPU from a small request is `compute_amp`; | ||||||
| unbounded retained memory over time is `memory_amp`; a per-connection or per-subscription leak is | ||||||
| `connection_exhaustion`. | ||||||
| 8. If there is no attack shape, it is `benign`. | ||||||
|
|
||||||
| A finding can touch more than one mechanism. Label it by the dominant one, meaning the mechanism the | ||||||
| mitigation lives in. A response-size cap fixes `response_amp`; a fix in the limiter logic is | ||||||
| `rate_limiter_bypass`. | ||||||
|
|
||||||
| ## A worked example, using a public NullRabbit advisory | ||||||
|
|
||||||
| Take advisory NR-2026-001 (Solana). An unauthenticated `getMultipleAccounts` JSON-RPC call returns far | ||||||
| more response bytes than the request costs to send, so one caller can drive disproportionate server | ||||||
| egress. | ||||||
|
|
||||||
| Walk the rules in order. Is it discovery only? No. Does it need consensus key material? No. Is it | ||||||
| peer-to-peer or gossip? No, it is the public JSON-RPC surface. Does it defeat authentication? No. Is it a | ||||||
| rate-limiter logic bug? No. Is it a co-located service? No. It is a resource-amplification shape, and the | ||||||
| dominant cost is response bytes, so it is `response_amp`. | ||||||
|
|
||||||
| For contrast, the same advisory's `simulateTransaction` finding drives disproportionate CPU rather than | ||||||
| bytes, so it is `compute_amp`. Same endpoint family, different family label, because the dominant resource | ||||||
| differs. That is the discipline the vocabulary is meant to enforce. | ||||||
|
|
||||||
| ## Producing bundles | ||||||
|
|
||||||
| To contribute measurements, capture each run in the Bundle v1 shape: a manifest, a packet capture, and the | ||||||
| four time-series modalities (host, app, protocol, responses), as specified in this repository. The public | ||||||
| sample dataset provides ground-truth examples to validate your pipeline against. | ||||||
|
|
||||||
| ## Citing and contributing | ||||||
|
|
||||||
| Cite the format using the `CITATION.cff` file in this repository. The format is MIT-licensed, so you can | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The repository does not currently contain a
Suggested change
|
||||||
| adopt it on your own infrastructure and publish results citing it. To propose a new family or refine a | ||||||
| definition, open an issue. The vocabulary is versioned and evolves by proposal, not by decree. | ||||||
|
|
||||||
| ## Scope | ||||||
|
|
||||||
| This vocabulary is for node and client software findings only. On-chain contract, protocol, and | ||||||
| DeFi-economic findings use a separate vocabulary and are out of scope here. | ||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # How the Validator Integrity Index is built | ||
|
|
||
| *A companion to the Bundle v1 format specification and the NullRabbit disclosure record.* | ||
|
|
||
| NullRabbit Labs measures one thing: the probability that a given blockchain validator or node client | ||
| commits a slashable fault or is remotely exploitable. This note explains how the underlying finding | ||
| record is built, and just as importantly, what the index does and does not yet claim. A rating layer is | ||
| either trusted or it is nothing, so the method and its honest limits are the product. | ||
|
|
||
| ## 1. Canonicalise, don't count | ||
|
|
||
| Adversarial research surfaces the same underlying weakness many times: across chains, across ports, and | ||
| across client implementations. Counting each surfacing as a separate finding inflates a number without | ||
| adding information. Instead, one written rule collapses repeat surfacings of the same root weakness into a | ||
| single canonical record, keyed to the specific client and component. The index therefore measures | ||
| distinct, real weaknesses rather than research volume. | ||
|
|
||
| ## 2. Provenance: ours, or a reproduction of someone else's public disclosure | ||
|
|
||
| Every record is marked as one of two kinds. The first is original, meaning a weakness NullRabbit | ||
| discovered or first measured. The second is public-replication, meaning a faithful reproduction of an | ||
| already-public disclosure such as a CVE, a GHSA advisory, or a named third-party audit. The distinction is | ||
| explicit, so that a re-statement of public work is never mistaken for a novel finding, and so the line | ||
| between what is disclosure-gated and what is freely publishable is never in doubt. | ||
|
|
||
| ## 3. One vocabulary for every finding | ||
|
|
||
| Every weakness is classified into one of eleven chain-agnostic families defined by the Bundle v1 format: | ||
| response amplification, compute amplification, memory amplification, connection exhaustion, consensus | ||
| abuse, gossip abuse, authentication bypass, rate-limiter bypass, service misconfiguration, reconnaissance, | ||
| and a benign class. The vocabulary is defined by mechanism, not by chain. A finding in a Solana RPC path | ||
| and a structurally identical finding in a Cosmos RPC path receive the same family label. That is what | ||
| makes cross-client comparison meaningful, and what lets a finding reported by an outside team drop into | ||
| the same scheme. The [adoption guide](adoption-guide.md) shows how to classify a finding. | ||
|
|
||
| ## 4. The disclosure record, including the rejections | ||
|
|
||
| For every disclosed finding, NullRabbit records what was sent to the vendor and what the vendor actually | ||
| said back. That includes the disclosures that were ignored, dismissed, or declined, and the findings | ||
| NullRabbit itself later retracted. This record is published deliberately. Showing where vendors | ||
| disagreed, where they went silent, and where we were wrong is precisely what makes the rest of the record | ||
| credible. | ||
|
|
||
| ## 5. What the index does not claim | ||
|
|
||
| Honesty about limits is part of the method, not a footnote. | ||
|
|
||
| First, the index is procedural, not yet empirical. Today its credibility rests on a clean, documented | ||
| method and an honest disclosure record, not on a large body of vendor-confirmed, externally-credited | ||
| validations. Those accrue over time as disclosures are acknowledged. Until then, the per-client ratings | ||
| are not presented as externally proven. | ||
|
|
||
| Second, there is no cross-chain generalisation claim. The research behind the index does not yet reliably | ||
| generalise a detector trained on one chain to an unseen chain. That limitation is reported plainly, and | ||
| in-distribution results are never presented as cross-chain ones. | ||
|
|
||
| Third, self-graded severity is a liability, not an asset. Where a severity is our own assessment rather | ||
| than a vendor's, it is treated as provisional and calibrated against the disclosed evidence. | ||
|
|
||
| ## 6. Scope | ||
|
|
||
| The index covers node and client software only: the daemon a validator runs, spanning consensus, RPC, | ||
| peer-to-peer, and co-located services. On-chain contract, protocol, and DeFi-economic findings are a | ||
| separate measurement with a separate vocabulary, and they are deliberately not folded in. | ||
|
|
||
| ## Where the standard lives | ||
|
|
||
| The Bundle v1 format and the family vocabulary are published under the MIT license in this repository. The | ||
| format is designed to be adopted on third-party data without coordination. See the | ||
| [adoption guide](adoption-guide.md). |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The phrasing "large response bytes" and "large CPU" is slightly awkward. Rephrasing these to refer to "large response size" and "high CPU consumption" would improve the grammatical flow and clarity of the classification rules.