Skip to content

Add detection for extra immutable account mutation patterns #25

@taasbaba

Description

@taasbaba

Issue Type

  • Feature Request

Description

I noticed a few mutation patterns that the current detector doesn't seem to catch, plus some tests I added for verification:

  • Two-level dereference with a chained call to try_borrow_mut_lamports() (new detection)
  • Same as above but with extra parentheses and to_account_info() variant (new detection)
  • Directly replacing the entire account struct (not just assigning to a field) (already detected — I just added a test to confirm)
  • Lamports modification on an UncheckedAccount variant (new detection)
  • Calling a method that takes &mut self (not a direct field assignment) (new detection)
  • Local shadow variable that’s just a normal struct, not an account (negative test to check false positives)
  • Sysvar, Program, and Signer accounts (negative test to check false positives)

Current Behavior

By case:

  • Two-level deref + try_borrow_mut_lamports() → not detected right now.
  • Same with extra parentheses + to_account_info() → also slips through.
  • UncheckedAccount lamports changes → goes undetected.
  • Mutations via calling a &mut self method → missed by the current rules.

Expected Behavior

By case:

  • Two-level deref + try_borrow_mut_lamports() → should be flagged.
  • Same with extra parentheses + to_account_info() → should be flagged.
  • UncheckedAccount lamports change → should be flagged.
  • &mut self method call → should be flagged if on an immutable account.

Steps To Reproduce

  1. Open an Anchor workspace with the Solana extension enabled.
  2. Add a Rust file containing one or more of these examples:
// Two-level dereference with try_borrow_mut_lamports()
**ctx.accounts.vault.try_borrow_mut_lamports()? = 0;

// Same as above but with extra parentheses and to_account_info()
**(ctx.accounts.vault.to_account_info()).try_borrow_mut_lamports()? = 0;

// Lamports change on an UncheckedAccount
**ctx.accounts.victim.try_borrow_mut_lamports()? = 0;

// Call a method that takes &mut self
ctx.accounts.vault.inc();
  1. Trigger “solana: Scan Workspace for Security Issues”.

Possible Solution

It seems the current detector design leaves some room for improvement, so I built a local version that handles these extra cases.
It’s a bigger change than a quick tweak, so if this feels like too much, please feel free to ignore.
Just wanted to share what I found in case it’s useful.

Status:
I already have a working branch with the implementation and tests passing locally.
I've opened a PR with these changes so it’s easier to review alongside this issue.

Environment

  • OS: macOS 15.6 (Darwin Kernel 24.6.0) - x86_64
  • VS Code version: 1.103.0
  • Extension version: 0.1.2
  • Solana CLI version: solana-cli 2.2.12 (src:0315eb6a; feat:1522022101, client:Agave)
  • Anchor version: anchor-cli 0.31.1
  • Rust: rustc 1.86.0 (LLVM 19.1.7)

Additional Context

No extra context at the moment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions