Skip to content

fix: honor top-level originRequest.access (default Access config) in ingress JWT validation#1695

Open
mvanhorn wants to merge 1 commit into
cloudflare:masterfrom
mvanhorn:fix/784-default-access-config-ignored
Open

fix: honor top-level originRequest.access (default Access config) in ingress JWT validation#1695
mvanhorn wants to merge 1 commit into
cloudflare:masterfrom
mvanhorn:fix/784-default-access-config-ignored

Conversation

@mvanhorn

Copy link
Copy Markdown

Summary

A top-level originRequest.access block now actually enforces Access JWT validation on every ingress rule. Previously it was silently ignored: validation only ran when the access block was placed under an individual ingress rule, so operators who used the documented top-level form believed enforcement was active when it was not.

Why this matters

The reporter of #784 traced the root cause in 2022 and it is unchanged on current master: setConfig (via setAccess in ingress/config.go) correctly merges the global access config into each rule's effective OriginRequestConfig, but validateIngress in ingress/ingress.go attaches the middleware.NewJWTValidator handler from the raw per-rule r.OriginRequest.Access pointer, so the merged value is computed and never used. A comment from 2026-07-10 confirms the bug still reproduces on 2026.7.1 with a minimal A/B test: the same block returns an unauthenticated 200 at top level and a 403 per-rule. Two later commenters flagged this as a live security risk because the failure is silent.

Changes

  • validateIngress now builds the Access handler from the merged cfg.Access (the config returned by setConfig(defaults, r.OriginRequest)) instead of the raw per-rule pointer. Because the merged field is a value type, the handler is gated on a non-zero merged config before calling validateAccessConfiguration and attaching the JWT validator.
  • Per-rule semantics are preserved exactly: a rule-level access block still overrides the global one through the existing setAccess merge. A 2022 comment called per-hostname placement "largely intended", but the code's own merge path and the origin-configuration docs both present the top-level block as supported; this change makes behavior match both.

Testing

Extended ingress/ingress_test.go: global-only access config attaches a validator to every rule; a per-rule block overrides the global teamName/audTag; per-rule-only behavior is unchanged; no access config anywhere attaches nothing; and a global block with required: true but a blank teamName now fails at startup with the existing "access.TeamName cannot be blank" error instead of being silently ignored. go test ./ingress/... passes.

Fixes #784

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The default Access config is ignored

1 participant