Back to Blog
high SEVERITY6 min read

Authorization Bypass in gRPC-Go HTTP/2 Path Validation (CVE-2026-33186)

A critical authorization bypass vulnerability (CVE-2026-33186) in `google.golang.org/grpc` v1.79.1 allowed attackers to circumvent gRPC authorization policies through malformed HTTP/2 path values. The fix upgrades the dependency in `src/go/go.mod` from v1.79.1 to v1.79.3, closing a path validation gap in the `grpc-go/authz` middleware that could have exposed protected RPC endpoints to unauthorized callers.

O
By orbisai0security
May 30, 2026

Authorization Bypass in gRPC-Go HTTP/2 Path Validation (CVE-2026-33186)

Introduction

The src/go/go.mod file in this Moby-based containerized service pulls in google.golang.org/grpc as an indirect dependency — one of the most widely used RPC frameworks in the Go ecosystem. Because it sits behind an // indirect comment, it's easy to overlook during routine dependency audits. That oversight nearly cost this project dearly: grpc-go v1.79.1 ships with a critical authorization bypass (CVE-2026-33186) rooted in how the authz middleware validates HTTP/2 :path pseudo-headers.

This post breaks down exactly what went wrong, why HTTP/2 path handling is a surprisingly tricky security surface, and how a two-line change to go.mod and a checksum update in go.sum sealed the gap.


The Vulnerability Explained

gRPC Authorization and the HTTP/2 :path Header

gRPC-Go's google.golang.org/grpc/authz package provides policy-based authorization for RPC methods. Under the hood, every gRPC call maps to an HTTP/2 request where the method path — e.g., /mypackage.MyService/MyMethod — is carried in the :path pseudo-header.

Authorization rules are typically written against these path strings:

// Example authz policy (simplified)
{
  "rules": [{
    "name": "block-admin",
    "source": {"principals": ["*"]},
    "request": {"paths": ["/admin.AdminService/*"]}
  }]
}

The vulnerability lies in how authz normalizes the :path value before matching it against policy rules. In v1.79.1, certain malformed or non-canonical path representations — such as paths with unexpected percent-encoding, double slashes, or other HTTP/2-legal-but-semantically-ambiguous constructs — were not consistently normalized. This created a mismatch: the policy engine evaluated one string while the actual RPC dispatcher resolved another.

The Exploitable Pattern

Consider a service that protects /admin.AdminService/DeleteUser behind an authorization rule. An attacker who can send raw HTTP/2 frames could craft a :path value like:

/admin.AdminService/%44eleteUser

or

//admin.AdminService/DeleteUser

The authz middleware, operating on the raw or inconsistently normalized value, might not match the deny rule — passing the request through to the RPC handler as if it were authorized. The dispatcher, which performs its own normalization, resolves the path correctly and executes the privileged method.

This is a classic TOCTOU-style normalization mismatch: the security check and the execution engine disagree on what the path actually means.

Why This Matters for a Containerized Moby Service

In a containerized environment, gRPC endpoints are often exposed on internal networks with the assumption that the authorization middleware is the primary access control layer. If that layer can be bypassed by a network-adjacent attacker — or even a compromised container on the same overlay network — the blast radius is significant. Any RPC method behind an authz policy could be reachable without credentials or role membership.

The Trivy scanner flagged this in src/go/go.mod with severity CRITICAL and assessment "Likely exploitable", indicating the vulnerable code path is reachable in the production build.


The Fix

What Changed

The fix is surgical: a single version bump in src/go/go.mod and the corresponding checksum entries in src/go/go.sum.

src/go/go.mod — before:

google.golang.org/grpc v1.79.1 // indirect

src/go/go.mod — after:

google.golang.org/grpc v1.79.3 // indirect

Additionally, a previously missing transitive dependency was pinned explicitly:

// Added to the indirect require block:
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect

src/go/go.sum — new checksums added:

google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:...
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:...

Why Each Change Was Necessary

Change Purpose
grpc v1.79.1v1.79.3 Pulls in the patched authz path normalization logic
Added genproto/googleapis/rpc explicit pin v1.79.3 tightened its RPC type dependencies; pinning ensures reproducible builds and prevents the module graph from silently resolving an older, potentially vulnerable version
Updated go.sum hashes Go's module verification requires cryptographic checksums for every resolved module version; without these, go build would refuse to proceed

The grpc-go v1.79.3 patch introduces canonical normalization of the HTTP/2 :path pseudo-header inside the authz interceptor before policy evaluation, ensuring the string the security check operates on is identical to the string the dispatcher will use. The fix eliminates the normalization mismatch at its source.


Prevention & Best Practices

1. Treat Indirect Dependencies as First-Class Security Concerns

The vulnerable line in go.mod was marked // indirect — meaning no first-party code directly imports grpc. It's a transitive dependency pulled in by another library. Indirect dependencies are just as exploitable as direct ones and must be included in vulnerability scanning.

Action: Configure Trivy, govulncheck, or Dependabot to scan all dependencies, not just direct imports.

# Run govulncheck on your module
govulncheck ./...

# Or use trivy on your go.mod directly
trivy fs --scanners vuln src/go/go.mod

2. Pin and Audit gRPC Authorization Middleware Separately

If you use google.golang.org/grpc/authz, treat it as a security-critical component. Add it as a direct dependency in go.mod even if it's technically indirect, so version changes are explicit and visible in code review:

require (
    google.golang.org/grpc v1.79.3
    // Explicitly track authz-bearing grpc version
)

3. Validate HTTP/2 Path Inputs at the Application Layer Too

Even with a patched framework, defense-in-depth recommends validating RPC method paths at the application layer:

// In your gRPC server interceptor
func pathValidationInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    method := info.FullMethod
    if !isCanonicalGRPCPath(method) {
        return nil, status.Errorf(codes.InvalidArgument, "malformed method path: %s", method)
    }
    return handler(ctx, req)
}

func isCanonicalGRPCPath(path string) bool {
    // Must start with /, no double slashes, no percent-encoding
    return strings.HasPrefix(path, "/") &&
        !strings.Contains(path, "//") &&
        !strings.ContainsRune(path, '%')
}

4. Use go mod tidy + go mod verify in CI

# Ensure the module graph is consistent
go mod tidy

# Verify all downloaded modules match go.sum checksums
go mod verify

Failing CI on go mod verify discrepancies catches tampered or unexpected dependency versions before they reach production.

5. Relevant Standards and References

  • CWE-863: Incorrect Authorization
  • CWE-116: Improper Encoding or Escaping of Output (path normalization failure)
  • OWASP ASVS v4.0, Section 4.1: Access Control Design Requirements — specifically, that access control checks must use the same representation of a resource as the enforcement point
  • gRPC Security Best Practices: https://grpc.io/docs/guides/security/

Key Takeaways

  • // indirect in go.mod does not mean "low risk" — CVE-2026-33186 lived in an indirect dependency and was rated CRITICAL. Scan everything.
  • HTTP/2 path normalization is a security boundary — the authz middleware in grpc-go v1.79.1 evaluated paths before canonicalization, creating a gap between the security check and the dispatcher. v1.79.3 closes this by normalizing first.
  • The genproto/googleapis/rpc pin was not cosmetic — explicitly adding it to go.mod ensures the build graph is deterministic and that no older RPC type package can be silently resolved, which could reintroduce instability in the patched code paths.
  • Authorization bypass vulnerabilities in RPC frameworks are high-value targets in containerized environments where gRPC endpoints are assumed to be protected by middleware alone.
  • A two-line diff can fix a critical vulnerability — but only if your scanner is configured to catch it. The Trivy rule CVE-2026-33186 found this; without automated scanning, it would have shipped.

Conclusion

CVE-2026-33186 is a reminder that the security of your gRPC service is only as strong as the path normalization logic in your authorization middleware. In this case, google.golang.org/grpc v1.79.1 — quietly sitting in src/go/go.mod as an indirect dependency — contained a flaw that could allow an attacker to bypass carefully crafted authorization policies by sending a semantically equivalent but syntactically non-canonical HTTP/2 path.

The fix is minimal in code footprint but significant in impact: upgrading to v1.79.3 ensures the authz interceptor and the RPC dispatcher always agree on what path is being requested. Combined with the explicit genproto/googleapis/rpc pin for build reproducibility, this change closes the vulnerability cleanly.

If your Go services use gRPC — directly or transitively — audit your go.mod today. Run govulncheck ./... and make sure your indirect dependencies are held to the same security standard as your first-party code.


This vulnerability was identified and remediated by Orbis AppSec automated security tooling.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #22587

Related Articles

high

Shell Injection via Unsafe String Concatenation in gRPC Command Generation

A high-severity shell injection vulnerability was discovered in `src/RtlJaguarDevice.cpp`, where user-controlled values from API responses were directly interpolated into gRPCurl command strings without proper shell escaping. An attacker who controls API response data could inject shell metacharacters, causing arbitrary command execution when a user pastes and runs the generated command. The fix applies proper shell escaping to all user-controlled values before they are included in command strin

high

Shell Injection via Unsafe String Concatenation in CXLMemSim gRPCurl Commands

A high-severity shell injection vulnerability was discovered and patched in a distributed server's gRPCurl command generation logic, where user-controlled values from API responses were directly interpolated into shell command strings without proper escaping. An attacker who can influence API response data — such as headers, endpoints, or payloads — could inject shell metacharacters that execute arbitrary commands when a user pastes and runs the generated command. This fix eliminates the risk by

high

Shell Injection via gRPCurl Command Generation: A Hidden Android Threat

A high-severity shell injection vulnerability was discovered and fixed in the HeadUnit Revived Android project, where user-controlled API response values were unsafely interpolated into gRPCurl command strings. An attacker could craft malicious headers, endpoints, or data payloads containing shell metacharacters that, when the generated command is pasted and executed, would run arbitrary commands on the victim's machine. The fix introduces proper shell escaping and broadcast intent protection to

critical

Stack Buffer Overflow in C++ gRPC Server: How sprintf() Enables Code Execution

A critical stack buffer overflow vulnerability was discovered in the ik-llama-cpp gRPC inference server, where three unguarded sprintf() calls wrote formatted statistics into fixed-size stack buffers without any length restrictions. If exploited, an attacker could overwrite return addresses and saved frame pointers, potentially achieving arbitrary code execution on the server. The fix replaces the unsafe sprintf() calls with length-aware alternatives, closing the door on this dangerous memory co

high

CVE-2026-41676: OpenSSL Bindings Vulnerability Fixed in Rust SDK Cargo.lock

A high-severity vulnerability (CVE-2026-41676) was discovered in the `rust-openssl` crate (version 0.10.73) used in the `apps/rust-sdk` component, as flagged by the Trivy scanner in `Cargo.lock`. The fix upgrades the `openssl` crate from `0.10.73` to `0.10.80` and `openssl-sys` from `0.9.109` to `0.9.116`, closing an exploitable attack surface in production code that handles user-influenced input. Because the Rust SDK sits in the production codebase, any attacker able to reach the OpenSSL code p

high

Shell Injection via Unsafe String Concatenation in PaddleOCR Deployment

A high-severity vulnerability was discovered in PaddleOCR's deployment configuration where model download URLs were specified using unencrypted `http://`, exposing users to man-in-the-middle attacks that could allow an attacker to intercept and replace model files with malicious ones. The fix upgrades all model download URLs to use `https://`, ensuring encrypted transmission and integrity of the downloaded files. This change is a critical security baseline for any application that downloads bina