feat(plugins): add realms-proposal-firewall, a read-only SPL Governance proposal analyzer#124
Closed
Lusitaniae wants to merge 3 commits into
Closed
Conversation
Add `realms-proposal-firewall`, a read-only T0 tool plugin that deterministically inspects one SPL Governance V2 proposal for treasury outflows, authority changes, governance weakening, program upgrades, and unknown instructions. - Reads all accounts at `finalized`, pins later reads with `minContextSlot`, and re-reads proposal/transaction bytes before reporting; a detected change returns SNAPSHOT_RACE and INCOMPLETE. - Validates governance/realm/proposal relationships and derives every expected ProposalTransaction PDA, failing closed on count mismatch. - Decodes System, classic SPL Token, ATA, Upgradeable Loader, and SPL Governance config instructions. Unknown programs or tags force CRITICAL. - Operator-owned config carries RPC, allowlists, thresholds, and caps; the model may supply only `proposal_address`. - Proposal prose and metadata URLs are never read or fetched. - Manifest grants exactly `http_client` and `config_read`. Includes 99 tests across decoding, policy, RPC failure matrix, prompt injection, and a hashed BonkDAO BIP zeroclaw-labs#76 mainnet fixture regression. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The suite proved the tool escalates dangerous proposals but never asserted that an approved treasury payment stays quiet, which is the claim reviewers have the most reason to doubt. - `tests/benign.rs`: an approved-mint, approved-recipient payment inside the configured outflow ratio returns LOW with zero findings while still disclosing analyzed transaction and instruction counts; the same payment above `large_outflow_bps` produces exactly LARGE_TREASURY_OUTFLOW. - `examples/live_lookup.rs`: one live mainnet analysis without building a plugin-capable host. It drives the same pure core across the same `Transport` seam the component crosses with `wasi:http`, posting through `curl`, so it adds no dependency to the plugin. Operator config is read from `REALMS_*` environment variables; only the proposal address is positional. - `DEMO.md`: the recorded walkthrough, with the live lookup separated from the hashed BIP zeroclaw-labs#76 fixture. Verified against mainnet: BIP zeroclaw-labs#76 returns CRITICAL with all seven required findings from `tests/fixtures/bip76/expected.json` plus UNAPPROVED_MINT under empty mint policy.
The component now has a live run through the ZeroClaw wasmtime component host (master f0b92f1, plugins-wasm-cranelift) rather than only through this crate's own suite: real wasi:http egress, real config jail, real fuel limits. - Instantiates against the host's own wit/v0 with the declared name and schema. - BIP zeroclaw-labs#76 live mainnet lookup returns CRITICAL / complete in 1.28s, matching tests/fixtures/bip76/expected.json on every required finding. - A model-supplied `__config.rpc_url` aimed at an attacker endpoint does not cross the host boundary; the plugin fails closed on the missing rpc_url.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This pull request adds one tool plugin. It adds 29 files. All the files are in plugins/realms-proposal-firewall/. It does not change a shared file. It does not change wit/, registry.json, or a workflow.
for people who do not know Solana
A Solana DAO keeps its money in accounts. The SPL Governance program controls these accounts. The members of the DAO vote on proposals.
A proposal is not a document. Each proposal contains transactions. The chain executes these transactions automatically after the vote passes and a delay ends. Thus a vote gives permission to execute code.
The title and the description of a proposal are free text. The instructions of the proposal are bytes. No rule makes the text and the bytes agree. Only the bytes execute. Thus a proposal with the title "Q3 contributor budget" can contain an instruction
that moves all the money.
To read the bytes manually, you must know these items:
Function of the plugin
The tool has the name realms_proposal_firewall. It has one argument: proposal_address. The plugin reads the proposal and its transactions at finalized commitment. Then it decodes them. Then it makes a report in JSON format.
The report shows these effects:
The plugin is read-only. It cannot sign, vote, or send a transaction.
The plugin makes the report only from decoded account bytes. It does not copy the proposal title, the description link, or the realm name into the report. It makes each link in this format: explorer.solana.com/address/.
The plugin fails safe. It gives the result CRITICAL or INCOMPLETE in these conditions: