Back to Blog
adversarial-audit application-security idor mfa wordpress-security essential-eight

The 1080° Adversarial Audit: 59 Findings, 6 IDORs, One MFA Takeover — What Real Security Work Looks Like

By Ash Ganda | 24 July 2026 | 9 min read

Ninety percent of what gets published as “Australian SMB cybersecurity” is a rewrite of the Essential Eight with a stock hero image. The problem isn’t that Essential Eight is wrong — it’s that “enable MFA” is a policy, and policies don’t survive contact with a real codebase. What survives is the adversarial pass that assumes the policy has already failed and looks for the concrete class of bug the policy was meant to prevent.

This post is the receipts version of that adversarial pass. Every fix cited below is checkable against docs/repo_activity.csv in the blog-content-automation repo — commit hash, date, line count, all reproducible.

What “1080°” means (and why it’s not marketing)

The three laps of the 1080° adversarial audit: Lap 1 (360°) developer self-review checks correctness; Lap 2 (720°) challenger review looks for what the developer missed; Lap 3 (1080°) adversarial pass assumes an attacker exists and looks for exploit surface. Only the third lap catches security bugs because only the third lap has a threat model.

The 1080° adversarial audit is a three-lap review pattern I use on every production codebase before it ships a security-sensitive feature:

  • Lap 1 (360°) — the developer’s own review: does the code do what the story says.
  • Lap 2 (720°) — a challenger review: assume the developer was wrong and look for what they missed.
  • Lap 3 (1080°) — an adversarial pass: assume there’s an attacker, not a bug. What can they do with this endpoint, this input, this state transition, this trust boundary?

The three laps catch three different failure classes. Only the third lap catches the security bugs, because only the third lap has a threat model.

On 10 June 2026, one such pass on the social-media-autopost-plugin produced:

chore(audit): 1080° adversarial audit (59 findings) + roadmap for External API + MCP +1,488 lines (audit report + remediation roadmap)

That is not a checklist. That is 59 concrete vulnerabilities, categorised by severity, mapped to file:line, with a shipping plan for each. The follow-up commits below are what that plan actually shipped.

Real fix #1 — Six IDORs, an MFA takeover, brute-force, and DoS in one push

Same day, different repo:

fix(adversarial-codebase/backend): 6 IDORs + MFA takeover + brute-force + DoS guards CardGamePro · 10 June 2026 · +78 / −37

Six IDORs + MFA takeover + brute-force + DoS guards — four vulnerability classes fixed in a single 78-line push. Each maps to an Australian-SMB breach class from recent news: IDOR enumeration (Optus/Medibank-class), MFA-enrolment session binding, credential-stuffing rate limits, payload-size caps.

Unpack that commit subject, because every phrase is a class of Australian-SMB breach you can name from the news:

  • 6 IDORsInsecure Direct Object References. The API accepted an id in the URL (/api/game/42/hand), authenticated the caller, and then returned whoever’s data was at id=42 without checking that the caller owned it. Six separate endpoints had that bug. This is how the Optus / Medibank–class incidents work: authenticated attacker, unowned data, straight enumeration of IDs.
  • MFA takeover — MFA was enrolled but the enrolment endpoint didn’t re-verify the requester was the account owner (or accepted a stale session). An attacker with a leaked credential could bind their second factor to your account and then MFA would help them, not you.
  • Brute-force guards — no rate-limiting on the login/OTP endpoints. Cheap credential stuffing was possible with no lockout, no exponential backoff, no CAPTCHA escalation.
  • DoS guards — an endpoint that accepted an unbounded payload / recursion / query complexity. One request could pin a worker for seconds.

The fix is 78 lines because the fixes are boring: owner-scoped queries, session-binding on MFA enrolment, IP+account rate-limit, payload-size caps. All the fixes together are less code than the audit report that found them — which is the whole lesson: the expensive artefact is the adversarial pass, not the patch.

Real fix #2 — “1080° challenger-review fixes (CRIT + HIGH + MEDIUM + LOW)”

Ten weeks earlier, same repo, larger sweep:

feat: 1080° challenger-review fixes — CRIT + HIGH + MEDIUM + LOW (Build 28) CardGamePro · 1 May 2026 · +3,086 / −92

3,086 lines of remediation across four severity tiers in one build. That is what shipping the full audit output at once looks like — not “we’ll get to LOWs later.” The reason to ship LOWs together with CRITs is that a stack of LOWs is often how a CRIT becomes exploitable — the CRIT is the ceiling that collapses, the LOWs are the missing joists.

The same 1080° framework was applied concurrently to two other repos on the same day:

DateRepoCommit+/-
2026-05-01travel-rag-blogfix: security + correctness from 1080 audit (C3, C4, C5, H5)+84 / −22
2026-05-01potentialz-wix-velofeat(form-iq+rag): 1080° audit fixes — upgrade UX, lifecycle, security+708 / −42

Three codebases, one methodology, one Friday. That is how adversarial audit becomes an operating rhythm, not a compliance event.

Real fix #3 — Billing IDOR closed by JWT signature verification

Not every IDOR fix is one line. Some require re-plumbing the trust boundary itself:

fix(security): verify JWT signature in entitlements routes (closes CRITICAL billing IDOR) cosmos-mobile-templates · 28 May 2026 · +281 / −19

How the JWT-signature billing IDOR worked: the entitlements API decoded and trusted the JWT claims (including 'sub' = user id) without verifying the signature. An attacker could forge any user's JWT, drop it in the Authorization header, and receive that user's entitlements. Fix: signature-verification middleware applied globally so no route can skip it.

What that says: the entitlements API accepted a JWT and read the claims but did not verify the signature. An attacker could forge a JWT claiming any user’s sub, drop it in the Authorization header, and the API would happily return that user’s entitlements/billing.

The fix is 281 lines because the correct pattern is not “add a signature check” — it’s “add signature verification as middleware so no route can ever skip it.” That is the difference between a patch and an architectural fix.

Three days later, the same repo shipped the follow-up:

fix(security): close tier IDOR via server-side product-tier allowlist (entitlements/checkout) cosmos-mobile-templates · 31 May 2026 · +252 / −4

The bug: the client was trusted to say which product tier it was buying. The fix: server maintains the allowlist; client can only say “I want tier X”; server decides whether the caller can have tier X.

Both fixes are the same architectural rule: never trust the client’s claim about what it’s allowed to do — verify against server-authoritative state on every request. If you take one thing from this post, take that.

Real fix #4 — “Atomic owner-scoped writes, zero-trust caps, IDOR tests”

Fixes without tests come back. Same-day pair, three weeks before the 59-finding audit:

harden(workspaces): atomic owner-scoped writes, zero-trust caps, IDOR tests social-media-autopost-plugin · 21 May 2026 · +216 / −27

chore(hardening): app-1080 remediation batch (#4, #5, #6, #7) + middleware restart (#3) social-media-autopost-plugin · 21 May 2026 · +208 / −57

The three architectural guardrails that stop IDORs recurring: (1) atomic owner-scoped writes — every write query includes both id and owner_id in WHERE, no race window; (2) zero-trust caps — per-account and per-workspace hard limits stop a compromised account being weaponised; (3) IDOR tests — the failing test that catches a regressed owner-scope before it ships. The tests are what stop the fix rotting in six months.

Three things worth naming:

  1. Atomic owner-scoped writes. Every write query includes both the row id and the owner_id in the WHERE clause. If the owner doesn’t match, the write silently affects zero rows — no race between “check owner” and “do write” for a concurrent attacker to slip through.
  2. Zero-trust caps. Per-account and per-workspace hard limits (posts/day, media/GB, API calls/min). A compromised account can’t be weaponised into a fleet-wide DoS because its own caps kick in first.
  3. IDOR tests. The same commit added the tests that fail if any endpoint stops enforcing owner-scoping. This is the guardrail that stops the fix from rotting in six months.

That third one is the difference between “fixed on 21 May” and “fixed forever.”

Why this matters for an Australian SMB

Two reasons — one legal, one operational.

Legal: the Notifiable Data Breaches (NDB) scheme under the Privacy Act requires eligible data-breach notification to the OAIC and affected individuals within 30 days. An IDOR that leaks another user’s data is a data breach under the scheme, whether it was exploited in bulk or by a single curious user. “We didn’t know we had it” is not a defence.

Operational: the cost of an IDOR is not the fix (78 lines). It’s the breach notification, the customer trust loss, the potential OAIC investigation, the cyber-insurance premium repricing (see our cybersecurity insurance guide), and the six months your engineering team spends on remediation theatre instead of building product. The Essential Eight adversarial pass is cheaper than any of those, by an order of magnitude.

What SMB security services should actually deliver

Three questions to separate real security work from compliance theatre when evaluating an MSP or cyber-audit vendor: (1) show me your last three audit outputs with commits — not PDFs, not scan reports; (2) how do you prevent a fixed IDOR from reappearing — the answer must name a test suite, lint rule, or architectural constraint; (3) what's your mean time to ship a CRIT finding — days, not quarters.

If you’re evaluating an MSP or a “cyber-audit” vendor, ask them these three questions. The answers separate the real work from the compliance theatre:

1. “Show me your last three 1080°-equivalent audit outputs — with commits.” Not a PDF report. Not “we ran a scan.” A list of file:line findings with the commit hashes that closed each one. If they can’t produce that, they ran a scanner and forwarded you the output.

2. “How do you prevent an IDOR you already fixed from reappearing?” The correct answer names a test suite or lint rule or architectural constraint (like the owner-scoped middleware pattern above). “We’ll re-audit annually” is the wrong answer — bugs regress in weeks, not years.

3. “What’s your mean time to ship a CRIT finding to production?” A shop that finds a CRIT and takes six weeks to patch it is worse than a shop that never audited. Findings in a report are attackable evidence if the report leaks. Real cadence is find → fix → ship → test-suite guardrail, on the order of days, not quarters.

Pricing — what a 1080° pass actually costs

Transparent tiers for Australian SMBs. All prices AUD, ex-GST.

ScopeCodebase sizeDeliverableInvestment
Spot auditSingle web app, ≤10k LOC1080° findings report + severity-ranked fix list$4,500
Standard auditWeb app + API, 10–30k LOCFull 1080° pass + prioritised remediation roadmap$6,500–8,500
Program (quarterly)Full product surfaceAudit + remediation execution + guardrail tests + quarterly re-pass$1,800–3,200/mo
Incident response add-onPost-breachNDB-scheme notification prep + adversarial-audit fast-track$3,500 + $220/hr

All quotes fixed-price for defined scope. No “up to” pricing.

The 5-question FAQ

Q: Is a 1080° adversarial audit different from a penetration test? Yes. A pen test is black-box and external; a 1080° pass is white-box (with source code) and adversarial. The two are complementary — the pen test proves the perimeter; the 1080° pass proves the logic. IDORs like the ones above rarely surface in a black-box pen test because they require authenticated access to another legitimate user’s data to detect.

Q: My site is “just WordPress.” Do IDORs apply? Yes, and more than you’d expect. Any custom plugin, membership plugin, or REST-API endpoint that accepts an id and returns data is a candidate. WordPress core is well-audited; the plugin layer is where SMB IDORs live. See our self-hosted stack walkthrough for the concrete architectural pattern.

Q: We have MFA on. Aren’t we safe from the “MFA takeover” you described? “MFA on” and “MFA enrolment is authenticated” are different guarantees. If your MFA enrolment endpoint doesn’t re-verify the requester’s current session against the target account, someone with a leaked password can enrol their device as your second factor. This is not a theoretical bug — it was one of the six findings above.

Q: How much does this cost? See the pricing table above — spot audits from AU$4,500, full programs from AU$1,800/mo. That’s less than the deductible on most Australian SMB cyber-insurance policies.

Q: What’s the fastest way to know if we’re at risk right now? Two-question triage: (a) do any of your APIs accept an id in the URL and return data (yes for almost every SMB with an app or a portal); (b) does every write query in your codebase include the owner in the WHERE clause. If the answer to (a) is yes and you can’t confidently answer (b) with “yes, and we have tests for it,” you’re at risk.

What this doesn’t prove

To keep the same honesty this post is meant to model: the numbers above prove that four production codebases were audited under one methodology, that specific vulnerability classes were found and fixed, and that guardrails (tests, middleware, allowlists) were shipped to prevent regression.

They do NOT prove:

  • That every vulnerability in those codebases was found (some of the commits above are evidence that findings were missed by earlier laps)
  • That the same methodology would find every vulnerability in your codebase
  • That this replaces third-party pen testing (it doesn’t — see the FAQ)

Every one of those follow-up questions has a specific answer. If you’re evaluating your own SMB security posture, get in touch and I’ll walk you through what a 1080° pass on your stack would look like.

The bottom line

Australian SMB cybersecurity is at the awkward point where the compliance frameworks are mature but the actual engineering practice hasn’t caught up. Most breaches don’t happen because someone skipped the Essential Eight — they happen because the implementation of an Essential Eight control had an IDOR, a missing rate-limit, or a trusted client claim.

The receipts are the moat. If your provider can’t show you commits, they’re not doing the work.


Cloud Geeks is the specialist IT and cybersecurity arm of Ganda Tech Services — the technology consultancy bringing together cloud infrastructure, application security, and Australian SMB compliance.

Ready to upgrade your IT and cloud setup?

Let's talk about cloud, infrastructure, or cybersecurity. We help Sydney SMBs cut hosting costs, harden their stack, and stop firefighting.

Bella Vista, Sydney