Skip to content

fix(policy-engine,controller): reject requests when no policy chain found#1424

Open
renuka-fernando wants to merge 1 commit intowso2:mainfrom
renuka-fernando:fix-reject-missing-policy-chain
Open

fix(policy-engine,controller): reject requests when no policy chain found#1424
renuka-fernando wants to merge 1 commit intowso2:mainfrom
renuka-fernando:fix-reject-missing-policy-chain

Conversation

@renuka-fernando
Copy link
Contributor

@renuka-fernando renuka-fernando commented Mar 20, 2026

Purpose

Fix a security gap where requests bypass all configured policies when the policy engine has no policy chain for a route. Previously, if a route had an empty policy chain (no policies configured), the gateway-controller skipped sending that route's policy chain resource via xDS, and the policy engine silently passed the request through (skipAllProcessing). This means a route configured with policies (e.g., API Key validation) could have its policies bypassed if the policy chain wasn't properly propagated.

Resolves #1422, #1423

Goals

  • Ensure the policy engine always requires a policy chain for every route
  • Return HTTP 500 instead of silently passing requests through when no policy chain is found
  • Ensure the controller always sends policy chain resources via xDS, even for empty chains

Approach

  • Gateway Controller (snapshot.go): Remove the continue that skipped empty policy chains in TranslateRuntimeConfigs, so all routes get their policy chain resource sent via xDS
  • Policy Engine (extproc.go):
    • Add sentinel error errNoPolicyChain returned by initializeExecutionContext when no chain is found
    • Return HTTP 500 ImmediateResponse in handleProcessingPhase instead of calling skipAllProcessing
    • Remove ctx parameter from initializeExecutionContext (logging moved to call site)
  • Tests: Updated to verify 500 rejection behavior and empty chain xDS resource generation

User stories

As a platform operator, I want the gateway to reject requests when policy chains are missing, so that misconfigured routes cannot bypass security policies.

Documentation

N/A — internal behavioral change, no user-facing API changes.

Automation tests

  • Unit tests
    • TestInitializeExecutionContext_NoPolicyChain — verifies errNoPolicyChain returned
    • TestInitializeExecutionContext_WithPolicyChain — verifies no error on valid chain
    • TestProcess_RequestHeaders_NoPolicyChain — verifies 500 ImmediateResponse
    • TestTranslator_TranslateRuntimeConfigs/empty_policy_chain_is_sent — verifies empty chains produce xDS resources
  • Integration tests
    • N/A

Security checks

Samples

N/A

Related PRs

N/A

Test environment

  • Go (as per go.work)
  • macOS Darwin 25.3.0

Summary by CodeRabbit

  • Tests

    • Added test coverage for empty policy chain scenarios
  • Bug Fixes

    • Missing policy chains now trigger HTTP 500 errors instead of silently bypassing processing
    • Empty policy chains are now properly included in configuration resources

…ound

Previously, routes with no policy chain in the policy engine were
silently allowed through (skipAllProcessing), creating a security gap
where requests could bypass configured policies. Now:

- Controller sends empty policy chains via xDS instead of skipping them
- Policy engine returns HTTP 500 when no policy chain is found for a
  route, preventing unauthorized passthrough
- initializeExecutionContext returns an error instead of setting nil
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 20, 2026

Walkthrough

The changes implement mandatory policy chain validation across the gateway system. Empty policy chains are now included in xDS resources instead of being skipped. When no policy chain exists during request processing, the system returns an HTTP 500 response instead of attempting to proceed with default behavior.

Changes

Cohort / File(s) Summary
Policy Chain Test Coverage
gateway/gateway-controller/pkg/policyxds/policyxds_test.go
Added subtest verifying empty policy chains are properly included in xDS resources, not omitted.
XDS Resource Generation
gateway/gateway-controller/pkg/policyxds/snapshot.go
Removed guard that skipped creating policy chain xDS resources when chain.Policies is empty, allowing empty chains to be generated.
Error Handling Refactor
gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go
Changed missing policy chain handling from silent skip to explicit error return. Added errNoPolicyChain sentinel, modified initializeExecutionContext to return error, and updated request header processing to reject with HTTP 500 when policy chain is missing.
Error Handling Tests
gateway/gateway-runtime/policy-engine/internal/kernel/extproc_test.go
Updated tests to expect HTTP 500 response for missing policy chains instead of mode override, adjusted function signatures, and added type imports.

Sequence Diagram

sequenceDiagram
    actor Client
    participant Handler as Request Handler
    participant InitCtx as initializeExecutionContext
    participant PolicyMgr as Policy Manager
    participant Response as Response Builder

    Client->>Handler: HTTP Request (headers phase)
    Handler->>InitCtx: initializeExecutionContext(req, execCtx)
    InitCtx->>PolicyMgr: Lookup policy chain for route
    alt Policy Chain Found
        PolicyMgr-->>InitCtx: RouteMetadata + nil error
        InitCtx-->>Handler: RouteMetadata, nil error
        Handler->>Handler: Continue processing
    else No Policy Chain Found
        PolicyMgr-->>InitCtx: nil RouteMetadata + errNoPolicyChain
        InitCtx-->>Handler: nil, errNoPolicyChain
        Handler->>Response: Return ImmediateResponse
        Response->>Response: Set HTTP 500 Status
        Response-->>Client: HTTP 500 Response
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A chain without a policy chain? Not on my watch!
Empty or missing, we catch every notch,
Now errors are clear, a 500 rings true,
No silent skips—just transparent review! 🎯

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: rejecting requests when no policy chain is found, which is the core security fix across both policy-engine and controller components.
Description check ✅ Passed The description comprehensively covers Purpose, Goals, Approach, User stories, Security checks, and automation tests with clear implementation details aligned to the template structure.
Linked Issues check ✅ Passed Code changes fully implement the requirement from issue #1422: the policy engine now returns HTTP 500 instead of silently passing requests when no policy chain is found, treating this as a platform error.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the policy chain security gap: controller ensures chains are always sent, policy engine returns 500 on missing chains, and tests verify both behaviors.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can customize the tone of the review comments and chat replies.

Configure the tone_instructions setting to customize the tone of the review comments and chat replies. For example, you can set the tone to Act like a strict teacher, Act like a pirate and more.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go (1)

412-441: ⚠️ Potential issue | 🟡 Minor

Remove the unused skipAllProcessing function.

The function has no callers in production code—only test files reference it. With the current implementation rejecting requests via HTTP 500 when no policy chain is found (line 168-183), this function is unreachable and should be deleted along with its tests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go` around
lines 412 - 441, Delete the unused skipAllProcessing method from
ExternalProcessorServer (function skipAllProcessing in extproc.go) and remove
its associated test(s); ensure any references in tests are deleted or updated so
there are no compile-time references to skipAllProcessing, and run unit tests to
confirm nothing else depends on it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go`:
- Around line 412-441: Delete the unused skipAllProcessing method from
ExternalProcessorServer (function skipAllProcessing in extproc.go) and remove
its associated test(s); ensure any references in tests are deleted or updated so
there are no compile-time references to skipAllProcessing, and run unit tests to
confirm nothing else depends on it.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c6f7d3ff-22a7-4c7b-b2c6-9685b62e97fc

📥 Commits

Reviewing files that changed from the base of the PR and between 8485d4d and 5a60e0b.

📒 Files selected for processing (4)
  • gateway/gateway-controller/pkg/policyxds/policyxds_test.go
  • gateway/gateway-controller/pkg/policyxds/snapshot.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/extproc_test.go
💤 Files with no reviewable changes (1)
  • gateway/gateway-controller/pkg/policyxds/snapshot.go

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.

[Task]: Mandate Policy Chain - If no policy chain found return 500

1 participant