Metaplex Authority Bypass
Detects missing update authority verification in Metaplex Token Metadata operations.
Metaplex Authority Bypass
Overview
Remediation Guide: How to Fix Metaplex Authority Bypass
The Metaplex authority bypass detector identifies Solana programs that invoke Metaplex Token Metadata program instructions or modify metadata account data without verifying that the transaction signer is the designated update_authority. This allows unauthorized modification of NFT metadata including name, symbol, URI, creator arrays, and royalty settings.
Why This Is an Issue
Metaplex Token Metadata operations require the update_authority to authorize changes. When a program makes CPI calls to the metadata program without first verifying the caller holds the correct authority, attackers can:
- Modify NFT metadata (name, image, attributes) to impersonate valuable collections
- Bypass collection verification, adding unauthorized NFTs to verified collections
- Alter creator arrays and royalty percentages to redirect fees
- Change supposedly immutable metadata by skipping
is_mutableflag checks
Multiple Solana NFT marketplace incidents in 2021-2022 exploited missing authority verification to perform unauthorized metadata updates and collection verification bypasses.
CWE mapping: CWE-862 (Missing Authorization), CWE-285 (Improper Authorization).
How to Resolve
Native Rust
pub fn update_nft_metadata(accounts: &[AccountInfo]) -> ProgramResult {
let authority = &accounts[0];
let metadata_account = &accounts[1];
// Verify the authority signed the transaction
if !authority.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
// Verify the signer matches the metadata's update_authority
let metadata = Metadata::from_account_info(metadata_account)?;
if metadata.update_authority != *authority.key {
return Err(MetadataError::InvalidUpdateAuthority.into());
}
// Verify metadata is mutable before allowing changes
if !metadata.is_mutable {
return Err(MetadataError::DataIsImmutable.into());
}
// Safe to proceed with Metaplex CPI
Ok(())
}
Anchor
#[derive(Accounts)]
pub struct UpdateMetadata<'info> {
pub authority: Signer<'info>,
#[account(
constraint = metadata.update_authority == authority.key()
@ ErrorCode::InvalidUpdateAuthority,
constraint = metadata.is_mutable @ ErrorCode::MetadataImmutable
)]
pub metadata: Account<'info, MetadataAccount>,
pub metadata_program: Program<'info, MplTokenMetadata>,
}
Examples
Vulnerable Code
pub fn update_metadata_uri(accounts: &[AccountInfo], new_uri: String) -> ProgramResult {
let metadata_program = &accounts[0];
let metadata_account = &accounts[1];
// VULNERABLE: no authority check before CPI to metadata program
let ix = update_metadata_accounts_v2(
*metadata_program.key,
*metadata_account.key,
*accounts[2].key, // authority -- not validated!
None,
Some(DataV2 { uri: new_uri, ..Default::default() }),
None,
);
invoke(&ix, accounts)?;
Ok(())
}
Fixed Code
pub fn update_metadata_uri(accounts: &[AccountInfo], new_uri: String) -> ProgramResult {
let authority = &accounts[2];
// FIXED: verify authority signed and matches metadata
if !authority.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
let metadata = Metadata::from_account_info(&accounts[1])?;
if metadata.update_authority != *authority.key {
return Err(MetadataError::InvalidUpdateAuthority.into());
}
if !metadata.is_mutable {
return Err(MetadataError::DataIsImmutable.into());
}
// Now safe to CPI
let ix = update_metadata_accounts_v2(/* ... */);
invoke(&ix, accounts)?;
Ok(())
}
Sample Sigvex Output
{
"detector_id": "metaplex-authority-bypass",
"severity": "high",
"confidence": 0.80,
"description": "Cross-program invocation to Metaplex Token Metadata program occurs without verifying that the transaction signer is the designated update authority.",
"location": { "function": "update_metadata_uri", "offset": 1 }
}
Detection Methodology
The detector performs multi-pass analysis:
- Function name filtering: Skips functions whose names do not suggest metadata operations (e.g.,
update_metadata,verify_collection,set_authority). - Authority check tracking: Identifies
CheckSignerandCheckOwnerstatements as evidence of authority validation. - CPI detection: Locates cross-program invocations that may target the Metaplex Token Metadata program and flags those lacking prior authority checks.
- Direct write detection: Identifies direct writes to metadata account data without authority verification.
- Heuristic analysis: Functions named for metadata updates that contain no security checks are flagged separately.
Limitations
- Function name heuristics may miss metadata operations with non-standard names.
- The detector cannot verify that a CPI target is specifically the Metaplex program without program ID constants in the bytecode.
- Anchor programs using
has_one = update_authorityconstraints may be flagged at reduced confidence if the constraint is not visible in decompiled output.
Related Detectors
- Metadata Authority Transfer — detects unsafe authority transfer operations
- SPL Token Metadata Validation — detects missing PDA derivation and URI validation
- Missing Signer Check — general signer verification detection