GHSA-4H7H-RV7C-7M2V
Vulnerability from github – Published: 2026-11-12 23:30 – Updated: 2026-11-12 23:30Summary
validator('form') only recognizes a multipart/form-data Content-Type that carries nothing but a single boundary parameter. A request with another legal parameter, such as charset, or with extra whitespace after the ; is not recognized as a form. The validation callback then receives an empty object, while c.req.parseBody() still parses the body as a form.
Details
The check that decides whether a request body is a form was written as a strict pattern over the whole Content-Type value. Any parameter list that does not look exactly like ; boundary=... fails the check. When it fails, the middleware does not read the body and passes an empty object to the validation callback. If the callback accepts an empty object, the request proceeds to the handler, which can still read all submitted fields through c.req.parseBody() or c.req.formData().
application/x-www-form-urlencoded is not affected. Only the multipart/form-data branch has the strict pattern.
This issue arises when an application relies on validator('form') to reject or restrict fields and the validation callback does not fail on an empty object.
Impact
An unauthenticated client can send form fields that the form validator never sees, by adding a legal parameter to the Content-Type header.
This may lead to:
- Allow-list or required-field checks in the validator being skipped
- Fields the application intended to reject reaching the handler
This issue affects applications that use validator('form') with multipart/form-data requests and whose validation callback accepts an empty object.
Workarounds
Reject an empty object in the validator('form') callback, or validate the result of await c.req.parseBody() in the handler.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.13.15"
},
"package": {
"ecosystem": "npm",
"name": "hono"
},
"ranges": [
{
"events": [
{
"introduced": "4.5.1"
},
{
"fixed": "4.13.16"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-126356"
],
"database_specific": {
"cwe_ids": [
"CWE-1471",
"CWE-20"
],
"github_reviewed": true,
"github_reviewed_at": "2026-11-12T23:30:45Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\n\n`validator(\u0027form\u0027)` only recognizes a `multipart/form-data` `Content-Type` that carries nothing but a single `boundary` parameter. A request with another legal parameter, such as `charset`, or with extra whitespace after the `;` is not recognized as a form. The validation callback then receives an empty object, while `c.req.parseBody()` still parses the body as a form.\n\n### Details\n\nThe check that decides whether a request body is a form was written as a strict pattern over the whole `Content-Type` value. Any parameter list that does not look exactly like `; boundary=...` fails the check. When it fails, the middleware does not read the body and passes an empty object to the validation callback. If the callback accepts an empty object, the request proceeds to the handler, which can still read all submitted fields through `c.req.parseBody()` or `c.req.formData()`.\n\n`application/x-www-form-urlencoded` is not affected. Only the `multipart/form-data` branch has the strict pattern.\n\nThis issue arises when an application relies on `validator(\u0027form\u0027)` to reject or restrict fields and the validation callback does not fail on an empty object.\n\n### Impact\n\nAn unauthenticated client can send form fields that the `form` validator never sees, by adding a legal parameter to the `Content-Type` header.\n\nThis may lead to:\n\n- Allow-list or required-field checks in the validator being skipped\n- Fields the application intended to reject reaching the handler\n\nThis issue affects applications that use `validator(\u0027form\u0027)` with `multipart/form-data` requests and whose validation callback accepts an empty object.\n\n### Workarounds\n\nReject an empty object in the `validator(\u0027form\u0027)` callback, or validate the result of `await c.req.parseBody()` in the handler.",
"id": "GHSA-4h7h-rv7c-7m2v",
"modified": "2026-11-12T23:30:45Z",
"published": "2026-11-12T23:30:45Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/honojs/hono/security/advisories/GHSA-4h7h-rv7c-7m2v"
},
{
"type": "WEB",
"url": "https://github.com/honojs/hono/commit/d88fab372415277a9e540e895650943dd08eef4a"
},
{
"type": "PACKAGE",
"url": "https://github.com/honojs/hono"
},
{
"type": "WEB",
"url": "https://github.com/honojs/hono/releases/tag/v4.13.16"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Hono: `validator(\u0027form\u0027)` skips validation for `multipart/form-data` requests with extra parameters"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
How durations are calculated
Following the VTEM framework (Black Hat USA 2015), time to patch starts when the vendor or a coordinator was informed, total time to patch at discovery, and disclosure to patch at public disclosure; vendor response time runs from the report to its acknowledgement. Time to exploit and time unpatched start at the earliest discovery or report, falling back to public disclosure. Unpatched time ends at the first recorded patch, or the calculation time when no patch is recorded. Exploitation to patch shows the interval between those two events; a published proof of concept is a public exploit, not exploitation.
Each result shows its source dates. A negative interval means the end event came first; when date-only inputs leave the order open, the result says so. Date-only inputs are approximate. The earliest evidence wins: KEV report dates and sightings are labelled as such. Records describing another vulnerability are listed but never calculated from, and a PoC alone does not establish exploitation. Missing patch evidence does not prove that no patch exists. Filters below change the event list only.
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.