solana-foundation / solana-foundation/program-examples
allow-block-list-token: InitConfig lets any signer claim the list authority, and nothing can change it afterwards
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 543
- Avg merge
- 21h 7m
- Merged PRs (30d)
- 14
Description
Problem
init_config requires only that the payer is a signer, and then records that payer as the list authority:
pinocchio/program/src/instructions/config.rs:28-30— the sole precondition ispayer.is_signer().pinocchio/program/src/instructions/config.rs:38—write_config(&mut config.try_borrow_mut()?, payer.address(), bump)?;
Nothing ties the caller to the deployer or to any expected key. The Anchor flavour is the same: anchor/programs/abl-token/src/instructions/init_config.rs:7 (pub payer: Signer<'info>, unconstrained) and :23 (Config { authority: self.payer.key(), .. }).
No instruction changes the authority afterwards. The full instruction sets are pinocchio/program/src/processor.rs:16-22 and anchor/programs/abl-token/src/lib.rs:23-54; the config account is written only by init_config, and nothing closes or resets it (the only close is remove_wallet on ab_wallet, config.rs:125).
The port already documents the behaviour (config.rs:15): "Whoever calls this first becomes the authority, matching the Anchor version." So this is a faithful port of a shared design choice, not a regression introduced by the Pinocchio version — raising it because the pattern is now repeated across two merged examples and looks unintentional rather than chosen.
Why it matters (weighted honestly)
The authority's powers are narrow: init_wallet (config.rs:76) and remove_wallet (config.rs:110) are the only gated instructions. It cannot change a mint's mode — Token-2022's metadata update authority gates that, and change_mode carries no config check in either flavour (pinocchio/program/src/instructions/mint.rs:291, anchor/programs/abl-token/src/instructions/change_mode.rs:19-32) — and it cannot attach the hook. This is list control, not fund or mint takeover.
But it is list control for the whole deployment. The config is one PDA per program, and README.md:10 describes the list as usable by several mints. Whoever claims it can:
- block any wallet in every mode —
decide.rs:33-35, checked before the mode match; - un-block a blocked wallet in
Blockmode —decide.rs:41, which defeats the example's headline purpose; - add their own addresses in
Allowmode —decide.rs:39; - take the rent of existing records —
config.rs:122-124.
The UI then shows the real operator "UNAUTHORIZED: Only the config authority can modify the wallet list".
Reachability, stated plainly: there is no window in the repo's own documented flows. The documented run is a local validator (README.md:55, scripts/start.sh, Anchor.toml cluster = "localnet"), and the LiteSVM test uses a freshly generated program id (pinocchio/tests/test.ts:112). Neither committed program id is deployed on devnet. The exposure is a reader who follows README.md:35 ("make sure to replace your program ID") onto a public cluster and only later clicks "Create Config" — the gap is however long that takes, and the attacker needs no knowledge of the deployer's key and no timing tricks.
It is also recoverable from outside the program: a plain solana program deploy leaves the deployer the upgrade authority, so a fix can be shipped. There is no fix available from inside the program.
Proposed fix
In both flavours:
- Take the intended authority as an instruction parameter that must sign, rather than deriving it from the rent payer — accounts
[authority (signer), payer (signer, writable), config, system_program], writingauthorityfromauthorityrather thanpayer. - Add a
change_authorityinstruction gated by the existing check (check_authority,config.rs:47; Anchor'shas_one = authority), so the list can be handed over without a program upgrade.
Plus two tests: a second init_config fails, and a stranger's init_config cannot claim the config.
Anchor flavour
Same flaw, same shape. The related block-list/pinocchio example does the same thing (block-list/pinocchio/program/src/instructions/init.rs:29-31, :77), so a fix here would be the first instance of the pattern in this family rather than a copy of an existing one.
Happy to send a PR for both flavours if that's the direction you'd like — flagging as an issue first per the CONTRIBUTING note that substantial changes should confirm the approach before the diff.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with pinocchio/program/src/instructions/config.rs and anchor/programs/abl-token/src/instructions/init_config.rs, then trace the instruction lists in pinocchio/program/src/processor.rs and anchor/programs/abl-token/src/lib.rs. Run the existing tests in pinocchio/tests/test.ts and add coverage for repeated initialization and an unauthorized claimant. Done means both flavours enforce the intended authority and support the requested authority handoff.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript
- Domain
- authorization, blockchain, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100