Kora (Paymaster Service), Fee Payer Policy Bypass, CVE-2025-XXXX (Medium)

Listen to this Post

The vulnerability arises from how Kora’s transaction parser handles unrecognized inner Cross-Program Invocation (CPI) instruction types, specifically those from the Token-2022 program extensions (like `WithdrawWithheldTokensFromMint` or ConfidentialTransfer). When the `reconstruct_spl_token_instruction()` function encounters an instruction type it doesn’t recognize, it falls through a catch-all `_ =>` arm. Instead of rejecting the transaction, it calls build_default_compiled_instruction(), which creates a stub `CompiledInstruction` containing only the correct program ID index but with empty `accounts` and empty `data` vectors . This stub is added to the transaction’s `all_instructions` list, allowing it to pass program allowlist and disallowed account checks because it contains no account references. However, when the fee payer policy validation runs, the `parse_token_instructions()` function attempts to deserialize the instruction data. Since the stub data is empty, `TokenInstruction::unpack(&[])` fails, triggering an error. The parsing function contains another catch-all `_ => {}` that silently skips this failed instruction without adding it to the parsed instruction map for policy checks. Consequently, when `validate_fee_payer_usage()` iterates through parsed instructions, the original Token-2022 extension instruction is completely invisible. The transaction is signed by Kora, and on-chain execution proceeds with the fee payer acting as an authority (e.g., withdraw authority) without any policy enforcement, potentially allowing unauthorized fee draining or manipulation .

dailycve form:

Platform: Kora Paymaster
Version: Prior to patch
Vulnerability : Fee Payer Bypass
Severity: Medium
date: 2024-07-18

Prediction: Patch expected soon

What Undercode Say:

Analytics:

The core issue is a “fail-open” design in the instruction reconstruction logic. For system and SPL token programs, Kora maintains exhaustive lists of known instruction types. For Token-2022—a newer, extensible standard—the parser does not recognize extension instructions (e.g., TransferFeeExtension, ConfidentialTransfer, PermanentDelegate). When an unknown type is encountered, the code defaults to building an empty stub to maintain compatibility. This stub, however, lacks the necessary data for fee payer policy deserialization, causing the policy engine to silently ignore the instruction. The vulnerability is forward-looking: any future Token-2022 extension will automatically bypass Kora’s fee payer policies until explicitly added to the parser. This creates a significant security gap where authority-based operations (withdrawals, mints, transfers) can be executed with the fee payer’s signature but without policy consent.

Bash Commands and Code:

To test if your Kora instance is vulnerable, you can attempt to simulate an unrecognized instruction.
First, clone the Kora repository and navigate to the test directory.
The following is a conceptual test based on the provided proof of concept.
Build a test that attempts to parse a simulated unknown instruction.
cat > test_unrecognized_instruction.rs << 'EOF'
[bash]
fn test_unrecognized_instruction_produces_empty_stub() {
// Simulate what happens for an unrecognized Token-2022 instruction
let program_id_index: u8 = 3; // Assuming Token-2022 is at index 3
// This is what the catch-all arm produces:
let stub = IxUtils::build_default_compiled_instruction(program_id_index);
assert_eq!(stub.accounts.len(), 0); // No accounts
assert_eq!(stub.data.len(), 0); // No data
// Attempt to parse it:
let result = TokenInstruction::unpack(&stub.data);
assert!(result.is_err()); // Cannot parse empty data
// Therefore: fee payer policy is never applied to this instruction.
// The fee payer could be the withdraw_withheld_authority in the
// REAL instruction, but the stub has zero accounts — invisible.
}
EOF
To run the test (conceptual, requires proper Rust test setup):
cargo test test_unrecognized_instruction -- --nocapture
To inspect the vulnerable code paths:
grep -n "build_default_compiled_instruction" crates/lib/src/transaction/instruction_util.rs
grep -n "_ =>" crates/lib/src/transaction/instruction_util.rs

How Exploit:

An attacker crafts a transaction containing a Token-2022 CPI instruction that Kora’s parser does not recognize, such as `WithdrawWithheldTokensFromMint` from the TransferFeeExtension. The attacker ensures that the fee payer is set as the `withdraw_withheld_authority` for that mint. When the transaction is submitted to Kora for signing, Kora’s `reconstruct_spl_token_instruction()` function sees the unknown instruction type and falls through to the catch-all arm, generating a stub with empty accounts and data. The transaction passes program validation (Token-2022 is allowed) and account validation (stub has no accounts to check). During fee payer policy validation, the stub fails to deserialize into a known TokenInstruction, so it is silently skipped. Kora signs the transaction, believing all policies are satisfied. On-chain execution uses the real instruction data from the original transaction (not the stub), and the fee payer’s authority is used to withdraw withheld fees from the mint to an account controlled by the attacker, bypassing all configured fee payer restrictions .

Protection from this CVE:

Apply the recommended patch to change the behavior from “fail-open” to “fail-secure.” In crates/lib/src/transaction/instruction_util.rs, modify the catch-all arms to return an error instead of building a default instruction:

// In reconstruct_system_instruction:
_ => {
return Err(KoraError::InvalidTransaction(format!(
"Unrecognized system instruction type '{}' in CPI — cannot validate fee payer policy. Transaction rejected.",
instruction_type
)));
}
// In reconstruct_spl_token_instruction:
_ => {
return Err(KoraError::InvalidTransaction(format!(
"Unrecognized SPL Token instruction type '{}' in CPI — cannot validate fee payer policy. Transaction rejected.",
instruction_type
)));
}

Alternatively, if maintaining compatibility with future extensions is required, maintain an explicit allowlist of known-safe instruction types that do not involve authority checks, and reject all unknown types by default. Update Kora to the latest patched version as soon as it is released.

Impact:

  • Fee Payer Policy Bypass: Any Token-2022 extension instruction that uses the fee payer in an authority role (withdraw authority, mint authority, permanent delegate, etc.) becomes invisible to Kora’s policy engine.
  • Financial Loss: Attackers can drain withheld transfer fees from mints, manipulate interest rates, or use permanent delegate privileges to transfer or burn tokens from any account without policy restrictions .
  • Forward-Looking Risk: As the Solana ecosystem adopts new Token-2022 extensions, all future instructions will automatically bypass Kora’s security policies until manually added to the parser, creating an ongoing maintenance burden and risk window.
  • Precondition Limitation: The attack requires the fee payer to hold an authority role for specific Token-2022 accounts, which is uncommon in standard deployments but possible in misconfigured setups or when fee payers are over-privileged.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top