Skip to main content
Engagement composite · External network

An exposed secret is only a finding until something uses it

Retail e-commerce, tested from the outside. The perimeter was worked out from announced ranges rather than taken from the list that arrived at kick-off, and both of the things that carried the chain were found that way: a status route that answered without a session, and a release artefact published alongside its source map. What made this critical was not that a credential had been published. It was that the credential still worked, and that it worked somewhere the front end had no business reaching.

Sector
Retail e-commerce
Coverage class
External network
Delivery model
Fully autonomous

The chain, step by step

4 steps, and what each one handed to the next

Each row names the technique, the weakness it maps to and what the step yielded. A finding that hands nothing to the next step is a finding, and belongs in the report rather than here.

StepWhat it yieldedSeverity
01 · An endpoint that answered without a session The exact path of a named release artefact, retrievable by anybody, without a session. Medium
The external range was swept for what answers rather than for what was listed. A status route on the storefront edge returned build metadata to an unauthenticated request: the release identifier, the environment name, and the path the front-end bundle for that release was served from. — CWE-200, Exposure of sensitive information to an unauthorised actor.
02 · A secret inside the shipped artefact A credential, and the name of the one service the surrounding code used it against. High
That bundle had been published together with its source map, so the pre-minified modules were readable as they had been written. One of them assembled a configuration object at build time, and a credential sat in it as a literal string. — CWE-540, Inclusion of sensitive information in source code.
03 · The credential was valid past its intended boundary An authenticated session on an administrative interface, carrying write access to content the platform serves back. Critical
The same value was offered to a management interface answering on the same external range. It was accepted. The value had been reused rather than scoped to the service it was written for, so authentication succeeded in a place the front end was never meant to reach. — CWE-798, Use of hard-coded credentials.
04 · Write access became code execution Command execution in the context of the web tier. The end of the chain, and the point the run stopped at rather than continued from. Critical
An administrative upload accepted a file type the server would execute and stored it under a path the web tier serves. Requesting it back ran it. — CWE-434, Unrestricted upload of file with dangerous type.

01 · An endpoint that answered without a session

What it yielded
The exact path of a named release artefact, retrievable by anybody, without a session.
Severity
Medium

The external range was swept for what answers rather than for what was listed. A status route on the storefront edge returned build metadata to an unauthenticated request: the release identifier, the environment name, and the path the front-end bundle for that release was served from. — CWE-200, Exposure of sensitive information to an unauthorised actor.

02 · A secret inside the shipped artefact

What it yielded
A credential, and the name of the one service the surrounding code used it against.
Severity
High

That bundle had been published together with its source map, so the pre-minified modules were readable as they had been written. One of them assembled a configuration object at build time, and a credential sat in it as a literal string. — CWE-540, Inclusion of sensitive information in source code.

03 · The credential was valid past its intended boundary

What it yielded
An authenticated session on an administrative interface, carrying write access to content the platform serves back.
Severity
Critical

The same value was offered to a management interface answering on the same external range. It was accepted. The value had been reused rather than scoped to the service it was written for, so authentication succeeded in a place the front end was never meant to reach. — CWE-798, Use of hard-coded credentials.

04 · Write access became code execution

What it yielded
Command execution in the context of the web tier. The end of the chain, and the point the run stopped at rather than continued from.
Severity
Critical

An administrative upload accepted a file type the server would execute and stored it under a path the web tier serves. Requesting it back ran it. — CWE-434, Unrestricted upload of file with dangerous type.

Why this one is a chain

An exposure is not a finding until something uses it

Information exposure is the most common weakness behind the engagements these pages are built from, and most of the time it is written up, rated medium, and left there.

Every one of the four steps above is answerable with “so what”, and the rating moves each time the answer gets worse. A status route that returns build metadata is a medium on its own, because metadata is not content — which is exactly how a route like that survives review. A secret in a published artefact is a high, because the value is out and cannot be called back. Neither of those is what makes this page worth reading. The hinge is the third step: the value was offered somewhere it had no business being accepted, and it was accepted. That is the move between a medium-rated hygiene item and a critical one, and it is the move a check that only pattern-matches for secrets cannot make, because trying a credential is an action rather than an observation and an action needs authorisation behind it. That authorisation is what scope sign-off is for, and it is why the scope on this engagement was proposed back and agreed before anything was touched. The fourth step follows from the third with no cleverness at all: an administrative session with write access, an upload that accepts a file type the server executes, and a path the web tier serves it back from.

Three views of the same moment

What each hop looked like from either side of it

The same three moments, read as the tester met them, as the estate recorded them, and as they had been assumed to work.

01 Step 02

The artefact

What the tester did
Fetched the bundle named by the status route, then fetched the source map published beside it, and read the configuration object the map restored.
What the estate recorded
A request for a static file from an edge cache. No authentication event, because none was required, and nothing in the access log that distinguishes it from an ordinary page load.
What had been assumed
That the build step which minifies a bundle also drops its map, and that a value injected at build time is a different thing from a value written into source. Neither holds once the map ships.
02 Step 03

The credential

What the tester did
Offered the value unchanged to a different interface on the same range. Then offered it again with a single character altered.
What answered
The first attempt authenticated. The second was rejected. The rejection is what turns the first response into evidence rather than coincidence, and both exchanges are in the report.
What had been assumed
That the value was scoped to the one service it was labelled for, so publishing it was untidy rather than dangerous.
03 Step 04

The execution

What was written
A single file whose only behaviour was to return a marker string when it was requested.
What proved it ran
The marker came back in the response body, which is the whole proof and the whole point.
Where it stopped
Nothing was read, moved or persisted beyond that file. Its removal is recorded in the same finding, against the scope that authorised the upload in the first place.

The estate

A retail storefront, and the machinery that keeps changing it

Retail e-commerce, tested from the outside, with nothing deployed inside the network.

A retail storefront is not a fixed target. It ships often, and every release publishes fresh static artefacts to a public edge, tears down some names and stands up others. The perimeter that existed when a target list was last written down is not the perimeter that answers today, and the gap between those two is where this chain lived: neither the status route nor the management interface was on the list handed over at kick-off. External network testing is the class that treats that gap as the subject rather than as an inconvenience, and it runs entirely from the outside, against what the estate chooses to answer.

Scope, worked out rather than handed over

What the perimeter turned out to contain

Announced ranges, the names that resolve into them, and what actually answers. The result is proposed back as the scope and signed off before anything is tested.

What answeredWhy it stayed in scope
The storefront edge The obvious target, and the one already on the list that arrived at kick-off.
Everything below this row came out of discovery rather than out of the list, and all of it was proposed back for sign-off before it was touched.
A status route on that same edge Unauthenticated, and its response named a build. Metadata is not content, which is how a route like this survives a review that would have caught an exposed page.
A static artefact host Served the front-end bundle for each release, and the source map beside it, to anyone who asked.
A management interface on a non-standard port Answered from the public range and required only a credential. Not on the list, and reachable from anywhere.
A name from a retired release train Still resolving to a live address. Nobody owned it, which is the usual reason a name outlives the thing it pointed at.

The storefront edge

Why it stayed in scope
The obvious target, and the one already on the list that arrived at kick-off.

Everything below this row came out of discovery rather than out of the list, and all of it was proposed back for sign-off before it was touched.

A status route on that same edge

Why it stayed in scope
Unauthenticated, and its response named a build. Metadata is not content, which is how a route like this survives a review that would have caught an exposed page.

A static artefact host

Why it stayed in scope
Served the front-end bundle for each release, and the source map beside it, to anyone who asked.

A management interface on a non-standard port

Why it stayed in scope
Answered from the public range and required only a credential. Not on the list, and reachable from anywhere.

A name from a retired release train

Why it stayed in scope
Still resolving to a live address. Nobody owned it, which is the usual reason a name outlives the thing it pointed at.

Step by step

What each step left for whoever had to close it

The chain table names the technique. This one names what the report put in front of the engineer who had to fix it.

StepWhat the report carried
01 · Status route The unauthenticated request as sent and the whole response as returned, with the release path visible in it, beside the same request made against a route that did require a session — so the difference is shown rather than asserted.
02 · Source map The path the map was served from on assets.shop.example, the module the configuration object was restored into, and the retrieval repeated from a browser profile with no cache and no session.
03 · Credential accepted The authentication request and the response that accepted it, followed by the identical request with one character of the value altered and the rejection that came back. A match proved by contrast.
04 · Execution The upload request, the path the file landed on, the request that fetched it back, and the response carrying the marker it printed. The removal of that file is recorded in the same finding.

01 · Status route

What the report carried
The unauthenticated request as sent and the whole response as returned, with the release path visible in it, beside the same request made against a route that did require a session — so the difference is shown rather than asserted.

02 · Source map

What the report carried
The path the map was served from on assets.shop.example, the module the configuration object was restored into, and the retrieval repeated from a browser profile with no cache and no session.

03 · Credential accepted

What the report carried
The authentication request and the response that accepted it, followed by the identical request with one character of the value altered and the rejection that came back. A match proved by contrast.

04 · Execution

What the report carried
The upload request, the path the file landed on, the request that fetched it back, and the response carrying the marker it printed. The removal of that file is recorded in the same finding.

The order matters

Rotate first, then remove, then close the path

A remediation note that says the secret was taken out of the repository and stops there is giving bad advice. Removal changes nothing about a value that has already been served.

Delivery

Fully autonomous, and what that did and did not mean

Scope was signed off and nothing further was asked of the customer. What changes between the three models is whose signature the report carries, not which classes are covered.

Fully autonomous, and what that did and did not mean
StateWhat it meansWhat follows
Fully autonomous The model this engagement ran under. Scope sign-off, then discovery, the chain, the proof and the report without a further approval being asked for. The observed median turnaround on this model is one to three business days — a median taken from real runs rather than a service level, and no equivalent figure exists for the other two. No auditor signature.
Autonomous, expert verified The same run underneath, with a senior Security Brigade auditor verifying every finding before it reaches you. The eleven coverage classes are unchanged. Carries an empanelled auditor’s verification.
Human led Terminal A Security Brigade team works the engagement with the platform underneath it. The eleven classes again, and the same proof per finding. Carries an empanelled auditor’s verification.
Key
  • Report carries a senior Security Brigade auditor’s signature
  • Report carries the proof per finding, without an auditor signature
  • TerminalNo state follows this one

The figures on this page

What the platform itself was measured against

The chain above is the evidence for this engagement. The two figures on this page — a turnaround median and a coverage proportion — belong to the platform rather than to this engagement.

B-52 run in parallel with Security Brigade’s expert assessment team As of 2026-09-15
  • Both worked the same targets at the same time, and neither side saw the other’s output while the work was running.
  • The two sets of findings were pooled into one denominator with each item counted once, so a defect both sides reached counts once rather than twice.
  • B-52 reached 90–95% of that pooled set. Part of what it reached was absent from the team’s own output, which is why the pooled set is larger than either side produced alone.
  • Every engagement Security Brigade has run since the firm started in 2006 was worked inside Lemon, and that record is what trained the models the platform runs on.

Deliberately excluded

  • The 90–95% figure is a proportion of a pooled findings set, not a comparison of two products, and not a statement about any single engagement.
  • The median measures turnaround across runs and says nothing about how long any individual run took, this one included.
  • Physical, hardware and wireless testing, which are out of scope for B-52 in every class.

Work out what your perimeter answers, from $500

A scan is one application or one target, and the entry price is $500. A paid trial is $299. External network work starts with a scoping call, because the card flow reaches the five application classes; nothing is deployed inside your network either way, and the scope is proposed back to you before anything is touched.