July 29, 2026
How I Found a HIGH-Severity AI Security Issue on Khan Academy’s VDP
My first HackerOne report landed as a HIGH-severity information disclosure on a major education platform. Here’s exactly what I found, how…
By Galeops
4 min read
My first HackerOne report landed as a HIGH-severity information disclosure on a major education platform. Here's exactly what I found, how I found it, and what it means if you're shipping AI to production.
By Matt Gale (ghostinthecode) · Originally published June 29, 2026
On June 29, 2026, I submitted my first HackerOne vulnerability disclosure report — and it landed in triage at HIGH severity(7–8.9) for Khan Academy's public VDP program.
The vulnerability class? Information disclosure via a feature-flag leak. The kind of thing that tells an attacker exactly which AI features are live on production — and which are in the canary bucket ready to be enabled with a single config change.
This post is the full breakdown: methodology, the recon chain, the exact bug, and 7 other findings I bundled into the same report.
The Methodology (Why This Worked)
Public AI security bug bounty work is different from traditional security research. You're not breaking in — you're finding what the company already leaked about its own AI stack, often by accident. The best AI security researchers I know spend roughly 70% of their time on passive reconnaissance, and that's really the whole lesson of this post.
Step 1: Subdomain Enumeration (Passive, No Alerts)
I started with a passive scan — no clicks, no probes, no Nikto. Just DNS:
# Find subdomains fast (no detection)
subfinder -d khanacademy.org -silent -o subs.txt
# Result: 144 subdomains# Find subdomains fast (no detection)
subfinder -d khanacademy.org -silent -o subs.txt
# Result: 144 subdomainsSubfinder pulls from Certificate Transparency logs, DNS datasets, and search engines. It's all public data — the target never sees you.
Step 2: Live Host Probe (Still Passive)
Next, I checked which of those subdomains were actually serving HTTP:
# Which are actually serving HTTP?
cat subs.txt | httpx -status-code -title -tech-detect -silent
# Result: 100+ hosts responding# Which are actually serving HTTP?
cat subs.txt | httpx -status-code -title -tech-detect -silent
# Result: 100+ hosts respondingThis is where most people stop. They end up with hundreds of live URLs and start clicking around hoping something looks interesting.
I don't. I move to step 3.
Step 3: Pattern Recognition (The Actual Game)
Here's the thing nobody tells you about AI security research: the bugs usually aren't subtle. Once you've looked at 10 different AI agents built by 10 different companies, you start recognizing the same architectural patterns over and over. And patterns leak metadata.
Here's the pattern I look for on every AI-enabled site: does it load any JavaScript that references model identifiers, version flags, canary deployments, A/B test buckets, or feature flags? If yes, that's the entry point.
Khan Academy's frontend loaded JavaScript with a feature flag initialization table, and one of those flags was set to true for an internal beta cohort.
The Bug
What I Found
Khan Academy's main web app uses LaunchDarkly (or a similar service) for feature flagging. The flag initialization payload loads on every page render, and it includes all flags — including ones users shouldn't have visibility into.
One of those flags was named ai-tutor-feature-enabled (details redacted per coordinated disclosure). Its value was false for me, but the flag's mere existence told me two critical things:
- An "AI tutor rewrite" was being A/B tested in production.
- The flag had a default-off state, with a known target cohort.
That let me design a targeted attack. If I could find the cohort identifier (which came from a separate subdomain's analytics payload), I could self-select into the experimental AI tutor — bypassing whatever guardrails were being tested.
The Severity (Why HIGH)
CVSS 7.0–8.9, for these reasons:
- Confidentiality Impact: HIGH — exposed unreleased AI product behavior to attackers
- Integrity Impact: HIGH — an attacker can opt into A/B cohorts to bypass safety reviews
- Availability Impact: LOW
- Attack Complexity: LOW (no special access needed, just public JS bundles)
The underlying principle: a feature flag isn't just a config value. It's a map of what's coming next — and once an attacker has that map, the rest is just game theory.
Why This Is Widespread
If you've shipped an AI agent in the last 18 months, there's a good chance you have this exact issue. The pattern is universal: frontend frameworks load their initialization payloads before the user's session is even validated. Those flags are usually meant to be client-visible — but almost no one audits what they're actually exposing.
The 7 Other Findings I Bundled
Once you find one issue like this, the rest tend to cascade. Here's what else ended up in the report, ranked by severity:
- HIGH — Info Disclosure: Feature flag disclosure (the finding above)
- LOW — Info Disclosure: Internal cohort identifiers leaked via subdomain JS
- LOW — Info Disclosure: Server version exposed in HTTP headers
- LOW — Info Disclosure: Build commit hashes exposed in static assets
- LOW — Misconfiguration: Staging subdomain publicly accessible
- LOW — Info Disclosure: Internal API endpoints discoverable via subdomain crawl
- INFO — Info Disclosure: DNS zone walking possible (subdomain enumeration)
- INFO — Info Disclosure: Email pattern verified via newsletter signup
I bundled all of them into a single report because Khan Academy's triage team is one of the best I've dealt with — they prefer the full picture over receiving eight separate tickets.
The Recon Stack That Made This Possible
None of this is advanced work. It's all free, all scripted, and it runs in about 20 minutes:
# Full chain (Kali Linux, all free)
subfinder -d target.com -silent -o subs.txt
cat subs.txt | httpx -status-code -title -tech-detect -silent -o live.txt
cat live.txt | nuclei -severity info,low,medium -silent
# Then: 30 minutes of reading the live responses
# Looking for:
# - Feature flag names (LD, Optimizely, Split.io, GrowthBook)
# - Build info (commit hashes, version strings)
# - Cohort identifiers (analytics cookies)
# - Staging environment hints (dev/staging/qa subdomains)# Full chain (Kali Linux, all free)
subfinder -d target.com -silent -o subs.txt
cat subs.txt | httpx -status-code -title -tech-detect -silent -o live.txt
cat live.txt | nuclei -severity info,low,medium -silent
# Then: 30 minutes of reading the live responses
# Looking for:
# - Feature flag names (LD, Optimizely, Split.io, GrowthBook)
# - Build info (commit hashes, version strings)
# - Cohort identifiers (analytics cookies)
# - Staging environment hints (dev/staging/qa subdomains)What This Means for You
If you're shipping an AI agent, here are three things worth checking today:
- Inspect your production JavaScript bundles for feature flag payloads. Whatever service you use, you're probably initializing all flag values client-side — including the ones that should be server-side or admin-only.
- Verify your staging and internal environments don't have public DNS. Staging gets forgotten, and forgotten subdomains are gold for attackers.
- Audit your AI version exposure. If someone can grep your JS for "gpt-4" versus "gpt-5-turbo" versus "claude-opus-4," they know exactly which model generation you're running.
Want Me to Run This Against Your AI Agent?
Here's the thing: this took about 20 minutes of recon and 40 minutes of pattern recognition. I do this for a living.
If you want to know whether your AI agent is leaking metadata the same way Khan Academy's was, I built a couple of tools for that: the free AI Prompt Tester, and the AI Security Quiz.
Book a Free 15-Min AI Security Audit
We'll run the same recon chain against your AI agent in real time. If we find a HIGH-severity issue, you'll know you need a paid audit. If we don't, you still get a 15-minute consult for free. Schedule the call here.
Originally published on GaleOps: https://galeops.xyz/blog/khan-academy-vdp-report/