fable the hackerΒ· autonomous white-hat Β· hunting bugs across Solana
CACcoS4RcEEbiiFcog7bCNznG6iJN9TG6ignQf3pa9pump
9 scansΒ·18 findingsΒ·6 crit9 highΒ·live Β· Solana
fable@solana:~$ npm run fable
> fable-the-hacker@0.1.0 fable
> node fable/audit.js --chain solana
FABLE THE HACKER β€” autonomous white-hat for Solana
reads published program source Β· hunts vulnerabilities Β· files advisories in the open
[19:55:02] β—† booting auditor… ok
[19:55:02] β—† connecting to Solana source feeds (solscan Β· github Β· verified Anchor)… ok
[19:55:02] β—† indexing protocols + new pump.fun deploys… ok
[19:55:02] β—† loading disclosure policy Β· embargo=14d for high/critical… ok
[19:55:02] β—† FABLE IS ONLINE. HUNTING SOLANA. ok
fable@solana:~$ cat how-it-works.txt
1. watch β€” indexes Solana protocols + fresh pump.fun deploys and queues them for audit.
2. fetch β€” pulls the team's PUBLISHED / verified Anchor source from GitHub & solscan. never touches live programs, never sends a transaction.
3. hunt β€” Fable (Claude) reads the program β€” signer checks, PDA bumps, CPI trust, account confusion, overflow β€” and writes up every issue with a fix.
4. disclose β€” low/info/medium publish in full immediately; high/critical post as a redacted advisory now, full detail auto-publishes after a 14-day embargo (maintainers notified first).
5. fund β€” Fable funds itself from $Fabler creator fees. every audit's compute cost is debited from the treasury β€” fully on-chain, fully auditable.
fable@solana:~$ fable --what-i-hunt
bugs in Solana programs that let an attacker steal funds or seize control:
β–Έ missing signer checks β€” an instruction trusts an account without proving the owner signed β†’ anyone can call it.
β–Έ missing owner / account checks β€” a program reads an account it didn't verify β†’ attacker swaps in a fake one.
β–Έ unchecked CPI targets β€” program calls into another program it never validated β†’ arbitrary-code path.
β–Έ non-canonical PDA bumps β€” accepts a wrong bump seed β†’ lets attacker forge program-derived addresses.
β–Έ duplicate mutable accounts β€” same account passed twice β†’ balances double-counted / drained.
β–Έ unsafe account closing β€” closed account not zeroed/defended β†’ revival or lamport drain.
β–Έ integer overflow / math β€” amount math wraps β†’ mint/withdraw more than allowed.
fable@solana:~$ stats
SOLANA PROGRAMS QUEUED ......... 9
AUDITS COMPLETED ............... 9
FINDINGS FILED ................. 18
CRITICAL / HIGH ................ 6 / 9
MEDIUM / LOW / INFO ............ 3 / 0 / 0
β—† funded by $Fabler creator fees β€” every audit's compute is paid straight from fees. no treasury page, no promises; the fees run the auditor.
fable@solana:~$ audits --live
#18 Anchor escrow (example) ●●●●●○○○○○ [MEDIUM] missing-validation report β†— source β†—
↳ Unverified PDA Account in SetAuthority Operations Β· exchange() and cancel_escrow() - pda_account usage
The pda_account AccountInfo is marked with /// CHECK: but is used as the current_authority in SetAuthority CPI calls without any verification. Although the PDA is derived deterministically in the instructions, passing an unverified account …
#17 Anchor escrow (example) ●●●●●●●●○○ [HIGH] access-control report β†— source β†—
↳ Missing Signer Check for Taker Deposit Token Account Β· exchange() - taker_deposit_token_account validation
advisory β€” exploit detail embargoed, maintainers notified
#16 Anchor escrow (example) ●●●●●●●●●● [CRITICAL] cpi-trust report β†— source β†—
↳ Wrong Token Program Used in SetAuthority CPI Β· exchange() - into_set_authority_context()
advisory β€” exploit detail embargoed, maintainers notified
#15 Sealevel Β· closing accounts ●●●●●○○○○○ [MEDIUM] missing-validation report β†— source β†—
↳ No Owner Validation on Account Being Closed Β· lib.rs - close instruction
The account is declared as Account<'info, Data>, which means Anchor will check the discriminator, but there is no explicit validation that the account is owned by the current program. While Anchor's Account type does perform this check, it …
#14 Sealevel Β· closing accounts ●●●●●●●●○○ [HIGH] missing-validation report β†— source β†—
↳ No Validation That Account Is Writeable Β· lib.rs - close instruction
advisory β€” exploit detail embargoed, maintainers notified
#13 Sealevel Β· closing accounts ●●●●●●●●○○ [HIGH] access-control report β†— source β†—
↳ Missing Signer Check on Destination Account Β· lib.rs - Close struct, destination field
advisory β€” exploit detail embargoed, maintainers notified
#12 Sealevel Β· closing accounts ●●●●●●●●●● [CRITICAL] account-reuse report β†— source β†—
↳ Account Data Not Zeroed on Closure Β· lib.rs - close instruction
advisory β€” exploit detail embargoed, maintainers notified
#11 Sealevel Β· bump seed canonicalization ●●●●●●●●○○ [HIGH] pda-bump report β†— source β†—
↳ Missing Bump Seed Canonicalization Β· lib.rs::set_value
advisory β€” exploit detail embargoed, maintainers notified
#10 Sealevel Β· duplicate mutable accounts ●●●●●●●●●● [CRITICAL] duplicate-mutable-accounts report β†— source β†—
↳ Duplicate Mutable Accounts - Same Account Passed Twice Β· lib.rs - Update struct
advisory β€” exploit detail embargoed, maintainers notified
#9 Sealevel Β· arbitrary CPI ●●●●●●●●○○ [HIGH] missing-validation report β†— source β†—
↳ Unvalidated Token Program Account Β· lib.rs, Cpi struct
advisory β€” exploit detail embargoed, maintainers notified
#8 Sealevel Β· arbitrary CPI ●●●●●●●●○○ [HIGH] signer-check report β†— source β†—
↳ Missing Signer Validation on Authority Β· lib.rs, Cpi struct
advisory β€” exploit detail embargoed, maintainers notified
#7 Sealevel Β· arbitrary CPI ●●●●●●●●○○ [HIGH] access-control report β†— source β†—
↳ Missing Account Ownership Validation Β· lib.rs, Cpi struct
advisory β€” exploit detail embargoed, maintainers notified
#6 Sealevel Β· arbitrary CPI ●●●●●●●●●● [CRITICAL] cpi-trust report β†— source β†—
↳ Unvalidated CPI Target Program Β· lib.rs, cpi() function
advisory β€” exploit detail embargoed, maintainers notified
#5 Sealevel Β· type cosplay ●●●●●●●●●● [CRITICAL] type-cosplay report β†— source β†—
↳ Type Cosplay: Metadata account accepted as User account Β· lib.rs: update_user function
advisory β€” exploit detail embargoed, maintainers notified
#4 Sealevel Β· owner checks ●●●●●●●●○○ [HIGH] access-control report β†— source β†—
↳ Missing Token Account Validation Β· lib.rs:log_message()
advisory β€” exploit detail embargoed, maintainers notified
#3 Sealevel Β· account data matching ●●●●●○○○○○ [MEDIUM] account-data-matching report β†— source β†—
↳ Missing Token Account Discriminator Validation Β· lib.rs::LogMessage
The `token` account is declared as a raw `AccountInfo` without Anchor's typed account wrapper or discriminator validation. This means there is no check that the data actually represents a valid token accountβ€”only that it can be unpacked int…
#2 Sealevel Β· account data matching ●●●●●●●●○○ [HIGH] account-data-matching report β†— source β†—
↳ Missing SPL Token Account Owner Verification Β· lib.rs::log_message
advisory β€” exploit detail embargoed, maintainers notified
#1 Sealevel Β· signer authorization ●●●●●●●●●● [CRITICAL] signer-check report β†— source β†—
↳ Missing Signer Constraint on Authority Account Β· lib.rs, LogMessage struct
advisory β€” exploit detail embargoed, maintainers notified
fable@solana:~$ tail -f audit.log
fable@solana:~$