ALB listener rule order can skip auth

When a broad rule wins before the protected path

A rule with priority 10 is evaluated before one with priority 20. That sounds boring until the broad rule forwards traffic straight to the application and the narrower rule with authenticate-oidc never runs.

A common failure looks like this:

  • priority 10: path /* forwards to tg-app
  • priority 20: path /admin* runs authenticate-oidc and forwards to tg-app

The /admin rule is there, but it never gets matched if the wildcard rule catches the request first. The result is a protected path that is only protected in theory. The listener still looks tidy in the console, which is part of the problem.

The same mistake shows up with host headers, custom headers, or a rule that is just too broad. If a rule matches the unauthenticated request shape, the auth action is skipped and the request goes on its way.

Priority 10 shadows the authenticate-oidc rule

Listener rule priority is not decoration. Lower numbers win, full stop. If the broad forwarding rule sits above the auth rule, the auth rule is dead code for that request path.

The fix is to make the protected match the earliest one that can catch it. That means the restrictive rule must sit above any catch-all, not underneath it. If the route to tg-app is shared, the auth action has to be on the rule that actually fires.

Match the exact request shape that bypasses auth

Bypass tests should use the exact shape the load balancer sees. That means the ALB DNS name, the right host header if one is used, and the path that slips past the intended rule. A path like /* is rarely the problem by itself. The problem is that it catches more than the protected route.

Do not assume a protected URL is safe because a matching rule exists somewhere lower down the list. The request has to hit that rule first. If it does not, the auth action never fires.

Hardening the routing graph, not just the listener

The listener page is only one entry point. The actual control surface is the routing graph around it, including any other way to reach the same target groups or backend instances. If the app is reachable through more than one path, one locked-down rule does not buy much.

Direct access to an internet-facing origin ALB behind CloudFront is a classic way to side-step front-door controls. WAF rules on CloudFront do nothing if the ALB DNS name is still reachable. The same applies to sibling load balancers in the same VPC, a different port on the same ALB, or an NLB pointing at the same instances.

Check direct ALB access, alternate ports, and sibling load balancers

Test HTTP and HTTPS directly against the ALB DNS name. Then check any alternate listener ports and any other load balancers that register the same target groups or instances. If one path expects auth and another does not, the weaker path becomes the real front door.

This is where source restrictions fall apart as well. A source-ip condition on one listener rule only protects that rule. If the same target group is reachable somewhere else, the restriction does not follow the traffic.

Treat source-ip conditions and X-Forwarded-For as separate controls

source-ip conditions act on the address the load balancer sees. X-Forwarded-For is just a header unless the downstream service makes trust decisions from it. Those two things are not interchangeable.

If routing.http.xff_header_processing.mode is set to preserve, the backend may see a chain of client and proxy addresses. A service that trusts X-Forwarded-For without a strict proxy boundary can end up making access decisions on something the client can influence. That gets messy fast, and messy access control is still access control.

Proving the gap is closed

Closing this kind of bypass needs tests, not hope. A clean console config tells you very little if the unauthenticated route still reaches the target group by another path.

Test the unauthenticated path against the ALB DNS name

Hit the ALB directly without credentials and without the CloudFront layer in front of it. Use the exact host, path, and port that would trigger the bypass if the rule order is wrong. If the request reaches the backend or returns application content, the auth boundary is still open.

Test both the obvious route and the awkward one. A protected /admin path can still be exposed by a broad /* rule, and a supposedly internal API can still be hit if a sibling listener forwards to the same tg-internal-api.

Verify the target group only appears behind the intended rule

A target group should not be reachable through a second listener with weaker conditions. If the same backend is registered behind multiple load balancers, every one of those paths needs the same level of restraint or the same failure comes back through the side door.

Watch for any rule that forwards to a target group before auth, any alternate listener that skips authenticate-oidc, and any direct route that bypasses CloudFront entirely. If the backend is visible from more than one place, the safest rule in the set only protects one of them.

Related posts

CVE-2026-3300 and WordPress admin account abuse

Everest Forms Pro CVE-2026-3300 is not a tidy bug, it is the sort of mess that turns form input into PHP and then acts surprised when attackers notice. I would not trust any site running the affected...

Review CI/CD install scripts for malicious code

Install scripts are the bit people wave through until they bite; in CI/CD, that means code runs under a trusted name before anyone has looked properly. I pin versions, record what landed, and treat...

Check npm and PyPI packages for compromise

A clean package yesterday means very little if a fresh update arrives with new maintainers, odd install scripts, or a version jump that does not make sense. I look for software supply chain trouble by...