Lenses
A lens is the perspective a round works from. It decides what the agent looks for when it annotates, and which identity the probes run as. bugb ships six, and rotates through them.
Six perspectives are not six times the work for its own sake. The same line of code is a different threat depending on who is standing in front of it, and a tool that only ever asks one of those questions returns a confident, partial answer.
The six
Section titled “The six”Read straight from the command’s own help:
--lens LENS perspective to annotate from (admin, chained, crosstenant, mitigation-audit, stduser, unauth)| Lens | Asks |
|---|---|
unauth |
what does an anonymous request reach? |
mitigation-audit |
do the declared controls actually hold? |
stduser |
what does an ordinary logged-in user reach? |
crosstenant |
what does one user reach of another’s? |
admin |
what does a privileged account reach, and should it? |
chained |
what becomes reachable once something else is proven? |
The order is a design decision
Section titled “The order is a design decision”Round 1 is always unauth. It needs no identities, so a broken environment
fails there — in the cheapest round — rather than three rounds in, after the
agent budget is spent.
mitigation-audit is scheduled second, and that is the choice worth explaining.
A single @mitigates removes every exposure sharing its asset/threat pair
from guardlink’s SARIF export. cxg never sees them, so no probe can be generated
for them, so nothing can ever confirm or refute them. A control that is 90%
correct is therefore more dangerous than no control at all: it silently ends the
investigation into everything it claims to cover.
The scale is not theoretical. On the reference repository:
SUPPRESSED FROM EXPORT (8) A @mitigates or @accepts anywhere in the repo removes every exposure sharing that pair from the SARIF export. cxg never sees these and cannot test them. critical app.benefits::missing-authz ×4 via @mitigates high app.memos::xss ×3 via @mitigates …Truncated — eight pairs, sixteen exposures, four of them critical.
mitigation-audit is the lens that restates those exposures into the export so
cxg can attack the control instead of assuming it. Asking “does the declared
control actually hold” is what has produced real findings that no other lens
could reach.
What a lens needs to mean anything
Section titled “What a lens needs to mean anything”crosstenant asks whether one user reaches another’s data. With one identity
captured, the question is unanswerable, and the round produces nothing: not a
refutation, and not a clean result either.
So the environment decides which lenses are real. Two equal-privilege identities plus one privileged identity is the shape most lenses assume; the environment guide captures them.
Rotation and retirement
Section titled “Rotation and retirement”A run records per-lens counters — attempts, uses, new exposures, confirmed findings, consecutive dry rounds, and whether the lens is retired, with a reason. A lens that stops producing is retired, and a run whose lenses are all retired has stopped for a stated reason rather than a budget one.
You can also pin one:
bugb annotate . --lens mitigation-auditbugb round . --lens crosstenant --target http://127.0.0.1:9054--focus narrows a lens further in your own words. Per its own help, it narrows
the lens and cannot relax the rules.
What it costs
Section titled “What it costs”- Every lens is another annotate phase, and annotation is an agent call against the whole repository.
- Lenses overlap.
stduserandcrosstenantwill both re-derive some of the same exposures; the ledger deduplicates the threats, not the work of finding them. - A lens can be wasted. A round under a lens whose identities are missing costs an agent call and returns nothing, and it will not tell you in advance.
Related
Section titled “Related”- The verification loop — where the rotation sits.
- Annotate a repository — running one lens by hand.
- Feeding findings into cxg — what the export drops, from guardlink’s side.

