Authored Articles

Field notes / AI pentesting / Entry 01

Race Conditions and HackerOne Heartbreaks:Day One or One Day

Two targets. One private finding. One duplicate. The real story of my first steps into AI-assisted pentesting, and the evidence that made the work worthwhile.

By Vincent Suen7 min read
Vincent Suen wearing a green hat in front of a bookshelf

Vincent Suen

A journey into AI pentesting.
Starting from day one.

From the research notebookHypothesis Evidence Reality check
GreenHat editorial cover: Race Conditions and HackerOne Heartbreaks

01The beginning

Day one, with all the false starts.

This is the beginning of my blog series tracking my journey into AI pentesting. I’m not claiming to be the best nor have the best methodology. Instead, my goal is to document my journey from day one.

Sharing the real journey is much more valuable to me than just posting the highlights, and hopefully you’ll learn a thing or two or at least find it interesting. :)

We’ve all read the flashy articles about AI jailbreaking and hacking enterprise targets in seconds. I definitely walked into this with a chip on my shoulder, assuming it would be easy. I always pictured pentesting as a cinematic lifestyle: a blacked-out room, a hoodie up, five monitors, and hacking the mainframe. In reality, the difficult part is just me staring at a single laptop screen, heavily caffeinated, trying my best to stay awake for my 9:00 AM calls.

But here is the reality: if you let an LLM loose on an enterprise codebase without strict guardrails, it won’t find zero-days while you sleep. It will confidently hallucinate two dozen fake Semgrep hits and recommend submitting an out-of-scope bug that gets your account banned. Unless you have extremely great luck, unlike me.

Over the last two weeks, I’ve been running Olympus, GreenHat Security’s federated, AI-assisted research loop, against a series of open-source enterprise applications. Instead of treating the AI as a magic 0-day machine, I used it to thin-slice codebases and generate strict dynamic test harnesses.

02The pivot

From rejections to zero-days.

My entire sprint actually started with a rejection. I submitted what I thought was a solid session-invalidation bug, only to get hit with the dreaded “Informative” status.

A wise man once told me: “Quit, don’t quit. Noodles, don’t noodles.”

Wait, wrong man. What my boss told me was to never just walk away from a rejection. Use the triager’s feedback as your roadmap, dig deeper, and pivot.

That got me thinking: if the developers were making risky architectural choices with token validation, where else were they cutting corners? If standard JWT expiration was an “expected architectural choice,” I needed to stop hunting basic token flaws and start targeting the complex architectural blind spots they actually cared about.

I used that exact feedback as a constraint for the AI, pointing Olympus at adjacent preview and metadata endpoints where developer “shortcuts” might bypass primary authorization guards.

03Review setup

Two targets. One hypothesis.

To avoid LLM context rot, we don’t feed Olympus entire repositories. I constrained the AI to specific, high-risk authentication handlers and controllers. For this sprint, we targeted two distinct threat models:

Enterprise ERP

SAML module / Tenant isolation

Can an unauthenticated user bypass tenant isolation in a multi-database deployment to read another tenant’s SAML configuration?

Government forms

Public templates / Shared cache

Can an unauthenticated user abuse a public template API to poison a Redis cache and force unpublished, unapproved draft forms onto live citizen-facing pages?

The core hypothesis for both targets was identical: developers often apply robust authorization checks to the primary state-changing routes but forget to apply those same strict checks to adjacent metadata or preview-oriented routes.

Findings at a glance As recorded in this sprint
TargetBug classSeverityOutcome
A / ERPTenant isolation bypassMedium CVSS 5.3Triaged (Private)
B / FormsCache poisoning race conditionHigh CVSS 8.2Duplicate

04The hunt / Target A

The clean win.

The enterprise ERP hunt was a textbook win. The AI flagged a suspicious asymmetry in the SAML controller routing: the primary sign-in route properly validated database boundaries using a strict tenant filter, but the adjacent metadata route accepted an attacker-controlled query parameter with zero filtering.

Same controller. Different boundaries.
Primary sign-in routeTenant filter enforcedDatabase boundary respected
Adjacent metadata routeTenant filter missingCross-tenant configuration exposed

Authorization on the main route did not protect the neighboring route.

To prove this wasn’t a static artifact, I spun up a purpose-built two-tenant Docker lab. By enforcing strict positive and negative controls, I proved that unauthenticated actors could bypass multi-tenant isolation boundaries to read sensitive configuration data and map out valid internal databases. We immediately routed a private, responsible disclosure to the vendor’s security team.

05The hunt / Target B

The twist was in the timing.

Then came the government forms platform. Olympus flagged a primary server action responsible for form submissions. A specific boolean argument used for “previews” was entirely client-controlled. When flagged to true, it bypassed the application’s anti-automation captcha validation and seemingly cached the draft version of a form under a shared, un-moded Redis key.

I built a zero-dependency Python harness to prove the exploit. The first run came back INCONCLUSIVE.

This was the plot twist: it wasn’t an arbitrary write. My harness was failing because the target short-circuited on a warm cache hit. I realized the exploit was actually a repopulation race condition.

You couldn’t just write the cache at will; you had to hit the endpoint in the exact millisecond after the 30–60 second TTL expired.

Inside the race

A cache miss changes the outcome.

The cache expires, a preview request wins the race to refill it, and the unapproved draft reaches the public page.

The cache race, in motion. Timing is compressed.

Warm cache

The existing value is returned. The first harness cannot overwrite it.

TTL expires

After 30–60 seconds, the shared cache needs to be repopulated.

Preview request wins

The draft fills the shared key before legitimate traffic does.

Public impact The live page serves the unapproved draft template.

Conceptual sequence from this test. The weakness depended on cache state and request timing.

The exploit logic flow

  1. Request. Anonymous POST to submitForm with client-controlled isPreview: true.
  2. Missing guard. The application skips the captcha check, bypassing anti-automation.
  3. The race. The harness loops 76 requests to beat legitimate traffic during the 30–60 second cache TTL window.
  4. Impact. The Redis key is populated with the draft template, serving unapproved content to the public.

I rewrote the harness to model the race. It passed all five negative controls. It took exactly 38.0 seconds and 76 unauthenticated requests to flip the live public form to the unapproved draft. It was a beautiful, mathematically proven high-severity bug.

Elapsed time
38.0seconds
Unauthenticated requests
76requests
Negative controls passed
5controls

I submitted the report to HackerOne.

Duplicate

Another researcher had found the root parameter vulnerability 40 days prior.

06Final thoughts

The process was worth more.

Finding a vulnerability, understanding it, and successfully exploiting it with AI brings an incredible rush of dopamine. Hitting an “out of scope” wall or getting a “Duplicate” status is definitively the complete opposite. It’s gut-wrenching.

But it isn’t a total loss. The triager’s response made it sting a little less:

It was like putting a bandaid on a hole in my chest.

Getting scooped by 40 days hurts, but the methodology scales. If we hadn’t enforced strict dynamic controls, we would’ve reported an “arbitrary write” instead of a race condition and lost our credibility with the triage team.

Going forward, we are integrating this exact logic into Argus via an Offline Replay Simulator (based on the Dream-RSI paper). By scoring our AI’s exploration policies against historical logs of these exact false starts, dead ends, and race conditions, we can mathematically prove our automation is getting smarter without sending a single live packet.

A tool that confidently says “I don’t know” is infinitely more valuable than one that hands you a green checkmark based on a lie.

Vincent Suen

The process was worth way more than the actual CVE, and it has left me even hungrier for that first official payout.

Vincent Suen

Written by Vincent Suen

Field notes on AI-assisted pentesting · Entry 01