Summary
OnHttpResponseTrailers crashes with a nil pointer panic when ctx.logger is nil. This can happen when getWAFOrDefault fails in OnHttpRequestHeaders (e.g. no WAF matches the request authority). In that case, the function returns early without initializing ctx.tx or ctx.logger. Subsequent callbacks including OnHttpResponseTrailers are still invoked by Envoy — and unlike the sibling functions, OnHttpResponseTrailers has no nil guard.
In practice this manifests with gRPC traffic, because gRPC is the most common use of HTTP/2 response trailers (gRPC always sends grpc-status in a trailers frame). Regular HTTP responses do not use trailers, so those code paths never reach OnHttpResponseTrailers even when ctx.logger is nil.
Crash backtrace (from Envoy WASM host logs)
Proxy-Wasm plugin in-VM backtrace:
0: 0xc34e6 - runtime.runtimePanicAt
1: 0x9edea - runtime.nilPanic
2: 0x235532 - interface:{debuglog.Logger}.Debug$invoke
3: 0x2a0196 - proxy_on_response_trailers
Preceded in the Envoy logs by:
wasm log coraza-waf coraza: Failed to resolve WAF for authority "<ip>:<port>": no default WAF
Root cause
In wasmplugin/plugin.go, OnHttpResponseTrailers calls ctx.logger.Debug() as its first substantive line with no nil guard:
func (ctx *httpContext) OnHttpResponseTrailers(numTrailers int) types.Action {
defer logTime("OnHttpResponseTrailers", currentTime())
ctx.logger.Debug().Msg("Enforced response body processing at OnHttpResponseTrailers") // PANICS if ctx.logger is nil
return ctx.OnHttpResponseBody(ctx.bodyReadIndex, true)
}
ctx.logger is only assigned in OnHttpRequestHeaders inside the success branch of getWAFOrDefault. When that lookup fails, the function returns ActionContinue early without setting ctx.logger or ctx.tx.
All sibling response-phase functions guard against this correctly:
// OnHttpResponseBody — safe:
if ctx.tx == nil {
return types.ActionContinue
}
OnHttpResponseTrailers is the only callback missing this guard.
Impact
- Any stream where
getWAFOrDefault fails in OnHttpRequestHeaders AND the response carries HTTP/2 trailers will crash the WASM plugin.
- After the panic, the WASM plugin enters a bad state — subsequent streams on the same worker return
grpc-status: 14 (UNAVAILABLE) to the client.
- Regular HTTP/1.1 and HTTP/2-without-trailers traffic is unaffected, which is why this is specific to gRPC workloads in practice.
Proposed fix
Add the same nil guard used in OnHttpResponseBody:
func (ctx *httpContext) OnHttpResponseTrailers(numTrailers int) types.Action {
if ctx.tx == nil {
return types.ActionContinue
}
defer logTime("OnHttpResponseTrailers", currentTime())
ctx.logger.Debug().Msg("Enforced response body processing at OnHttpResponseTrailers")
return ctx.OnHttpResponseBody(ctx.bodyReadIndex, true)
}
Note: OnHttpRequestTrailers has the same missing nil guard and may be susceptible to the same panic on the request side.
Environment
- coraza-proxy-wasm:
0.6.0
- Envoy Gateway: deployed via
EnvoyExtensionPolicy targeting a Gateway resource
- Traffic: gRPC over HTTP/2
Summary
OnHttpResponseTrailerscrashes with a nil pointer panic whenctx.loggeris nil. This can happen whengetWAFOrDefaultfails inOnHttpRequestHeaders(e.g. no WAF matches the request authority). In that case, the function returns early without initializingctx.txorctx.logger. Subsequent callbacks includingOnHttpResponseTrailersare still invoked by Envoy — and unlike the sibling functions,OnHttpResponseTrailershas no nil guard.In practice this manifests with gRPC traffic, because gRPC is the most common use of HTTP/2 response trailers (gRPC always sends
grpc-statusin a trailers frame). Regular HTTP responses do not use trailers, so those code paths never reachOnHttpResponseTrailerseven whenctx.loggeris nil.Crash backtrace (from Envoy WASM host logs)
Preceded in the Envoy logs by:
Root cause
In
wasmplugin/plugin.go,OnHttpResponseTrailerscallsctx.logger.Debug()as its first substantive line with no nil guard:ctx.loggeris only assigned inOnHttpRequestHeadersinside the success branch ofgetWAFOrDefault. When that lookup fails, the function returnsActionContinueearly without settingctx.loggerorctx.tx.All sibling response-phase functions guard against this correctly:
OnHttpResponseTrailersis the only callback missing this guard.Impact
getWAFOrDefaultfails inOnHttpRequestHeadersAND the response carries HTTP/2 trailers will crash the WASM plugin.grpc-status: 14 (UNAVAILABLE)to the client.Proposed fix
Add the same nil guard used in
OnHttpResponseBody:Note:
OnHttpRequestTrailershas the same missing nil guard and may be susceptible to the same panic on the request side.Environment
0.6.0EnvoyExtensionPolicytargeting a Gateway resource