Like a bouncer who checks IDs by last name only — drop the first letter and you walk right past the velvet rope
CVE-2026-33186 is an authorization bypass in google.golang.org/grpc versions prior to v1.79.3. The gRPC-Go HTTP/2 server transport stored the raw :path pseudo-header value without validating its leading slash. The routing layer internally normalized paths for dispatch, but authorization interceptors — including the official grpc/authz RBAC engine (authz.NewStatic(), authz.NewFileWatcher()) and any custom interceptor reading info.FullMethod or grpc.Method(ctx) — evaluated the *raw, pre-normalization* string. An attacker sending Service/Method instead of /Service/Method caused deny rules to fail string matching, falling through to a permissive default-allow policy. The result: complete bypass of path-based RBAC deny rules with a single missing character.
The vendor CVSS of 9.1 CRITICAL (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) models a universally exploitable, unauthenticated network attack — and the attack *is* trivially easy when the preconditions are met. But the score overstates real-world exposure because it ignores two compounding friction points: (1) the vulnerability only fires when the target uses gRPC-Go's built-in authz interceptor with a deny-rule + fallback-allow policy pattern, which is a fraction of deployments, and (2) the vast majority of gRPC services sit behind internal service meshes or API gateways, not on the public internet. The 9.1 is the theoretical ceiling; most environments sit well below it.
4 steps from start to impact.
Identify gRPC endpoint
- Network reachability to gRPC service port (typically 443 or 50051)
- Knowledge of service and method names (via reflection, protos, or guessing)
- Most gRPC services are internal-only behind L4/L7 load balancers or service meshes
- gRPC reflection is often disabled in production
http.component:grpc); WAF/API gateway logs showing gRPC traffic from unexpected sources.Craft malformed HTTP/2 :path header
h2 library), the attacker constructs a HEADERS frame with :path set to Service/Method (no leading slash). Standard gRPC clients always prepend /, so this requires a custom tool — the public PoC by JohannesLks on GitHub provides this out of the box.- Ability to send raw HTTP/2 frames (not possible with standard gRPC client libraries)
- Target must be running gRPC-Go < v1.79.3
- Standard gRPC stubs and clients always add the leading slash; attacker needs a custom HTTP/2 framing tool
- Some reverse proxies (Envoy, nginx) may normalize or reject non-canonical paths before they reach the backend
:path values missing leading slash.Bypass authz deny rules
authz interceptor evaluates the raw path Service/Method. Deny rules written for /Service/Method fail to match. If the policy has a fallback allow rule (common in deny-list-first RBAC patterns), the request proceeds unchecked.- Target uses
grpc/authzinterceptor (NewStatic or NewFileWatcher) or custom interceptor reading raw FullMethod - RBAC policy uses deny-list pattern with a permissive fallback allow rule
- Many deployments use allow-list-only policies (explicit allow, default deny) which are NOT bypassed
- Services using external authorization (OPA, Istio AuthorizationPolicy, service mesh sidecars) are unaffected
- mTLS-only auth patterns are unaffected
Access protected methods
- Successfully bypassed deny rules in step 3
- Actual impact depends on what the protected methods do — many internal services have limited blast radius
- Additional application-layer checks (e.g., per-field authorization, tenant isolation) may still block meaningful abuse
The supporting signals.
| In-the-wild exploitation | Not observed. No KEV listing. No GreyNoise or Shadowserver tags as of 2026-09-10. No confirmed campaigns targeting this CVE. |
|---|---|
| Proof-of-concept | Public. Python PoC by JohannesLks published ~June 2026. Uses h2 library for raw HTTP/2 frame crafting. Supports no-slash, double-slash, and custom :path modes. |
| EPSS score | 0.01557 (~98.4th percentile). Moderate exploitation probability reflecting the narrow trigger conditions. |
| KEV status | Not listed on CISA KEV as of 2026-09-10. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N — Network-reachable, no auth required, no user interaction. High confidentiality and integrity impact, no availability impact. The AC:L is accurate *if* the authz pattern is present. |
| Affected versions | google.golang.org/grpc < v1.79.3. All prior versions using the grpc/authz interceptor package are vulnerable. |
| Fixed versions | gRPC-Go v1.79.3. Downstream: Traefik 2.11.42 / 3.6.12 / 3.7.0-ea.3, Datadog Agent tracking in #48151, IBM Fusion per IBM Security Bulletin, Red Hat tracking at access.redhat.com. |
| Scanning / exposure | gRPC-Go is the dominant Go gRPC library with millions of downstream imports. However, the vulnerable *pattern* (authz interceptor + deny-list + allow fallback) is a small subset. Shodan http.component:grpc shows ~200K internet-facing gRPC endpoints globally, but language/version breakdown is unavailable. |
| Disclosure | 2026-03-17 (GHSA published), 2026-03-20 (NVD). Fix released same day as advisory. |
| Credited researcher | Not publicly attributed in GHSA or NVD records. |
noisgate verdict.
The single most decisive downgrade factor is that this bypass only triggers when the target uses gRPC-Go's built-in authz interceptor with a deny-list + fallback-allow policy pattern — a configuration subset, not the default. The 9.1 CVSS models universal applicability that does not hold across the installed base.
Why this verdict
- Narrow trigger condition: The bypass requires the target to use
grpc/authz(or a custom interceptor reading rawFullMethod) with a deny-rule + fallback-allow policy. Deployments using allow-list-only policies, external authorization (OPA, Istio, service mesh), or mTLS-only auth are unaffected. This meaningfully reduces the reachable population below the universal scope the 9.1 CVSS assumes. - Internal-only exposure: The overwhelming majority of gRPC-Go services run behind service meshes, internal load balancers, or API gateways — not directly internet-facing. Exploiting from outside requires a prior foothold or a misconfigured edge, adding an implicit prerequisite the CVSS doesn't capture.
- Trivial exploitation when conditions met: The attack is a single malformed HTTP/2 header with a public PoC. No memory corruption, no race conditions, no brute force. When the authz pattern is present, exploitation is deterministic and reliable — this prevents further downgrade.
- Role multiplier: gRPC-Go is embedded in high-value infrastructure — Kubernetes control plane components (etcd client libraries), service mesh control planes (Istio Pilot), ingress controllers (Traefik), and monitoring agents (Datadog). However, most of these high-value consumers use mTLS or external policy engines for authorization rather than the built-in
grpc/authzpackage. Traefik is a confirmed affected downstream in a network-edge role, keeping the floor at HIGH. If an organization's Traefik deployment relied on gRPC authz deny rules, the blast radius would be network-edge bypass → HIGH floor holds. - Public PoC availability: The JohannesLks PoC has been public since ~June 2026, lowering the attacker skill bar and increasing the urgency to patch even without observed exploitation.
Why not higher?
The vulnerability does not universally affect all gRPC-Go deployments — only those using the specific authz interceptor with deny-list policies. The canonical high-value consumers of gRPC-Go (etcd, Kubernetes API server, Istio) predominantly use mTLS and external policy engines, not the built-in authz package. Without evidence of active exploitation or KEV listing, and with the narrow trigger condition, CRITICAL is not warranted.
Why not lower?
The attack is unauthenticated, network-reachable, trivially exploitable with a public PoC, and results in complete authorization bypass (C:H/I:H). Traefik — a network-edge component — is a confirmed affected downstream, establishing a HIGH floor via the role-multiplier rule. The EPSS of 1.6% is non-trivial, and the Go ecosystem's broad adoption means the absolute number of vulnerable instances is significant even if the percentage is modest.
What to do — in priority order.
- Upgrade gRPC-Go to v1.79.3 immediately — The fix rejects any request with a
:pathmissing the leading slash at the transport layer, before it reaches interceptors. This is the definitive fix. For a HIGH verdict, deploy within 30 days per noisgate mitigation SLA. - Deploy reverse proxy path validation — Configure your L7 proxy (Envoy, nginx, HAProxy) to reject HTTP/2 requests where
:pathdoes not start with/. Envoy'snormalize_pathandmerge_slashesoptions help. This blocks the attack before it reaches gRPC-Go. - Switch to allow-list-only RBAC policies — If using
grpc/authz, restructure policies to explicit allow-list (default deny) rather than deny-list + fallback allow. The bypass only works when deny rules fail to match and a fallback allow permits the request. - Audit downstream Go module dependencies — Run
go list -m all | grep google.golang.org/grpcacross all Go services to identify which binaries embed a vulnerable gRPC-Go version. Prioritize services usinggrpc/authzimports. - Update affected downstream packages — Patch Traefik to 2.11.42+ / 3.6.12+, Datadog Agent per vendor guidance, IBM Fusion per IBM Security Bulletin. These bundle vulnerable gRPC-Go.
- Network-level firewalling alone — if the attacker is already on the internal network (post-compromise), firewall rules between segments won't help unless they specifically inspect HTTP/2 frame content.
- Standard gRPC client-side fixes — the vulnerability is exploited via raw HTTP/2 frames, not standard gRPC client libraries. Upgrading client-side gRPC libraries does not protect the server.
- TLS/mTLS without authz changes — mTLS authenticates the *caller* but does not enforce method-level authorization. If the authz interceptor is still the deny-list pattern, a client with valid mTLS certs can still exploit the bypass.
Crowdsourced verification payload.
Run this on each host or in CI where Go services are built. It scans go.sum files to detect vulnerable gRPC-Go versions. No special privileges needed. Example: bash check_cve_2026_33186.sh /path/to/your/go/project
#!/usr/bin/env bash
# CVE-2026-33186 checker: detects vulnerable google.golang.org/grpc versions
# Usage: bash check_cve_2026_33186.sh <path-to-go-module-root>
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -euo pipefail
TARGET_DIR="${1:-.}"
FIXED_VERSION="1.79.3"
if [ ! -f "$TARGET_DIR/go.sum" ] && [ ! -f "$TARGET_DIR/go.mod" ]; then
echo "UNKNOWN: No go.sum or go.mod found in $TARGET_DIR"
exit 2
fi
# Try go.sum first, fall back to go.mod
GRPC_VERSION=""
if [ -f "$TARGET_DIR/go.sum" ]; then
GRPC_VERSION=$(grep -oP 'google\.golang\.org/grpc v\K[0-9]+\.[0-9]+\.[0-9]+' "$TARGET_DIR/go.sum" | sort -V | tail -1)
fi
if [ -z "$GRPC_VERSION" ] && [ -f "$TARGET_DIR/go.mod" ]; then
GRPC_VERSION=$(grep -oP 'google\.golang\.org/grpc v\K[0-9]+\.[0-9]+\.[0-9]+' "$TARGET_DIR/go.mod" | head -1)
fi
if [ -z "$GRPC_VERSION" ]; then
echo "UNKNOWN: google.golang.org/grpc not found in module files"
exit 2
fi
echo "Detected gRPC-Go version: v$GRPC_VERSION"
echo "Fixed version: v$FIXED_VERSION"
# Compare versions using sort -V
LOWEST=$(printf '%s\n%s' "$GRPC_VERSION" "$FIXED_VERSION" | sort -V | head -1)
if [ "$GRPC_VERSION" = "$FIXED_VERSION" ] || [ "$LOWEST" = "$FIXED_VERSION" ]; then
echo "PATCHED: gRPC-Go v$GRPC_VERSION >= v$FIXED_VERSION"
exit 0
else
echo "VULNERABLE: gRPC-Go v$GRPC_VERSION < v$FIXED_VERSION (CVE-2026-33186)"
# Additional check: see if grpc/authz is imported
if grep -rq 'google.golang.org/grpc/authz' "$TARGET_DIR/" 2>/dev/null; then
echo "WARNING: This project imports grpc/authz — HIGH exploitation risk"
else
echo "NOTE: grpc/authz import not detected — lower exploitation risk (but custom interceptors may still be affected)"
fi
exit 1
fiIf you remember one thing.
grpc/authz or use custom path-based interceptors — those are your highest-risk targets. Per the noisgate mitigation SLA for HIGH (≤ 30 days), deploy compensating controls (L7 proxy path validation, switch to allow-list policies) on exposed services immediately while scheduling dependency upgrades. Per the noisgate remediation SLA for HIGH (≤ 180 days), bump google.golang.org/grpc to v1.79.3+ and update downstream packages (Traefik 2.11.42+/3.6.12+, Datadog Agent, IBM Fusion) across all environments. If any gRPC service using deny-list authz is internet-facing, treat it as emergency patching — do not wait 30 days.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.