Skip to content

Rule: PDA seeds/signing consistency across CPIs #4

Description

@Cass402

Summary

Detect PDAs that are derived with one seed tuple/bump in a program but used as a signer/owner in a CPI with a different seed ordering, missing seeds, or mismatched bump.
Related to #3

Why it matters

Cross-program invocations (CPIs) can silently accept inconsistent PDA derivations, leading to accounts that verify in one place but not another. This can cause signing failures or unintended signer authority, especially in security-critical protocols.

Proposed Approach

•	Track Pubkey::find_program_address / find_program_address_seeds calls and Anchor #[account(seeds=..., bump)] attributes.
•	Build a “seed signature” (ordered seed list + bump + program_id) for each PDA.
•	On any CPI site, verify that with_signer(&[...]) matches the stored seed signature for that PDA.
•	Allow intentional exceptions via #[allow(pda_inconsistent_signer)].

Examples

Flag:

#[account(seeds=[b"pool", authority.key().as_ref()], bump)]
pub pool: Account<'info, Pool>;

// later in CPI
let signer_seeds = &[b"pool".as_ref(), &[bump]]; // missing authority seed
invoke_signed(..., &[signer_seeds]);

Pass:

let seeds = &[b"pool".as_ref(), authority.key().as_ref(), &[bump]];
invoke_signed(..., &[seeds]);

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions