Skip to content

program: RecoverNested doesn't forward TransferHook extra accounts #244

Description

@tschifra

RecoverNested is the only instruction that signs for a parent ATA's PDA, so it's the only path for a user to unwind tokens from a nested ATA. Its transfer_checked CPI is built with five accounts: source, mint, destination, authority, and the token program. That's fine for legacy SPL Token and for Token-2022 mints without hooks. It's not fine for mints with TransferHook set — Token-2022 tries to CPI into the hook program during the transfer, needs the hook program plus the ExtraAccountMetaList PDA plus whatever hook-specific accounts resolve from it, and RecoverNested never forwards any of them. The CPI errors out with MissingAccount, the outer transaction rolls back, and the tokens sit in the nested ATA with no instruction in the program that can extract them.

Previously filed as GHSA-cj9j-wvf7-3w99 (private advisory); re-filing here as a regular issue per @joncinque's guidance. Should be fixable in the Pinocchio migration via spl_token_2022::onchain::invoke_transfer_checked, which already handles the hook + fee cases correctly.

Runnable PoC (4 tests against mainnet-dumped BPF): https://gist.github.com/tschifra/ba737cfb139372af7fe7abe9b099be86

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions