Patched Twice, Bypassed Twice: A Case for Authentication Bypass Regression Testing

Authentication bypass regression testing is the practice of re-verifying, after every patch and every build, that a protected route still refuses an unauthenticated request. It tests behavior rather than version numbers, which matters because a patch can raise your version string without actually closing the path an attacker used.

That distinction stopped being academic in early August 2026, when the same product picked up two CISA Known Exploited Vulnerabilities entries for the same weakness, several days apart, because the first fix did not finish the job.

Key takeaways

  • N-able N-central received two KEV entries, CVE-2026-18556 and CVE-2026-18577, for authentication bypass using an alternate path or channel. The catalog description for the second states plainly that it is “the result of an incomplete patch” for the first.
  • The second bypass did not just restore the original impact. It escalated it, adding account takeover.
  • A CVE identifier and a patched version string are inventory facts. Neither is evidence that a protected route now requires a valid session.
  • The only thing that proves a bypass is closed is sending the request again, against the patched build, and watching what comes back.
  • Discovery is the precondition. An alternate path is by definition not the documented front door, so a test suite built from documentation will not exercise it.

One patch, then another bypass

The sequence, as recorded in public sources, is short and unpleasant.

CVE-2026-18556 describes N-able N-central as containing “an authentication bypass using an alternate path or channel that allows for authentication bypass.” CVE-2026-18577 describes the same product, the same weakness class, and then adds the part that makes this post worth writing: “authentication bypass and account takeover in N-central. This vulnerability is the result of an incomplete patch for CVE-2026-18556.”

Dark Reading reported active exploitation of the bypass on RMM servers on August 3, 2026, noting that the vendor discovered another vector over a weekend, one that hands attackers administrator access.

There is a detail in the CISA catalog worth pausing on. CVE-2026-18577, the follow-on, was added to KEV on August 3, 2026. CVE-2026-18556, the original it descends from, was added on August 4. The catalog order is the reverse of the causal order.

That is not a criticism of the catalog, which records when a vulnerability became a known exploited risk, not when the code changed. It is a small, concrete illustration of the whole problem: the metadata around a vulnerability follows its own timeline, driven by disclosure, reporting, and confirmation of exploitation. The behavior of your running application follows a completely different one. If you reconcile your security posture against the metadata, you are tracking the wrong clock.

What “alternate path or channel” actually means for an attacker

The weakness class here is CWE-288, authentication bypass using an alternate path or channel. The name is dry and the idea is not.

Most applications do not implement authentication once. They implement it on the path they expect traffic to arrive on: the login page posts to a handler, a session gets established, and a middleware layer checks that session on the routes that matter. That is the front door, and it usually works, because it is the path everyone tests, demos, and reasons about.

An alternate path is any other way to reach the same functionality. A legacy API version still mounted alongside the current one. An internal service endpoint that assumes the network already vouched for the caller. A route registered by a framework convention that nobody remembers writing. A header, parameter, or path prefix that causes the request to be handled before the check runs, or routed to a handler that was never wired to the check at all.

The attacker is not defeating your authentication. They are declining to participate in it, then asking the application for the thing behind it.

This is also why the fix is so easy to get partially right. If you patch the specific route or parameter in the reported proof of concept, you have closed the path the reporter walked. Whether you have closed the class of path depends on whether the check now sits somewhere that every route must pass through, and that is a much harder property to establish by reading a diff than by exercising the application.

We wrote about a closely related failure in our detection work on the Next.js middleware bypass, CVE-2025-29927. The pattern generalizes: when the authentication check lives in a layer that can be skipped, the interesting question is never “is the check correct,” it is “can I get to the handler without passing through it.”

Why a CVE number is not the same as a fixed behavior

Vulnerability management workflows are built to close tickets, and a CVE is an excellent ticket. It has an identifier, a severity, an affected version range, and a fixed version. Deploy the fixed version, mark it resolved, move on. The workflow is not wrong. It is just measuring something narrower than most teams think it is.

A version check proves that a particular build artifact is installed. It says nothing about whether the behavior that made the old artifact dangerous is still reachable in the new one. Those are usually the same thing. In the N-central chain, for several days, they were not.

Consider what each common verification method actually establishes.

Verification approachWhat it provesWhat it does not prove
Version or inventory check (SCA, patch management)The patched build is deployedThat the vulnerable behavior is gone
Vendor advisory and release notesThe vendor believes the issue is addressedThat the fix is complete for your configuration
Re-running the published proof of conceptThat one specific request is now refusedThat a variant of it is also refused
Behavioral re-test across the discovered route surfaceThat protected routes refuse unauthenticated requests, on this buildThat no logic flaw exists behind a route that correctly requires a session

None of these is worthless. Inventory data is how you know a patch is deployed at all, and re-running a proof of concept is a fast, high-value first check. The point is narrower: every row above the last one asks a question about artifacts and intentions, and only the last row asks the application. The incomplete-patch case is exactly where the first three agree with each other and are wrong together. The version is current. The advisory says fixed. The published proof of concept fails. And the alternate path is still open, because it is a different alternate path.

Testing the auth flow, not the version string

If the goal is to catch an incomplete authentication fix, the test has to have three properties, and most testing setups have one or two.

It has to know the route exists. This is the one that quietly disqualifies most suites. A test derived from an OpenAPI document, a Postman collection, or recorded production traffic can only cover what those artifacts describe. An alternate path is, by construction, the route that is not in the documentation. If your inventory of endpoints comes from a document a human maintains, your coverage of undocumented routes is whatever that human happened to remember.

It has to actually be unauthenticated. Testing that a protected route rejects a request requires sending a request with no valid session, from a client that is not silently carrying a cookie, a bearer token, or a header injected by a proxy. This sounds trivial and is a common source of false confidence, because a scanner or test harness configured with credentials will happily use them everywhere.

It has to run again after the fix. A test that runs during a release cycle and not after the hotfix proves the state of a build that is no longer deployed. Incomplete patches are shipped under time pressure, out of band, which is exactly when the normal pipeline gets skipped.

There is a fourth property that is not about detection but about trust: the result has to be reproducible. A finding that says “authentication bypass detected” with no request and response attached will be argued with, and the argument will take longer than the fix.

What authentication bypass regression testing looks like in CI

The practical shape of this is less dramatic than the CVE chain that motivates it, and it splits into two halves worth keeping separate: the surface you test against, and the assertion you make about it. Tooling is good at the first. The second is mostly yours.

Rebuild the route inventory on every run rather than maintaining it by hand. Deriving the API surface from application source, before any request is sent, means the routes the code defines land on the list whether or not anyone documented them. NightVision does this from the repository for REST APIs across Python, JavaScript and TypeScript, Java, C#, Ruby on Rails, PHP, and Go (experimental). It is the same mechanism that makes undocumented routes visible in the first place, which is covered in shadow API discovery.

Scan fully authenticated, and fail loudly when authentication itself breaks. NightVision drives real Playwright-scripted logins, including TOTP and MFA flows, with vaulted credentials, and the --login-check CI gate exits nonzero when the login fails. A scan that silently degrades to unauthenticated crawling is worse than no scan, because it reports a clean result for a surface it never reached. That failure mode has its own post: your scan passed because it never logged in.

Re-run on the build that contains the fix, through the pipeline you already have. NightVision integrates with GitHub, GitLab, Jenkins, Azure DevOps, and Bitbucket, and every finding carries the full request and response that produced it, so the verification is reproducible by whoever is skeptical of it.

Where the tooling stops and you start

Now the part most vendor posts skip, because it is the part where the honest answer is “not automatically.”

For a known bypass in third-party software, this is largely a solved problem. A published CVE with an understood signature becomes a detection template, and from then on it runs on every scan without anyone having to remember it. NightVision ships Nuclei templates for known CVEs, and wrote one for the Next.js middleware bypass, using directory bruteforcing to locate protected endpoints and a two-stage check to hold false positives down. If your exposure is a vendor product on a version you can identify, that is the path, and it is the one that would eventually cover something like the N-central chain once a signature exists.

For your own application, it is a different problem, and no scanner should pretend otherwise. Whether a route is supposed to require a session is not a property that can be inferred from the outside. A route that returns 200 to an anonymous request is a critical finding on a billing API and correct behavior on a health check, and nothing in the response tells the two apart. The assertion has to come from someone who knows what the route is for.

So the durable version of this practice is a division of labor. Let discovery keep the route list honest and current, decide which of those routes are supposed to be protected, and then encode that decision as a check that runs on every build. NightVision hosts custom Nuclei templates for exactly this, uploaded and assigned to targets so they execute inside the normal scan rather than as a side project. The platform supplies the surface, the schedule, and the evidence. You supply the assertion once, and it outlives both the incident that prompted it and the engineer who was on call for it. That is also why it survives a refactor, where a check that merely replays last quarter's proof of concept does not.

The same boundary shows up one level in. Discovery can hand you a current list of the doors your application answers on. Which authenticated user should be allowed through which one is a policy question your team owns, and it is the subject of authentication is not authorization.

Learn more

Where dynamic testing, source-based discovery, and the rest of the application security testing landscape fit together: API and Application Security Testing, explained.

Frequently asked questions

What is authentication bypass regression testing?

It is the practice of re-testing, after every patch and every build, that protected routes still refuse requests without a valid session. It verifies behavior against the running application rather than confirming a version number in an inventory system.

Why did N-able N-central get two CVEs for the same issue?

CVE-2026-18577 exists because the patch for CVE-2026-18556 was incomplete. The CISA KEV description for the second entry states directly that it “is the result of an incomplete patch” for the first, and the second added account takeover to the original bypass impact.

Does deploying the patched version prove the vulnerability is fixed?

It proves the patched build is installed. Whether the vulnerable behavior is still reachable is a separate question that only a test against the running application can answer. In an incomplete-patch scenario those two answers diverge, which is what makes the scenario dangerous.

What does “authentication bypass using an alternate path or channel” mean?

It is CWE-288. The attacker does not defeat the login. They reach the protected functionality by a route that never passes through the authentication check, such as a legacy API version, an internal endpoint, or a framework-registered route that the check was never wired to.

Why does undocumented endpoint discovery matter for authentication bypass?

An alternate path is by definition not the documented front door. Test suites built from an OpenAPI spec, a Postman collection, or recorded traffic only cover what those artifacts describe, so the routes most likely to carry a bypass are the ones least likely to be tested.

Can a scanner detect an authentication bypass automatically?

For a known CVE in third-party software, yes, once a detection template exists for that specific signature. For a bypass in your own application, no. Whether a given route is supposed to require a session is application-specific intent, and a 200 response to an anonymous request is a critical finding on one route and correct behavior on another. A scanner can supply the route inventory, the schedule, and the evidence. The assertion about which routes must be protected has to be written by someone who knows the application.

Ask the application, not the changelog

The N-central chain is not a story about a vendor that shipped a bad patch. Every vendor ships an incomplete fix eventually, including the ones reading this. It is a story about the gap between a CVE being marked resolved and the behavior actually being closed, and about how long that gap can stay open while every dashboard shows green.

Close it by asking the application, on every build, including the build right after the fix.

Know the surface before you test it.

Start free, or book a demo to see NightVision discover your API from source and test it fully authenticated against the endpoints your application really answers.