Engine Context Propagation#
Kyverno's engine accepts a context.Context at every public entry-point (Validate, Mutate, Generate, VerifyAndPatchImages, ApplyBackgroundChecks) , but historically several internal dispatch paths discarded that context and substituted context.TODO() or context.Background(). The consequence is that Kubernetes admission timeouts and request cancellations cannot interrupt those operations, creating un-cancellable goroutines, hung external API calls, and potential connection-pool exhaustion.
This is an ongoing incremental effort to close those gaps, layer by layer.
Where Context Flows (and Where It Doesn't)#
The call chain inside engine.go illustrates the pattern:
- Entry-points receive a live
ctxand forward it to their private counterparts (e.validate,e.mutate,e.generateResponse,e.applyBackgroundChecks, etc.) . - Rule invocation β
invokeRuleHandlerpropagatesctxthrough OpenTelemetry span creation, the context loader, and ultimately to each rule handler'sProcess()call . - Context loader β The
ContextLoaderfactory captures the livectxso all external data fetches (API calls, image registry lookups) inherit the request's deadline.
Remaining gap: Before any rule runs, the engine calls internal.MatchPolicyContext(logger, e.client, policyContext, e.configuration) β with no context argument . Inside match.go, checkMatchConditions then calls matcher.Match(context.TODO(), ...) , bypassing the live request context for CEL match-condition evaluation. This is the subject of the open issue below.
Fixed: Background Checks and Generate Rule Evaluation (PR #14812)#
PR #14812 (merged January 2026; cherry-picked to the release branch as PR #14821) patched the first critical gap.
Root cause: applyBackgroundChecks and generateResponse received ctx from callers but internally called contextLoader(context.TODO(), ...) β making every external data fetch in background and generate rules un-cancellable.
Fix: Added ctx context.Context through the entire internal dispatch chain: applyBackgroundChecks β filterRules β filterRule β contextLoader(ctx, ...). The engine.go entry-points were updated to pass their live ctx down .
A dedicated test (TestApplyBackgroundChecks_ContextPropagation) verifies that the context received inside the loader is the same one passed to ApplyBackgroundChecks .
Refactored: Background Utility Functions (PR #16643)#
PR #16643 (merged July 2026) is an incremental follow-up that updated pkg/background/common/util.go.
Changes: FindDownstream, UpdateStatus, and retryOrDeleteOnFailure were updated to accept a ctx context.Context parameter, replacing internal client.ListResource(context.TODO(), ...) and similar calls .
Partial uplift: Most call sites temporarily pass context.TODO() as a placeholder pending further work. One call site was immediately upgraded: the webhook generation handler (pkg/webhooks/resource/generation/handler.go) now passes its real request ctx to FindDownstream .
This PR establishes the correct function signatures so that future PRs can bubble real contexts up from controller reconcile loops without breaking callers.
Open Gap: CEL Match-Condition Evaluation (Issue #16909)#
Status: open as of 2026-08-02 β tracked in issue #16909.
The checkMatchConditions function in pkg/engine/internal/match.go accepts no context.Context and passes context.TODO() directly to matcher.Match() . All five engine entry-points call MatchPolicyContext without threading their live ctx .
Impact: A hung or slow CEL expression in a policy's matchConditions block cannot be interrupted by Kubernetes API-server admission timeouts (30 s), leading to goroutine leaks and memory pressure under load.
Proposed fix (from issue #16909):
- Add
ctx context.ContexttoMatchPolicyContextandcheckMatchConditionsinmatch.go. - Replace
matcher.Match(context.TODO(), ...)withmatcher.Match(ctx, ...). - Thread
ctxfrom each entry-point inengine.gointoMatchPolicyContext.
Related Efforts#
| Area | Status | Reference |
|---|---|---|
| Background checks & generate rule evaluation | β Fixed | PR #14812 |
Background utility functions (pkg/background/common) | β Signatures fixed, call sites partial | PR #16643 |
CEL match condition evaluation (match.go) | π΄ Open | Issue #16909 |
| CLI HTTP policy/resource loaders | π΄ Open | Issue #16500 |
Dynamic resource watcher (gpol/dynamic_watcher.go) | β Fixed | PR #16087 |
Context propagation is also a prerequisite for the CEL Policy Decision Explainability feature (issue #16692), which requires properly scoped contexts to carry structured evaluation traces through the CEL pipeline.
General rule: avoid context.Background() or context.TODO() in long-lived goroutines; propagate the parent ctx and use context.WithTimeout for detached work .