fix: 75 security issues in squads-multisig-cli — SolAudit Agent#175
Open
grkhmz23 wants to merge 1 commit intoSquads-Protocol:mainfrom
Open
fix: 75 security issues in squads-multisig-cli — SolAudit Agent#175grkhmz23 wants to merge 1 commit intoSquads-Protocol:mainfrom
grkhmz23 wants to merge 1 commit intoSquads-Protocol:mainfrom
Conversation
|
@grkhmz23 is attempting to deploy a commit to the squads Team on Vercel. A member of the Team first needs to authorize it. |
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.
Executive Summary
Automated security audit of squads-multisig-cli (
anchor) identified 1 critical and 74 high severity vulnerabilities across 56 instructions. This PR includes code fixes for 18 file(s) and 10 proof-of-concept test(s).Findings Summary
executable_transaction_message.rsbatch_add_transaction.rsbatch_create.rsbatch_execute_transaction.rsbatch_execute_transaction.rsconfig_transaction_create.rsconfig_transaction_execute.rsmultisig_add_spending_limit.rsmultisig_config.rsmultisig_remove_spending_limit.rsproposal_activate.rsproposal_create.rsproposal_vote.rsspending_limit_use.rstransaction_accounts_close.rstransaction_accounts_close.rstransaction_accounts_close.rstransaction_accounts_close.rstransaction_accounts_close.rstransaction_buffer_close.rstransaction_buffer_create.rstransaction_buffer_extend.rsvault_transaction_create.rsvault_transaction_execute.rsvault_transaction_execute.rsephemeral_signers.rsbatch_create.rsmultisig_create.rsprogram_config_init.rsproposal_create.rslib.rslib.rslib.rslib.rslib.rslib.rslib.rslib.rslib.rsbatch_execute_transaction.rsconfig_transaction_execute.rsproposal_vote.rsvault_transaction_execute.rsconfig_transaction_execute.rsmultisig_config.rstransaction_accounts_close.rstransaction_buffer_close.rslib.rslib.rslib.rslib.rslib.rslib.rslib.rsbatch_add_transaction.rsbatch_create.rsconfig_transaction_execute.rsvault_transaction_create.rsvault_transaction_create.rspda.rspda.rspda.rspda.rspda.rsconfig_transaction_execute.rsconfig_transaction_execute.rsmultisig_create.rsspending_limit_use.rsspending_limit_use.rsspending_limit_use.rsproposal_vote.rsproposal_vote.rslib.rslib.rsconstraint-analysisDetailed Findings
1. [CRITICAL] execute_message: CPI target program not validated
Location:
programs/squads_multisig_program/src/utils/executable_transaction_message.rs:211@execute_messageClass: #4 — Arbitrary CPI Target
Confidence: 90%
Impact: Attacker can substitute malicious programs in CPI calls, enabling theft of vault assets, unauthorized token transfers, or arbitrary code execution within multisig transactions.
Exploitability: moderate
Proof of Concept:
tests/poc_4_execute_message.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: Valid program state with legitimate authority
State after: Corrupted state / unauthorized access
Assertion: Vulnerability allows unauthorized operation
Fix Applied: Use Anchor's Program<'info, T> type or manually verify program ID.
View Diff
2. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
3. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/batch_create.rs:17@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/batch_create.rs:17 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
4. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/batch_execute_transaction.rs:11@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/batch_execute_transaction.rs:11 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Fix Applied: Validate each remaining account's key, owner, and/or signer status.
View Diff
5. [HIGH] batch_execute_transaction: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/batch_execute_transaction.rs:141@batch_execute_transactionClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/batch_execute_transaction.rs:141 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Fix Applied: Validate each remaining account's key, owner, and/or signer status.
View Diff
6. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/config_transaction_create.rs:17@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/config_transaction_create.rs:17 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
7. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/config_transaction_execute.rs:13@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/config_transaction_execute.rs:13 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Fix Applied: Validate each remaining account's key, owner, and/or signer status.
View Diff
8. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/multisig_add_spending_limit.rs:35@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/multisig_add_spending_limit.rs:35 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
9. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/multisig_config.rs:52@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/multisig_config.rs:52 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
10. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/multisig_remove_spending_limit.rs:15@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/multisig_remove_spending_limit.rs:15 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
11. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/proposal_activate.rs:9@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/proposal_activate.rs:9 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
12. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/proposal_create.rs:18@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/proposal_create.rs:18 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
13. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/proposal_vote.rs:14@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/proposal_vote.rs:14 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Fix Applied: Validate each remaining account's key, owner, and/or signer status.
View Diff
14. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/spending_limit_use.rs:23@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/spending_limit_use.rs:23 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Fix Applied: Add token::authority constraint to verify the token account's authority.
View Diff
15. [HIGH] unknown: PDA uses non-canonical bump (seed drift risk)
Location:
programs/squads_multisig_program/src/instructions/transaction_accounts_close.rs:21@unknownClass: #3 — PDA Derivation Mistake
Confidence: 85%
Impact: PDA at programs/squads_multisig_program/src/instructions/transaction_accounts_close.rs:21 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Exploitability: Moderate
Proof of Concept:
tests/poc_3_unknown.tsRun:
cd <repo> && anchor test -- --grep "PoC"Reproduction Steps
State before: [object Object]
State after: [object Object]
Assertion: PDA at programs/squads_multisig_program/src/instructions/batch_add_transaction.rs:19 accepts a user-supplied bump instead of using the canonical (highest) bump. An attacker can derive alternative valid PDAs.
Fix Applied: Zero account data before draining lamports, or use Anchor's close constraint.
View Diff
Fix Verification
To verify the fixes in this PR:
anchor testcd <repo> && anchor test -- --grep "PoC"cd <repo> && anchor test -- --grep "PoC"cd <repo> && anchor test -- --grep "PoC"cd <repo> && anchor test -- --grep "PoC"cd <repo> && anchor test -- --grep "PoC"Files Changed
programs/squads_multisig_program/src/utils/executable_transaction_message.rs— Use Anchor's Program<'info, T> type or manually verify program ID.programs/squads_multisig_program/src/instructions/batch_execute_transaction.rs— Validate each remaining account's key, owner, and/or signer status.programs/squads_multisig_program/src/instructions/config_transaction_execute.rs— Validate each remaining account's key, owner, and/or signer status.programs/squads_multisig_program/src/instructions/proposal_vote.rs— Validate each remaining account's key, owner, and/or signer status.programs/squads_multisig_program/src/instructions/vault_transaction_execute.rs— Validate each remaining account's key, owner, and/or signer status.programs/squads_multisig_program/src/instructions/transaction_accounts_close.rs— Zero account data before draining lamports, or use Anchor's close constraint.programs/squads_multisig_program/src/instructions/transaction_buffer_close.rs— Zero account data before draining lamports, or use Anchor's close constraint.programs/squads_multisig_program/src/lib.rs— Zero account data before draining lamports, or use Anchor's close constraint.programs/squads_multisig_program/src/lib.rs— Zero account data before draining lamports, or use Anchor's close constraint.programs/squads_multisig_program/src/lib.rs— Zero account data before draining lamports, or use Anchor's close constraint.programs/squads_multisig_program/src/lib.rs— Zero account data before draining lamports, or use Anchor's close constraint.programs/squads_multisig_program/src/lib.rs— Zero account data before draining lamports, or use Anchor's close constraint.programs/squads_multisig_program/src/instructions/multisig_create.rs— Use checked arithmetic methods.programs/squads_multisig_program/src/instructions/spending_limit_use.rs— Add token::authority constraint to verify the token account's authority.programs/squads_multisig_program/src/instructions/proposal_vote.rs— Add require! or constraint checking current state before allowing transition.programs/squads_multisig_program/src/instructions/proposal_vote.rs— Add require! or constraint checking current state before allowing transition.programs/squads_multisig_program/src/lib.rs— Add require! or constraint checking current state before allowing transition.programs/squads_multisig_program/src/lib.rs— Add require! or constraint checking current state before allowing transition.PoC Test Files Added
tests/poc_4_execute_message.ts— PoC for: execute_message: CPI target program not validatedtests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)tests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)tests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)tests/poc_3_batch_execute_transaction.ts— PoC for: batch_execute_transaction: PDA uses non-canonical bump (seedtests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)tests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)tests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)tests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)tests/poc_3_unknown.ts— PoC for: unknown: PDA uses non-canonical bump (seed drift risk)This PR was created by SolAudit Agent, an autonomous AI-powered Solana security auditor.
Pipeline: Clone → Parse → 15 Detectors → LLM Enrich → PoC Gen → Patch → Advisory → PR
Live demo: solaudit.fun
Full Security Advisory
Security Advisory: Squads Protocol v4 (squads-multisig-cli)
Executive Summary
Audit of the Squads Protocol v4 multisig program identified 81 vulnerabilities (1 Critical, 74 High) across 56 Anchor instructions. Critical failures in account initialization guards, CPI validation, and privilege verification enable authority hijacking, arbitrary code execution, and unauthorized asset drainage. Verdict: Do Not Ship. Immediate comprehensive remediation required prior to mainnet deployment.
Methodology
Static analysis of Rust/Anchor source code focusing on: account validation constraints, PDA canonicalization, reinitialization attack vectors, Cross-Program Invocation (CPI) safety, and privilege escalation via
remaining_accounts. Proof-of-concept exploits developed for critical and high-severity findings to confirm exploitability.Findings
1. Unvalidated CPI Targets (Critical)
execute_message.execute_messageinvokes target without program ID validation, allowing arbitrary logic execution within the multisig context.AccountInfowith AnchorProgram<T>types; reject execution if validation fails.2. Account Reinitialization Attacks (High)
multisig_create,batch_create, orproposal_createon existing initialized PDAs; missinginitconstraints andis_initializedguards permit complete state overwrite.#[account(init)]constraint to all creation contexts; implement booleanis_initializedguards with explicitrequire!(!initialized)checks; validate account discriminators.3. Non-canonical PDA Derivation (High)
batch_add_transactionvia alternative valid bumps.find_program_addressfor identical seeds; invoke instruction with non-canonical bump to create duplicate PDA, breaking authorization invariants.bumpconstraint without value to enforce canonical derivation; validate againstfind_program_addressoutput.4. Unvalidated remaining_accounts (High)
batch_execute_transaction,vault_transaction_execute, andconfig_transaction_executevia arbitrary account injection.remaining_accounts; instruction iterates without key/ownership validation, bypassing multisig safeguards.is_signerstatus; reject unverified accounts.5. Missing Owner Validation (High)
config_transaction_execute(line 103), bypassing ownership verification.UncheckedAccountto instruction; execution proceeds without owner check.UncheckedAccountwithAccount<'info, SpecificType>; add manualrequire!(account.owner == expected_program_id)assertions; validate discriminators.6. Account Revival Attack (High)
vault_batch_transaction_account_closeto drain lamports without zeroing data; refund rent-exempt minimum in same transaction; account retains pre-close approval bitmap allowing stale state exploitation.CLOSED_ACCOUNT_DISCRIMINATOR; use Anchor#[account(close = recipient)]constraint; validate initialization state in dependent instructions.Conclusion
The codebase exhibits systemic validation failures across account lifecycle management, CPI security, and privilege separation. The concentration of critical and high-severity vulnerabilities, combined with trivial exploitability, presents unacceptable risk to user funds and protocol integrity. Deployment is not recommended until all 81 findings are remediated and comprehensive security regression testing is completed.