The $1.1M bug hiding in plain sight

A simple permission check could have prevented this — here’s how.

Hey, it’s Gio.

Over the past few issues, I’ve shared examples of subtle logic bugs we’ve caught during onboarding and what onboarding with Octane actually looks like.

But today, I want to highlight a far more direct (and much more expensive) failure.

One function. No access control. $1.1 million lost.

This one didn’t hide in complex logic.
It sat in plain sight and slipped into production anyway.

The bug: a public price feed setter

On April 15, 2022, attackers drained roughly $1.1 million in BNB from a DeFi lending protocol called RiFi. The exploit took just minutes.

At its core, the issue was almost shockingly simple:

A smart contract function — setOracleData()— let anyone update the address of the Chainlink price oracle used to determine collateral valuations.

No onlyOwner modifier.
No access control at all.

Anyone could call it.

Just one missing modifier enabled a $1.1M exploit. This simple change would’ve stopped it cold.

That meant an attacker could swap in a malicious oracle address, instantly replacing a trusted price feed with a fake one.

And that’s exactly what they did:
→ Set up a malicious oracle
→ Faked a collateral value
→ Borrowed out the entire lending market
→ Laundered the funds through Tornado Cash

Total loss? 2,600 BNB.

Why these bugs still make it to mainnet

You’d think something this basic wouldn’t slip through. But it happens — even in audited codebases.

Security reviews are time- and scope-limited. Manual audits involve parsing thousands of lines of code while scanning for hundreds of attack vectors. But some bugs — like a missing onlyOwner on a critical function — are too important to miss. They should never make it to mainnet.

It’s a challenge of scale, not effort. And it’s why static review alone isn’t enough.

How Octane would have caught it

Octane is trained to catch both the painfully obvious and the dangerously subtle.
From public functions with no access control… to role modifiers that don’t actually enforce roles — our models flag vulnerabilities before they reach mainnet.

Here are three real examples Octane surfaced:

Example 1: The RiFi Exploit — Missing Access Control on Oracle Setter

This is the exact bug that led to $1.1 million being drained from the RiFi lending protocol:

Function: setOracleData()
Issue: No access control — anyone could call it
Impact: Attacker replaced the Chainlink oracle with a fake one and drained the protocol

This kind of issue should never make it to production. Octane would’ve flagged it the moment the pull request hit GitHub — and a single onlyOwner check would’ve prevented a seven-figure exploit.

Example 2: Suzaku’s addAssetClass() — Unauthorized Asset Registration

This finding came up during a real Octane onboarding:

Function: addAssetClass()
Issue: Marked external with no onlyOwner
Impact: Any external user could register arbitrary asset classes and set manipulated validator thresholds

The function modified critical protocol configuration — yet had no access restriction. Octane surfaced this as a critical severity issue with a direct fix. It’s another case where a simple modifier makes the difference between safe and exposed.

Example 3: EOA Bypass in onlyDelegatedRole — A More Subtle Logic Flaw

Now here’s one that’s harder to catch — even for experienced reviewers:

Function: onlyDelegatedRole modifier
Issue: Logic only applied to contract addresses, not EOAs
Impact: Any Externally Owned Account could bypass the check and call restricted functions

This wasn’t a missing modifier, it was a flawed implementation of one that was missed by a manual auditing firm. Octane identified that the logic failed to enforce the intended access control behavior, allowing EOAs to bypass delegate role checks entirely.

Why this matters

Access control bugs aren’t just a single class of issue. They range from dead-simple omissions to subtle logic errors hiding inside modifiers.

Octane’s AI catches both — automatically, continuously, and in real time.

Even if you’ve had a thorough security review, it’s easy for issues like this to slip back in:

  • A new contributor merges a module

  • A function gets refactored

  • Code gets copied across contracts without inherited permissions

Security isn’t a checkbox. It’s a continuous process that evolves with your code.

That’s why Octane scans every pull request, on every change — flagging permission issues like this before they ever touch mainnet.

Bugs like this are avoidable.

If you’re building in DeFi, you shouldn’t have to worry about a missing access control check compromising your entire protocol.

We can show you exactly how Octane would’ve caught this and how we catch similar issues in seconds.

Book a demo and we’ll walk you through it.

More soon,
Gio

Ready to Secure Your Smart Contracts?

Deploy with confidence by adding Octane’s AI security to your CI/CD pipeline. Schedule a live demo to see how we deliver 24/7 offensive intelligence and real-time vulnerability detection.

Interested in hearing more?

Login or Subscribe to participate in polls.