We were given a list of hostnames and five days. No credentials, no source, no diagrams. Before the week was out, the client's engineers were closing authorization paths we had already proven reachable from the open internet.
A venture-backed company building a generative-AI product on modern cloud infrastructure. The API surface had grown faster than security review could cover it, and enterprise buyers were asking posture questions the team could not yet answer with evidence. The client wanted an adversarial answer before onboarding larger customers.
The brief was deliberately constrained: black-box, unauthenticated, external only. No credentials, no source, no architecture diagrams, no allow-listing of our testing origin. We started from exactly what an internet-based attacker starts from — a set of in-scope hostnames.
That constraint is the point. An assessment that begins with a diagram tests the architecture as documented. An assessment that begins with a hostname tests the architecture as deployed. The gap between those two is where real exposure lives — and it is the only gap an attacker ever sees.
Every piece of context had to be earned from the outside: which hosts existed, which applications sat behind them, and which endpoints were real rather than inferred. Discovery was not a preliminary step — it was a continuous one, feeding new targets into testing until the final day.
Multiple applications sat behind a single application load balancer. Host-based routing fabric is frequently where authorization assumptions quietly break down: a control enforced for one virtual host is often absent on a sibling that reaches the same backend.
Endpoints had shipped ahead of security review, and no reliable inventory existed of what was externally reachable. Before anything could be tested, the real request surface had to be reconstructed from client-side assets and observed behaviour.
The central question for any fast-scaling platform: does the backend enforce identity, or does it rely on a front-end control that an attacker never has to traverse? This is the assumption an attacker tests first, and it cannot be answered from a configuration review.
Coverage had to be bought with prioritisation rather than hours. Enumeration breadth was spent where trust boundaries actually existed, and candidate findings were triaged by potential impact before any time was invested in proving them.
We distinguish configuration (what a setting permits) from reachability (what answered from our position) from exploitability (what we demonstrably did) — and we report every finding at the highest level we actually reached, never one above it.
Proxy-driven manual testing is the core of the engagement. Automation is used to widen coverage, never to conclude findings — reconnaissance tooling and configuration scanners produce candidates, and every candidate is reproduced by hand before it reaches the report.
| Stage | What Happens | Tooling Class | Exit Criteria |
|---|---|---|---|
| Candidate generation | Perimeter enumeration and configuration review at breadth | Recon, subdomain and TLS/configuration scanners | Candidate queued — never reported |
| Manual verification | Request manipulation against the suspected trust boundary | Intercepting proxy with repeater/intruder-style tooling | Reproduced by hand, or discarded |
| Out-of-band confirmation | Blind classes proven by observed callback from the target | Controlled OOB interaction collaborator | Callback observed and logged |
| Evidence capture | Exact request/response pair preserved for client replay | Proxy history and engagement notes | Engineer can replay it unaided |
| Severity assignment | Impact rated in the client's environment, compensating controls accounted for | Contextual rating, cross-checked against public CVSS | Rating and rationale both stated |
A candidate that cannot be reproduced by hand does not become a finding. It is either recorded as a genuine untested possibility with a concrete verification step, or discarded. Scanner output is never passed through to a client as a result.
What distinguishes the deliverable is restraint in the wording. A report that overstates one finding costs the client trust in all of them — and sends engineering time at the wrong problem. These are the distinctions we hold to.
| Observation | How We Report It | How We Refuse To Report It |
|---|---|---|
| Version banner in an affected range | Candidate CVE — to be verified, with affected range and fixed version | “Vulnerable to CVE-XXXX” |
| Public address, filtered port | Defence-in-depth / configuration finding | “Publicly accessible” |
| A control that looks weak but was never tested | Genuine untested possibility, with a concrete “to verify” step | “Exploitable” |
| An action we performed and can prove | Exploited / bypassed / accessed, with the request/response pair | Any of those words without the proof attached |
| Our rating differs from public CVSS | Contextual severity with compensating controls, and the reason stated | Scanner severity, passed straight through |
A version banner in an affected range stays out of the confirmed set until the code path is reproduced. A host with a public address but a filtered port is explicitly not described as publicly accessible, because nothing answered from the internet. Severity reflects demonstrated impact in the client's environment — and where our contextual rating differs from a public CVSS, we say why.
Mapped to the OWASP API Security Top 10 and reported at the exact level proven. Each item shipped with its reproduction steps, the trust boundary it crossed, and a contextual severity — so the client could prioritise by genuine exposure rather than by scanner alarm.
Customer-facing endpoints served backend functionality to unauthenticated requests they should have rejected. The front-end control existed. The backend did not enforce it — and the backend is the only thing an attacker ever talks to.
Application behaviour inducible to reach systems it was never intended to. One public request crossed into infrastructure built on the assumption that only internal callers could ever reach it — the assumption most internal services are secured by.
Internal configuration and operational detail reachable from outside the perimeter without credentials — material that shortens the path for any subsequent attacker, even where it is not directly exploitable.
Remediation started during the engagement, not after it. Because confirmed findings shipped on a daily cadence rather than in a report at the end, engineering began closing the highest-impact authorization and SSRF paths while we were still testing.
What they were left with is a findings set reproducible line-by-line, each tagged with an impact-based severity and a remediation order driven by real risk rather than scanner ranking. Nothing to argue about: every claim came with the request that proves it.
“A precise, adversarial picture of what an unauthenticated attacker could and could not do — stated no stronger, and no weaker, than the evidence supports.”
For AI and platform companies scaling quickly, the API layer is the attack surface — and “we put auth in the front end” is exactly the assumption an attacker tests first.
JSN Cloud delivers assessments that survive an engineer's own reproduction: every claim backed by a request they can replay. Teams fix what is real, and leadership can speak to posture with precision.
Find out what an unauthenticated attacker can actually reach — and get findings your own engineers can reproduce before they start fixing them.
Engagement details, client identity, and technical specifics are withheld under confidentiality. This case study describes our methodology and the classes of risk addressed.