Skip to content

Validate ATA token-program dispatch and existing occupants #83

@3esmit

Description

@3esmit

Summary

ATA should only forward token operations to the canonical token program, and idempotent Create should only succeed when the existing ATA PDA occupant is a valid canonical token holding for the requested owner and token definition.

The current ATA implementation derives downstream dispatch from account metadata:

  • Create uses token_definition.account.program_owner as the token program for the chained Token::InitializeAccount.
  • Transfer uses sender_ata.account.program_owner as the token program for the chained Token::Transfer.
  • Burn uses holder_ata.account.program_owner as the token program for the chained Token::Burn.

Create also returns success for any non-default account at the derived ATA PDA without checking that the occupant is owned by the canonical token program, decodes as a TokenHolding, and points at the requested token definition.

This is the ATA-program subissue for the trust-boundary hardening tracked in #70. It is adjacent to #69, which raises the same broader question for AMM user deposit accounts: token accounts should not be accepted only because their account data looks token-like.

Affected Area

  • ata/src/create.rs derives token_program_id from token_definition.account.program_owner.
  • ata/src/create.rs treats any non-default ATA PDA occupant as idempotent success.
  • ata/src/transfer.rs derives token_program_id from sender_ata.account.program_owner.
  • ata/src/burn.rs derives token_program_id from holder_ata.account.program_owner.
  • ata/core/src/lib.rs documents that dispatch is derived from these account owners.
  • Existing ATA tests cover happy-path create, idempotent create, transfer, burn, and wrong ATA address, but do not cover non-canonical token-program dispatch or malformed existing ATA occupants.

Why This Matters

ATA owns the PDA authorization used for downstream token calls. If an attacker can make ATA call a token-like program chosen from account metadata, the ATA PDA authorization can be forwarded to code that is not the canonical token program.

For Create, a malicious or malformed account can also occupy the correct ATA PDA and make future creates return success, even though the account is not a valid associated token account for that owner and definition.

Proposed Scope

  • Stop selecting downstream token programs from token_definition.account.program_owner, sender_ata.account.program_owner, or holder_ata.account.program_owner unless those owners are first checked against a trusted token program identity.
  • Validate Create inputs before emitting Token::InitializeAccount: the token definition must belong to the trusted token program.
  • Validate idempotent Create: an existing ATA PDA occupant must be owned by the trusted token program, decode as TokenHolding, and have definition_id == token_definition.account_id.
  • Validate Transfer and Burn before emitting chained calls: the ATA occupant must be owned by the trusted token program and decode as a holding for the PDA seed being verified.
  • For Burn, also require the supplied token definition account to be owned by the trusted token program and to match the holder ATA's definition_id.
  • Keep the fix focused on ATA ownership and dispatch validation. AMM-specific downstream effect checks and token InitializeAccount ownership checks should remain separate subissues under #70.

Acceptance Criteria

  • ata::create rejects token definition accounts owned by a non-canonical token program.
  • ata::create rejects an existing ATA PDA occupant that is not a canonical token holding for the requested definition.
  • ata::transfer rejects sender ATA accounts whose owner is not the canonical token program.
  • ata::burn rejects holder ATA accounts or token definition accounts whose owner is not the canonical token program.
  • ata::burn rejects a holder ATA whose definition_id does not match the supplied token definition account.
  • Tests cover malicious token-like program owners, malformed idempotent ATA occupants, and definition mismatches across unit and integration paths.
  • Existing valid create, idempotent create, transfer, burn, and private-owner create behavior remains intact.

Notes

  • The trusted token program identity should come from program-side configuration or guest wiring, not from caller-controlled account metadata.
  • If that identity cannot be represented without a small ATA guest or IDL change, split the wiring explicitly instead of preserving account-owner-derived dispatch.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions