Aug 22, 2026·6 min read·44 visits
Unauthenticated remote attackers can crash servers using getkin/kin-openapi (v0.10.0 to v0.140.0) by transmitting a malformed multipart/form-data request, triggering a nil-pointer dereference panic in the error validation encoder.
CVE-2026-76905 is a high-severity Denial of Service (DoS) vulnerability in the getkin/kin-openapi library, specifically inside the openapi3filter sub-package. When processing multipart/form-data request validation errors, a missing nil-pointer guard causes a Go runtime panic during error formatting. This panic terminates the active server process if no recovery handler is present, resulting in a total denial of service. The vulnerability affects versions from v0.10.0 to v0.140.0, and is resolved in v0.141.0.
The getkin/kin-openapi library is a standard tool in the Go ecosystem for validating, parsing, and verifying HTTP traffic against OpenAPI specification files. Within this ecosystem, the openapi3filter sub-package is frequently implemented as request-validation middleware. This middleware exposes an attack surface to arbitrary remote inputs, parsing request parameters and incoming message bodies before handing them off to downstream controllers.
When openapi3filter encounters a schema discrepancy, it constructs a structural parsing or validation error representation. Downstream services routinely invoke validation helpers such as openapi3filter.ConvertErrors or the ValidationErrorEncoder to translate these internally generated validation errors into client-facing JSON objects. This conversion step acts as the precise point of failure.
The underlying security issue resides within the error translation logic. During parsing of certain complex payloads, the translation routine attempts to access properties of structural references that were never initialized. This logic gap results in a NULL pointer dereference, classified under CWE-476. The vulnerability manifests when formatting validation errors for malformed requests.
The bug is located within the convertParseError helper function inside openapi3filter/validation_error_encoder.go. The validation subsystem defines a core struct named RequestError which maintains metadata regarding the validation failure context. A RequestError can point to parameter-based input violations or body-based input violations, but never both simultaneously.
When a request body is validated (such as a multipart or JSON structure), the parameter validation struct member e.Parameter is explicitly initialized as nil. However, if the error relates to a URI query parameter, e.Parameter contains a reference to the active parameter specification. This logic expects downstream code paths to respect the optional nature of this property.
During multipart/form-data processing, a non-string and non-numeric scalar field that violates schema type guidelines yields a nested structure containing an outer *ParseError wrapping an inner core failure. This nesting triggers a specific code branch in convertParseError that attempts to verify whether the root cause represents an invalid query parameter format.
The logic attempts to evaluate rootErr.Kind == KindInvalidFormat && e.Parameter.In == "query". Because the validation error originated inside the request body, e.Parameter is nil. When the engine attempts to evaluate e.Parameter.In, it dereferences a NULL pointer, throwing a panic that is not recovered inside the validation library itself.
Analyzing the vulnerable logic before and after commit 1d0a337c9b1570fab283be8a04c8af6e43b9a22c reveals the exact structural fault and its corrective patch.
Prior to the patch, the vulnerability in openapi3filter/validation_error_encoder.go was structured as follows:
func convertParseError(e *RequestError, innerErr *ParseError) *ValidationError {
// ...
} else if innerErr.RootCause() != nil {
// e.Parameter is dereferenced directly without verifying if it is nil
if rootErr, ok := innerErr.Cause.(*ParseError); ok &&
rootErr.Kind == KindInvalidFormat && e.Parameter.In == "query" {
return &ValidationError{
Status: http.StatusBadRequest,
Title: fmt.Sprintf("parameter %q in %s is invalid: %v is %s",
e.Parameter.Name, e.Parameter.In, rootErr.Value, rootErr.Reason),
}
}
return &ValidationError{
Status: http.StatusBadRequest,
Title: innerErr.Reason,
}
}
return nil
}The corresponding patch introduces a strict logical boundary that prevents NULL dereferencing. It updates the conditional branch using Go's short-circuit evaluation behavior:
func convertParseError(e *RequestError, innerErr *ParseError) *ValidationError {
} else if innerErr.RootCause() != nil {
if rootErr, ok := innerErr.Cause.(*ParseError); ok &&
- rootErr.Kind == KindInvalidFormat && e.Parameter.In == "query" {
+ rootErr.Kind == KindInvalidFormat && e.Parameter != nil && e.Parameter.In == "query" {
return &ValidationError{
Status: http.StatusBadRequest,
Title: fmt.Sprintf("parameter %q in %s is invalid: %v is %s",
e.Parameter.Name, e.Parameter.In, rootErr.Value, rootErr.Reason),
}
}
+ // For body parse errors (e.Parameter == nil) the outer ParseError's
+ // Reason is often empty, e.g. the multipart decoder wraps a part's
+ // *ParseError without setting one. Fall back to the full error text so
+ // the response still carries a meaningful message.
+ title := innerErr.Reason
+ if title == "" {
+ title = innerErr.Error()
+ }
return &ValidationError{
Status: http.StatusBadRequest,
- Title: innerErr.Reason,
+ Title: title,
}
}
return nil
}By placing e.Parameter != nil before e.Parameter.In == "query", any body-based request error causes the logical evaluation of the if statement to fail immediately. The engine skips evaluating the properties of the nil reference, neutralizing the panic. The added fallback title formatting ensures that body-parsing errors return a valid description.
Exploiting CVE-2026-76905 requires a simple delivery sequence. The targeted application must process validation errors using openapi3filter.ConvertErrors or ValidationErrorEncoder to process user input failures.
The attack is initiated by submitting a multipart request containing a data representation error. The targeted API endpoint must be configured to process multipart/form-data with an OpenAPI schema containing a non-string or non-boolean scalar (e.g., an integer). The attacker transmits a payload containing a non-numeric string where the integer value is expected.
POST /v1/upload HTTP/1.1
Host: target-api.internal
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXyZ
Content-Length: 185
------WebKitFormBoundaryXyZ
Content-Disposition: form-data; name="age"
notanumber
------WebKitFormBoundaryXyZ--Upon processing the boundary parts, the server's internal parser fails to map "notanumber" to an integer object. It initializes a nested ParseError containing the structural failure but omits the initialization of e.Parameter. When the app formats the failure with ConvertErrors, the service dereferences e.Parameter, throwing a panic that shuts down the entire thread.
The primary impact is service unavailability. A single, small payload containing a malformed boundary value can terminate the active server process.
In Go, unrecovered panics are fatal. Unlike languages where exceptions are confined to localized runtime execution spaces, a Go panic that escapes the active HTTP routine halts the parent process. This results in an absolute Denial of Service (DoS) for all clients interacting with the system.
The vulnerability does not allow remote code execution, file system access, or privilege escalation. It has a CVSS v3.1 score of 7.5, reflecting a network-exploitable vector that requires low complexity and no special privilege states. The absence of data leakage or execution control limits the scope to availability.
The definitive remediation for CVE-2026-76905 is updating the dependency version of github.com/getkin/kin-openapi to version v0.141.0 or higher.
If upgrading is not immediately possible, implement a structural panic-recovery middleware block. This wrapper catches escaped runtime panics and maps them to a normal HTTP error state, such as a 500 Internal Server Error, protecting the parent process.
func PanicRecoveryMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
// Prevent server shutdown by catching the runtime error
log.Printf("[SECURITY] Recovered from validation panic: %v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"error":"Internal Server Error"}`))
}
}()
next.ServeHTTP(w, r)
})
}Additionally, validation processes can be modified to bypass calling ConvertErrors() when formatting incoming schema issues. Instead, check the error type directly in user code to generate client responses safely.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
github.com/getkin/kin-openapi getkin | >= 0.10.0, < 0.141.0 | v0.141.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-476 |
| Attack Vector | Network |
| CVSS Score | 7.5 |
| EPSS Percentile | N/A |
| Impact | Denial of Service (DoS) |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
A NULL pointer dereference occurs when the application attempts to read or write to a memory address assumed to be valid but is instead NULL, triggering a crash.
Payload CMS was discovered to use an insecure default configuration for its password-hashing mechanism. The system requested a 512-byte key from PBKDF2-HMAC-SHA256 with 25,000 iterations, creating a severe cryptographic asymmetry. While the defending server sequentially computed 16 blocks of key material (equivalent to 400,000 internal iterations), an offline attacker only needed to compute the first 32-byte block to verify password guesses. This allowed offline attackers to crack stolen database hashes 16 times faster than intended by the security design.
VectorFreed identifies a critical Use-After-Free (UAF) memory corruption vulnerability in librsvg (CVE-2026-96889), which manifests when parsing structured SVG documents containing nested XML inclusions (XIncludes) and duplicate entity declarations. The flaw results from an entity ownership conflict where librsvg prematurely deallocates an xmlEntity structure still actively referenced by the underlying libxml2 parser context. When transitively compiled into downstream applications such as the high-performance sharp image processing library, this vulnerability facilitates denial of service and unauthenticated remote code execution on the host operating system.
CVE-2026-102275 (GHSA-x33g-cr3x-6449) is a public/private key identity confusion vulnerability in PyJWT versions 2.1.0 through 2.14.0. When importing Octet Key Pair (OKP) JSON Web Keys (JWKs) representing Ed25519 or Ed448 curves, PyJWT fails to verify that the public parameter 'x' matches the private parameter 'd'. An attacker can construct a hybrid JWK combining a victim's public key with the attacker's private key. In protocols like DPoP that bind sessions via public key thumbprints, this allows the attacker to authenticate as the victim while signing proofs with their own private key, fully bypassing sender-constrained security guarantees.
An authentication bypass and privilege escalation vulnerability exists in Filament (filamentphp/filament) due to missing password verification during multi-factor authentication (MFA) setup and management. An attacker with access to an active session can modify or disable MFA, leading to account hijacking.
A critical Denial of Service (DoS) vulnerability exists in @socket.io/cluster-engine before version 0.1.1. Unauthenticated remote attackers can crash the server process by supplying inherited prototype property names as session identifiers.
A vulnerability in the Client-Side Field-Level Encryption (CSFLE) component of the MongoDB Python Driver (PyMongo) allows an attacker with database write access to trigger local Unix domain socket connections. By manipulating the Key Management Service (KMS) endpoint configuration inside the key vault collection to end with a '.sock' extension, an attacker forces the application to perform a Server-Side Request Forgery (SSRF) against internal Unix domain sockets.