You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The issue created from using solana_program::sysvar::instructions::get_instruction_relative(0, ...) to check if a program was called via Cross-Program Invocation (CPI) or directly. The code wrongly assumes this will return the calling instruction during a CPI and the current instruction when called directly. However, get_instruction_relative(0, ...) always returns the current program's instruction.
Understanding get_instruction_relative
The get_instruction_relative function retrieves an instruction relative to the currently executing instruction based on the call stack.
Here's how it works:
Index 0: Refers to the currently executing instruction.
Index -1: Refers to the instruction that called the currently executing instruction (useful for CPI).
Why the Bug Occurs
In bellow code, following check is used:
let instruction = get_instruction_relative(0,&ctx.accounts.instruction_sysvar_account.to_account_info()).unwrap();if instruction.program_id == id(){panic!("The instruction must be called from a CPI");}
This check fails because get_instruction_relative(0, ...) always retrieves the current program’s instruction, even during CPI. So the panic is triggered both for direct calls and CPI.
Potential Exploit
An attacker could exploit this behavior by crafting a transaction that bypasses this check. For instance, they could create a transaction where they call your program directly but manipulate the instruction sysvar to make it appear as if it was called via CPI, or they could exploit the misunderstanding of how get_instruction_relative works to bypass the check entirely.
Proposed Solution
To correctly determine if your program was called via CPI, you should:
Use get_instruction_relative(-1, ...): This will attempt to retrieve the instruction that called the currently executing instruction. If the program was called directly, there will be no instruction at index -1, and the function will return an error.
Check for Errors: If get_instruction_relative(-1, ...) returns an Err, it means the program was called directly. If it returns Ok, you can proceed, knowing it was called via CPI.
Describe the bug
Components make use of
solana_program::sysvar::instructions::get_instruction_relative
to enforce that they are called from CPI and the identify of the caller, e.g.: https://github.com/magicblock-labs/bolt/blob/main/programs/bolt-component/src/lib.rs#L11This may contains a bug, since a transaction could contain a valid instruction at index [0], but be malicious .
Proposed solution
The text was updated successfully, but these errors were encountered: