Security Testing Every Release Without a Manual Bottleneck

Security review is often the last step in a release pipeline that still waits for a person. Builds run themselves. Tests run themselves. Deployments run themselves. Then a change touching authentication, tenant boundaries or billing reaches a queue, and it sits there until someone with the right context has time to read it.
That queue is usually described as a security problem. It is closer to a capacity problem, and the distinction matters because the two have different fixes.
Where the bottleneck actually sits
The size of the security team is one of the things that produces the queue. When the number of changes requiring review grows faster than the team's review capacity, work starts to wait.
The consequences tend to arrive in one of two shapes. Either changes wait, and delivery slows in a way engineering feels every sprint, or the gate gets routed around: changes get classified as low risk to avoid the queue, and the ones that genuinely touch an authorisation boundary go out with the same scrutiny as a copy change.
Neither shape is a security control. A gate that people learn to avoid is worse than a slower gate, because it produces the appearance of review without the substance of it.
The useful question is therefore not how to review faster. It is which parts of the review genuinely need a person, and which parts are being done by a person only because nothing else was doing them.
What the pipeline already covers
A modern CI pipeline is not empty on security. Dependency scanning flags known vulnerable packages. Secret scanning looks for committed credentials and other sensitive information. Static analysis flags injection-shaped patterns, unsafe deserialisation and a long list of known-bad constructs.
These are real controls and they run without anyone waiting. They also share a property worth naming: they compare your code against patterns known in advance. A dependency scanner knows a CVE exists. A static analyser knows what a SQL string concatenation looks like.
What generic scanning does not reliably hold is your application's full intent. A tool may be able to recognise some authorisation checks, but it generally cannot infer from generic patterns that an endpoint is supposed to be reachable only by an account administrator, because that rule comes from the application's design and business requirements. The gap between pattern matching and exploitability is covered in more detail in what static analysis can reach.
So the pipeline covers classes that can be described and checked automatically, while the queue remains for the cases where automation cannot provide enough confidence or context on its own.
The two questions a release actually raises
Once you separate them, a release raises two different security questions, and conflating them is part of why the queue never clears.
The first is about the change itself. Does this diff introduce a way for one tenant to reach another tenant's data, for a lower-privileged role to perform a higher-privileged action, or for a billing path to be walked out of order? That question is scoped to what changed, and it can often be assessed from the diff plus enough repository context to understand what the surrounding code expects.
The second is about the application as a whole. Given everything that has shipped, is there now a reachable path through the running system that nobody intended? That question is not answerable from a diff, because the interesting failures are often combinations: a route added in March, a role added in June, and a check that was correct when it was written.
Borg splits these deliberately. Gungnir reviews the pull request diff with repository context and posts inline comments carrying severity and a suggested fix, before the change reaches production. Mjolnir tests the full application, reading source code, mapping the attack surface, generating test cases and executing them against the running system. The distinction, and when each one answers your question, is set out in full pentest versus PR security review.
The reason this matters for the bottleneck is that the first question is the one naturally suited to a merge-time check. The second can run on its own schedule without making every merge wait for a full application test.
What can run without a person on every merge
The per-change review is the part that can move into the pipeline, because it has a defined scope and a defined trigger.
Gungnir runs as a GitHub check on pull requests. It reads the diff together with repository context rather than the diff alone, which is what lets it reason about whether a changed authorisation check is consistent with how the rest of the application enforces that boundary. Findings come back as inline comments on the pull request itself, with severity and a suggested fix, so the feedback arrives where the change is being discussed rather than in a separate tool. The check can block a merge, which means the gate still exists; what changes is that the gate no longer waits on a person's calendar.
That last point is the whole mechanism. The bottleneck was never the existence of a gate. It was that the gate's throughput was bounded by how many diffs the available security reviewers could assess in a day.
The application-wide question runs on its own cadence. Mjolnir can be run manually or on a schedule, returning verified findings with reproduction steps rather than relying solely on a list of candidates for an engineer to investigate. Findings land in Odin and can flow into Linear, Jira or GitHub as tickets, which is covered in how findings reach your tracker. When a fix merges, automatic retests review the merged change and update the finding's state, so the loop closes without a manual re-check.
None of that removes the security engineer. It changes what reaches them.
What still needs a person
This is the part a vendor is tempted to skip, and skipping it is how you end up with a security programme that quietly stops working.
Threat modelling for a genuinely new surface still benefits from human judgement. When your team introduces a new tenancy model, a new payment flow or a first-of-kind integration, the question of what an attacker would want and which boundaries now matter is a design question. Automated testing can probe a boundary once it exists; it is much weaker at deciding which boundary the design should have drawn.
Judgement on severity in context still needs a person. A verified finding tells you a path is reachable. Whether that path matters more than the other twelve things on the roadmap this quarter depends on what the data is, who your customers are and what your obligations to them look like. That is a business decision wearing a technical costume.
Anything genuinely novel still needs a person. Borg's own Embedded Research Service exists for cases where longer-term offensive-security expertise is needed, operating as an extension of the client's team rather than providing only routine automated coverage.
And review of the automation itself still needs a person. A check that runs on every pull request is a control like any other, and controls drift. Someone should periodically ask whether it is still firing on the paths that matter.
The realistic version of the pitch is not that the human disappears. It is that the human spends less time on diffs a machine can evaluate, and more time on the questions that require human judgement.
Why "verified" is the load-bearing word
The queue is not only made of reading time. A large part of it is triage: deciding which of the things a tool flagged are real.
That is why the distinction between a candidate and a verified finding matters more here than it looks. A candidate says something in the code resembles a known-bad pattern, and a person has to establish whether it is reachable and whether it matters. In this context, a verified finding should mean that the system has attempted to validate the suspected weakness and observed evidence supporting the result, with enough detail to reproduce it. The first still requires an engineer to establish whether the issue is real and relevant. The second removes much of that investigative work, leaving the engineer primarily to assess impact and fix it.
This is also the sharpest published objection to the whole autonomous category, and it is worth stating rather than dodging. HackerOne's own January 2026 announcement of agentic PTaaS argued that fully autonomous testing tends to deliver "shallow, unverified results that create noise rather than insight". That is a fair challenge, and the answer to it is not a confidence score. The answer to it is whether the output includes the attempted action and its result, with enough evidence for an engineer to reproduce or independently validate the finding.
Judge any per-release security tooling on that basis. If its output is a list you still have to investigate, it may have moved the bottleneck rather than removed it: the review queue becomes a triage queue, and a substantial part of the human workload remains. If its output is a reachable path with reproduction steps, the engineer's next action is a fix rather than an investigation, and that is the step that actually returns capacity to the team.
It is worth being clear about the limit of that claim. Verification tells you a path was reachable at the moment it was tested. It does not promise that everything unreported is safe, and no honest reading of a finding count supports that inference.
Comparing the approaches
| Approach | Runs without waiting | What it answers well | Where it falls short |
|---|---|---|---|
| Dependency and secret scanning | Yes, per commit | Known vulnerable packages, committed credentials | Says nothing about your own logic or authorisation rules |
| Static analysis | Yes, per commit | Injection-shaped patterns and known-bad constructs | Has limited visibility into application intent, so some authorisation and business-logic failures remain outside generic rules and findings still require triage |
| Manual AppSec review of each PR | No, bounded by team capacity | Deep context, novel designs, judgement on what matters | Throughput is constrained by reviewer capacity, which can create queues and incentives to route around the review |
| Periodic penetration test | No, scheduled and point-in-time | Whole-application view, multi-step and creative attack paths | Point-in-time coverage becomes less representative as the application changes, and the report describes the system as it existed during the assessment |
| Code-aware PR review (Gungnir) | Yes, per pull request | Whether this diff introduces a reachable authorisation, tenancy or logic failure | Scoped to the change plus repository context, so it is not a substitute for whole-application testing, and it needs the repository connected |
| Continuous application testing (Mjolnir) | Yes, on a schedule | Reachable paths across the whole running application, with reproduction steps | Runs on its cadence rather than per merge, so it is not the thing that gates a single change |
The table is worth reading as a set rather than a ranking. Every row has something the others do not, and the rows that run without waiting are not automatically the better ones. They are the ones that can be applied repeatedly and at a scale that would be difficult to match with manual review alone.
Where to start if the queue is the constraint
If the review queue is the thing actually slowing releases, the order that tends to help is narrower than a full programme.
Start by identifying which changes are currently gated on a human and why. In many teams, the gate is triggered by a path or label rather than by an assessment of what the change actually does, which can put changes that never needed offensive review into the queue.
Then put automated per-change review on the paths that genuinely carry authorisation, tenancy, billing or permissions logic. Connecting the repository is the prerequisite here; a diff-scoped review cannot reason about repository context it cannot read.
Then let the whole-application testing run on a schedule rather than trying to attach it to a release. It answers a different question and attaching it to a merge gate would recreate the bottleneck in a new place.
Finally, decide deliberately what the security engineer now owns. If that step is skipped, the freed capacity tends to be absorbed rather than redirected, and the programme ends up faster without being better.
What this does not solve
Moving suitable parts of offensive review into the pipeline can improve review throughput. It does not make your authorisation model correct, and it does not tell you which risks your business should accept.
It also depends on the reviews being trustworthy enough to act on. A per-merge check that produces too much noise is likely to be muted or bypassed, which can undermine the control by teaching engineers to ignore its output. That is the standard by which any per-change security review should be judged: not how much it flags, but whether an engineer reading its output changes what they ship.
Frequently asked questions
- Can security testing run on every release without a human reviewing each change?
- Partly, and the split matters. The per-change question, whether this diff introduces a reachable authorisation, tenancy or logic failure, can run as an automated check on the pull request itself, because it has a defined scope and a defined trigger. The whole-application question, whether anything shipped so far has opened a path nobody intended, is not answerable from a diff and generally runs on its own schedule. Design work, severity judgement in business context and genuinely novel surfaces still need a person.
- Why does a security review queue slow releases down?
- Throughput, not necessarily difficulty. Once the number of changes requiring review exceeds the available review capacity, work either waits or the gate can be quietly avoided by labelling changes as low risk. The second outcome is the more damaging one, because the programme can keep reporting that reviews happened while the control is being bypassed. Fixing it means asking which parts of the review genuinely require judgement and which were only ever done by hand because nothing else was doing them.
- What does a code-aware pull request review check that a static analyser does not?
- Intent and exploitability, within the scope of the change. Pattern-based tooling is good at flagging things like unsafe deserialisation or injection-shaped queries, but generic rules do not reliably capture the full set of application-specific security requirements. A tool may recognise some authorisation checks, but it generally cannot infer from a generic pattern that an endpoint is supposed to be reachable only by an account administrator because that rule comes from the application's design and business requirements. Reading the change alongside the surrounding repository provides additional context for asking whether a modified permission check still matches how the rest of the codebase enforces that boundary.
- What is the difference between a candidate and a verified finding?
- Effort transferred to the reader. Flagging something as suspicious leaves an engineer to work out whether it can actually be triggered and whether triggering it would matter. A verified finding should provide evidence that the suspected weakness was tested, together with enough detail to reproduce or independently validate the result. That removes much of the investigative work, but not the engineer's responsibility for assessing impact and deciding how to fix it. The limit matters as well: a successful test proves that the tested path was reachable at the moment it was tested; it does not establish that everything the system did not test is safe.
- Does automating per-change review remove the need for a security engineer?
- No. It changes what reaches them. Threat modelling for a new tenancy model or payment flow is a design question, severity in context is a business decision, and the automation itself is a control that can drift and should be reviewed periodically. The realistic claim is that the engineer spends less time on diffs a machine can evaluate and more time on the questions that require human judgement.



