Back to Blog
critical SEVERITY7 min read

Go JOSE DoS Vulnerability: Fixing JWE Object Exploitation in Rclone

A high-severity Denial of Service vulnerability (CVE-2026-34986) was discovered in the `github.com/go-jose/go-jose/v4` library, which Rclone depends on for JSON Web Encryption operations. An attacker could craft a malicious JWE object to exhaust server resources and bring down services. The fix is a targeted dependency upgrade from v4.1.3 to v4.1.4 — a minimal change with significant security impact.

O
By orbisai0security
May 28, 2026

Go JOSE DoS Vulnerability: Fixing JWE Object Exploitation in Rclone

Introduction

Cryptographic libraries sit at the heart of modern application security. When they fail, the consequences ripple outward — affecting every application that trusts them. That's exactly the scenario at play with CVE-2026-34986, a high-severity Denial of Service (DoS) vulnerability discovered in github.com/go-jose/go-jose/v4, a widely-used Go library for JSON Object Signing and Encryption (JOSE) operations.

Rclone — the popular open-source cloud storage sync tool — was among the affected projects, as it relies on go-jose/v4 for cryptographic operations. This post breaks down the vulnerability, explains how it could be exploited, and walks through the surgical fix that closes the security gap.

CVE at a Glance
- CVE ID: CVE-2026-34986
- Severity: HIGH
- Affected Package: github.com/go-jose/go-jose/v4 ≤ v4.1.3
- Fixed In: v4.1.4
- Impact: Denial of Service via crafted JSON Web Encryption (JWE) object


What Is JSON Web Encryption (JWE)?

Before diving into the vulnerability, it's worth understanding the attack surface.

JSON Web Encryption (JWE) is a standard (RFC 7516) for representing encrypted content using JSON-based data structures. It's commonly used in:

  • OAuth 2.0 / OpenID Connect flows for encrypting tokens
  • API authentication systems that pass sensitive claims securely
  • Secure messaging between microservices

A JWE object looks like this (compact serialization):

BASE64URL(JWE Protected Header) . BASE64URL(JWE Encrypted Key) . BASE64URL(JWE Initialization Vector) . BASE64URL(JWE Ciphertext) . BASE64URL(JWE Authentication Tag)

The go-jose library is responsible for parsing and processing these objects in Go applications. And that parsing step — specifically how the library handles crafted, malformed, or adversarially constructed JWE objects — is where the vulnerability lives.


The Vulnerability Explained

What Goes Wrong?

CVE-2026-34986 is a Denial of Service vulnerability triggered by processing a specially crafted JWE object. When the vulnerable versions of go-jose/v4 (≤ v4.1.3) parse a malicious JWE payload, they can be forced into an expensive or unbounded computation — consuming excessive CPU or memory resources.

This class of vulnerability is sometimes called an algorithmic complexity attack or resource exhaustion attack. The attacker doesn't need to break the encryption — they just need to make the server work so hard trying to process the input that it becomes unavailable to legitimate users.

How Could It Be Exploited?

The attack scenario is straightforward:

  1. Identify a target endpoint that accepts JWE tokens — such as an API that processes encrypted JWTs, an OAuth callback, or any service that decrypts user-supplied tokens.
  2. Craft a malicious JWE object — specifically constructed to trigger the expensive code path in the parser.
  3. Send the payload repeatedly — even a moderate request rate can exhaust server resources if each request triggers the vulnerable path.
  4. Service becomes unavailable — legitimate users are denied access while the server struggles to process the flood of malicious inputs.
Attacker                          Vulnerable Server
   |                                     |
   |-- POST /api/auth (crafted JWE) ---->|
   |                                     | [CPU/Memory spike]
   |-- POST /api/auth (crafted JWE) ---->|
   |                                     | [Resources exhausted]
   |-- POST /api/auth (crafted JWE) ---->|
                                         |  Service unavailable
                                         |  Legitimate users denied

Why Is This Particularly Dangerous?

Several factors amplify the risk:

  • No authentication required: An attacker typically doesn't need valid credentials to submit a JWE token for processing. The vulnerability triggers before authentication succeeds.
  • Low attack complexity: Crafting a malicious JWE object requires knowledge of the standard format, not advanced cryptographic skills.
  • Broad impact: Any Go application using go-jose/v4 ≤ v4.1.3 that processes externally-supplied JWE tokens is potentially vulnerable.
  • Supply chain exposure: Even if your code doesn't directly call go-jose, a transitive dependency might — making this a classic supply chain vulnerability.

The Fix

What Changed?

The fix is elegantly simple: a one-line version bump in go.mod.

Before (vulnerable):

// go.mod
github.com/go-jose/go-jose/v4 v4.1.3 // indirect

After (fixed):

// go.mod
github.com/go-jose/go-jose/v4 v4.1.4 // indirect

The corresponding go.sum entries were also updated to reflect the new cryptographic hashes for the fixed version:

# Removed (vulnerable):
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=

# Added (fixed):
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=

How Does the Fix Work?

The v4.1.4 release of go-jose patches the vulnerable parsing logic to add proper input validation and bounds checking before performing expensive cryptographic operations. This typically involves one or more of the following mitigations:

  • Size limits: Rejecting JWE objects that exceed reasonable size thresholds before processing begins.
  • Complexity caps: Limiting the computational work performed on any single input, regardless of its structure.
  • Early rejection: Failing fast on malformed inputs rather than attempting to process them fully.

The result is that a crafted JWE object is rejected quickly and cheaply, rather than causing the server to spiral into resource exhaustion.

Why Is a Dependency Upgrade the Right Fix?

It's worth noting that this fix happens entirely at the dependency layer — no application code needed to change. This is by design:

  • The vulnerability exists in library internals, not in how Rclone calls the library.
  • The go-jose maintainers are best positioned to fix their own parsing logic.
  • Upgrading the dependency gets the fix for all call sites simultaneously.

This is a great example of why keeping dependencies up to date is a security practice, not just a maintenance chore.


Prevention & Best Practices

1. Automate Dependency Vulnerability Scanning

Don't wait for a CVE to appear in your inbox. Integrate automated scanning into your CI/CD pipeline:

# Using govulncheck (official Go vulnerability scanner)
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...

# Using trivy (detected this vulnerability)
trivy fs --scanners vuln go.mod

Tools to consider:
- govulncheck — Official Go vulnerability checker, understands call graphs
- Trivy — Comprehensive scanner for containers, filesystems, and IaC
- Dependabot — Automated PRs for vulnerable dependencies on GitHub
- Snyk — Developer-first security platform with Go support

2. Validate All Externally-Supplied Cryptographic Input

When your application processes tokens or encrypted objects from untrusted sources, add defensive layers:

// ❌ Vulnerable pattern: blindly processing external input
func handleToken(rawJWE string) error {
    parsed, err := jwe.ParseEncrypted(rawJWE)
    // ...
}

// ✅ Safer pattern: validate before processing
func handleToken(rawJWE string) error {
    // Enforce reasonable size limits
    const maxTokenSize = 64 * 1024 // 64KB
    if len(rawJWE) > maxTokenSize {
        return errors.New("token exceeds maximum allowed size")
    }

    // Use context with timeout to cap processing time
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    parsed, err := parseWithContext(ctx, rawJWE)
    // ...
}

3. Apply Rate Limiting to Token-Processing Endpoints

Even with a patched library, rate limiting is a critical defense-in-depth measure:

// Using golang.org/x/time/rate
limiter := rate.NewLimiter(rate.Every(time.Second), 100) // 100 req/sec

func authHandler(w http.ResponseWriter, r *http.Request) {
    if !limiter.Allow() {
        http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
        return
    }
    // process token...
}

4. Keep a Software Bill of Materials (SBOM)

Know what's in your software supply chain. Generate and maintain an SBOM:

# Generate SBOM for a Go project
go install github.com/anchore/syft@latest
syft . -o spdx-json > sbom.json

An up-to-date SBOM lets you quickly answer "are we affected by CVE-X?" across your entire portfolio.

5. Subscribe to Security Advisories

Stay informed about vulnerabilities in your dependencies:

Relevant Security Standards

This vulnerability maps to several well-known security frameworks:

Framework Reference
CWE CWE-400: Uncontrolled Resource Consumption
CWE CWE-20: Improper Input Validation
OWASP A05:2021 – Security Misconfiguration
OWASP A06:2021 – Vulnerable and Outdated Components

Conclusion

CVE-2026-34986 is a reminder that security is a supply chain problem. You can write perfectly secure application code and still be vulnerable because of what's hiding in your go.mod file. The go-jose vulnerability required no sophisticated cryptographic attack — just a crafted input and an unpatched library.

The key takeaways from this incident:

  1. Transitive dependencies mattergo-jose was an indirect dependency of Rclone, yet it represented a real attack surface.
  2. DoS is a real threat — Availability is part of the CIA triad. A service that's down is a service that's breached from a business continuity perspective.
  3. The fix was simple — One line in go.mod. The hardest part is knowing you're vulnerable, which is why automated scanning is non-negotiable.
  4. Defense in depth applies — Even after patching, rate limiting, input validation, and timeouts provide additional resilience.

Security isn't a destination — it's a continuous process of monitoring, updating, and improving. Tools like automated vulnerability scanners and services like OrbisAI Security exist precisely to make that process less burdensome, so your team can focus on building great software while staying secure.

Stay patched. Stay vigilant. Ship secure code. 🔒


This vulnerability was detected and fixed automatically by OrbisAI Security. Automated security fixes help teams respond to CVEs faster, reducing the window of exposure from weeks to hours.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #9518

Related Articles

low

From text/template to html/template: Closing the XSS Door in Go

A cross-site scripting (XSS) vulnerability was discovered and patched in a Go-based application where the `text/template` package was being used instead of the safer `html/template` package for rendering HTML content. This single-line fix — swapping one import — prevents user-controlled data from being injected as raw HTML, closing a potential attack vector for malicious script injection. While rated low severity, XSS vulnerabilities are among the most common and exploitable web security issues,

high

The Hidden Danger of Iterating Over Empty Maps in Go Applications

A medium-severity vulnerability was recently patched in a Go workflow runtime system where code attempted to iterate over a potentially empty map without proper validation. While this may seem like a minor oversight, such patterns can lead to unexpected behavior, logic bugs, and in some cases, exploitable security vulnerabilities when combined with other code paths.

critical

Heap Buffer Overflow in Audio Ring Buffer: How a Missing Bounds Check Could Crash Your App

A critical heap buffer overflow vulnerability was discovered in `audio_backend.c`, where the audio ring buffer's `memcpy` operations lacked bounds validation before writing PCM data. Without checking that incoming data sizes fell within the allocated buffer's capacity, a maliciously crafted audio file could corrupt adjacent heap memory, potentially enabling arbitrary code execution. The fix adds a concise pre-flight validation guard that rejects out-of-range write requests before any memory oper

critical

Critical Memory Safety Bug: Free of Uninitialized Memory in Rust Telemetry (CVE-2021-29937)

CVE-2021-29937 is a critical memory safety vulnerability in the Rust `telemetry` crate (versions prior to 0.1.3) that allows freeing uninitialized memory, leading to undefined behavior, potential crashes, and possible code execution. The fix involves upgrading the crate from version 0.1.0 to 0.1.3, which patches the unsafe memory handling at the root cause. Despite Rust's reputation for memory safety, this vulnerability demonstrates that `unsafe` code blocks can still introduce serious bugs that

critical

Critical Heap Buffer Overflow in SSDP Control Point: How Unbounded String Operations Put Networks at Risk

A critical heap buffer overflow vulnerability was discovered and patched in the SSDP control point implementation (`ssdp_ctrlpt.c`), where multiple unbounded `strcpy` and `strcat` operations constructed HTTP request buffers without any length validation. Network-received SSDP response fields — including service type strings and location URLs — could be crafted by an attacker to exceed buffer boundaries, potentially enabling arbitrary code execution or denial of service. The fix replaces the unsa

critical

Heap Buffer Overflow in OPDS Parser: How a Misplaced Variable Nearly Opened the Door to Remote Code Execution

A critical heap buffer overflow vulnerability was discovered in `lib/OpdsParser/OpdsParser.cpp`, where the buffer allocation size was calculated *after* a fixed chunk size was used to allocate memory, meaning the actual bytes read could exceed the allocated buffer. On embedded devices parsing untrusted OPDS catalog data from the network, this flaw could allow a remote attacker to corrupt heap memory and potentially achieve arbitrary code execution. The fix was elegantly simple: move the `toRead`