{"id":"GHSA-92p4-j3wq-jmqx","kind":"vulnerability","aliases":["GHSA-92p4-j3wq-jmqx"],"related":[],"title":"`validator()` skips validation for requests whose `Content-Type` parameters are formatted differently (incomplete fix for GHSA-4h7h-rv7c-7m2v)","description":"### Summary\n\n`validator('json')` and `validator('form')` decide whether to read the request body by matching the whole `Content-Type` value against a strict pattern. A value that is legal but formatted differently, such as whitespace before `;`, a trailing `;`, or a parameter name with an underscore, does not match. The validation callback then receives an empty object, while `c.req.json()` and `c.req.parseBody()` in the handler still read the body.\n\nGHSA-4h7h-rv7c-7m2v fixed this for a `multipart/form-data` value with extra parameters. The same problem remained for other parameter formats and for `application/json`.\n\n### Details\n\nThe media type and its parameters were checked together with one pattern per target. Anything outside the pattern, including `application/json ; charset=utf-8`, `multipart/form-data; boundary=x;` and `application/x-www-form-urlencoded; x_y=1`, failed 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 read all submitted fields.\n\nThe validator now takes the media type as the part before the first `;`, trimmed and lowercased, and decides on that alone. This is the same rule `c.req.parseBody()` uses, so the two can no longer disagree about the same request. Structured JSON suffixes such as `application/vnd.api+json` and subtypes containing digits are accepted as JSON.\n\nThis issue arises when an application relies on `validator('json')` or `validator('form')` 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 JSON or form fields that the validator never sees, by formatting the `Content-Type` header differently.\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('json')` or `validator('form')` and whose validation callback accepts an empty object.","summary":"Hono's validator('json') and validator('form') middleware fail to read the request body when the Content-Type header is legal but formatted differently, such as extra whitespace or a trailing semicolon. The validation callback then receives an empty object while the handler still reads the full body, so an attacker can send fields the validator was meant to reject.","severity":"medium","cvss":5.3,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"hono","fixed":["4.13.18"],"affected":">= 4.5.1, <= 4.13.17","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["api","cwe-20","hono","node","npm","package"],"not_affected_if":["callback-rejects-empty-object","hono-outside-affected-range","no-json-or-form-validator"],"how_to_check":"- Check the installed Hono version: `npm ls hono`\n- Search the code for `validator('json')` or `validator('form')` and confirm whether the callback rejects or restricts fields or accepts an empty object\n- Look for allow-list or required-field checks that depend only on the validator","fix":"- hono: move to `4.13.18`","status":"open","published_at":"2026-11-11T08:54:55+00:00","first_seen_at":"2026-11-11T08:59:08+00:00","triaged_at":"2026-11-11T09:01:19+00:00","updated_at":"2026-11-11T09:01:19+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-11T09:01:19Z","model":"claude-haiku-5-5","output":{"fix":"- hono: move to `4.13.18`","reach":"internet","title":"Hono: validator skips body checks when Content-Type parameters are formatted differently","impact":"medium","summary":"Hono's validator('json') and validator('form') middleware fail to read the request body when the Content-Type header is legal but formatted differently, such as extra whitespace or a trailing semicolon. The validation callback then receives an empty object while the handler still reads the full body, so an attacker can send fields the validator was meant to reject.","audience":"developers","category":"package","nicknames":[],"who_cares":["hono","node","npm","api"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"unvalidated fields reach the handler and bypass allow-list checks","analyst_note":"","how_to_check":"- Check the installed Hono version: `npm ls hono`\n- Search the code for `validator('json')` or `validator('form')` and confirm whether the callback rejects or restricts fields or accepts an empty object\n- Look for allow-list or required-field checks that depend only on the validator","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["no-json-or-form-validator","callback-rejects-empty-object","hono-outside-affected-range"],"who_is_affected":"Applications built on Hono 4.5.1 through 4.13.17 that use validator('json') or validator('form') to reject or restrict fields, and whose validation callback accepts an empty object. Apps that do not use these validators, or whose callbacks fail on an empty object, are not exposed by this path.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000817,"input_tokens":5220,"output_tokens":591,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-20':35B '-8':217C '1':225C '4h7h':19A,171C '7m2v':21A,173C '92p4':24A,29A 'accept':251C,318C,414C 'affect':401C 'allow':378C 'allow-list':377C 'alon':287C 'anyth':209C 'api':33B 'applic':326C,392C,402C 'application/json':193C,214C 'application/vnd.api':311C 'application/x-www-form-urlencoded':222C 'aris':323C 'attack':91B 'bodi':53B,88B,113C,168C,238C 'boundari':219C 'c.req.json':159C 'c.req.parsebody':161C,293C 'callback':75B,152C,247C,250C,342C,413C 'charset':215C 'check':202C,228C,384C 'client':353C 'contain':315C 'content':8A,57B,119C,369C 'content-typ':7A,56B,118C,368C 'cwe':34B 'decid':107C,284C 'detail':194C 'differ':13A,64B,133C,372C 'digit':316C 'disagre':301C 'empti':79B,156C,242C,253C,348C,416C 'extra':67B,181C 'fail':48B,226C,231C,345C 'field':94B,266C,338C,359C,383C,390C 'first':279C 'fix':15A,174C 'form':46B,106C,333C,358C,409C 'format':12A,63B,132C,190C,366C 'full':87B 'ghsa':18A,23A,28A,170C 'ghsa-4h7h-rv7c-7m2v':17A,169C 'ghsa-92p4-j3wq-jmqx':22A,27A 'handler':83B,164C,260C,398C 'header':59B,371C 'hono':32A,36B,40B 'impact':350C 'includ':213C 'incomplet':14A 'intend':393C 'issu':322C,400C 'j3wq':25A,30A 'jmqx':26A,31A 'json':43B,103C,307C,312C,320C,330C,356C,406C 'lead':375C 'legal':61B,130C 'list':379C 'longer':300C 'lowercas':282C 'match':115C,149C 'may':374C 'meant':98B 'media':196C,272C 'middlewar':47B,233C 'multipart/form-data':178C,218C 'name':143C 'never':363C 'node':37B 'npm':38B 'object':80B,157C,243C,254C,349C,417C 'one':205C 'outsid':210C 'packag':39B 'paramet':10A,142C,182C,189C,200C 'part':276C 'pass':240C 'pattern':125C,206C,212C 'per':207C 'problem':185C 'proceed':257C 'reach':396C 'read':50B,85B,110C,166C,236C,263C 'receiv':77B,154C 'reject':100B,335C,395C 'reli':327C 'remain':186C 'request':5A,52B,112C,256C,305C 'requir':382C 'required-field':381C 'restrict':337C 'rule':292C 'rv7c':20A,172C 'see':364C 'semicolon':72B 'send':93B,355C 'skip':2A,389C 'still':84B,165C 'strict':124C 'structur':306C 'submit':265C 'subtyp':314C 'suffix':308C 'summari':101C 'take':270C 'target':208C 'togeth':203C 'trail':71B,139C 'trim':280C 'two':297C 'type':9A,58B,120C,197C,273C,370C 'unauthent':352C 'underscor':146C 'use':294C,404C 'utf':216C 'valid':1A,3A,42B,45B,74B,96B,102C,105C,151C,246C,268C,329C,332C,341C,362C,387C,405C,408C,412C 'valu':121C,127C,179C 'whether':108C 'whitespac':68B,136C 'whole':117C 'whose':6A,411C 'x':220C,223C 'y':224C","nicknames":[],"mitigations":[],"who_affected":"Applications built on Hono 4.5.1 through 4.13.17 that use validator('json') or validator('form') to reject or restrict fields, and whose validation callback accepts an empty object. Apps that do not use these validators, or whose callbacks fail on an empty object, are not exposed by this path.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["hono"],"ptokens":["hono"],"labels":["api","cwe20","hono","medium","node","npm","package"],"campaign_type":null,"search_a":"'4h7h':19A '7m2v':21A '92p4':24A,29A 'content':8A 'content-typ':7A 'differ':13A 'fix':15A 'format':12A 'ghsa':18A,23A,28A 'ghsa-4h7h-rv7c-7m2v':17A 'ghsa-92p4-j3wq-jmqx':22A,27A 'hono':32A 'incomplet':14A 'j3wq':25A,30A 'jmqx':26A,31A 'paramet':10A 'request':5A 'rv7c':20A 'skip':2A 'type':9A 'valid':1A,3A 'whose':6A","search_b":"'-20':35B 'api':33B 'attack':91B 'bodi':53B,88B 'callback':75B 'content':57B 'content-typ':56B 'cwe':34B 'differ':64B 'empti':79B 'extra':67B 'fail':48B 'field':94B 'form':46B 'format':63B 'full':87B 'handler':83B 'header':59B 'hono':36B,40B 'json':43B 'legal':61B 'meant':98B 'middlewar':47B 'node':37B 'npm':38B 'object':80B 'packag':39B 'read':50B,85B 'receiv':77B 'reject':100B 'request':52B 'semicolon':72B 'send':93B 'still':84B 'trail':71B 'type':58B 'valid':42B,45B,74B,96B 'whitespac':68B","search_c":"'-8':217C '1':225C '4h7h':171C '7m2v':173C 'accept':251C,318C,414C 'affect':401C 'allow':378C 'allow-list':377C 'alon':287C 'anyth':209C 'applic':326C,392C,402C 'application/json':193C,214C 'application/vnd.api':311C 'application/x-www-form-urlencoded':222C 'aris':323C 'bodi':113C,168C,238C 'boundari':219C 'c.req.json':159C 'c.req.parsebody':161C,293C 'callback':152C,247C,250C,342C,413C 'charset':215C 'check':202C,228C,384C 'client':353C 'contain':315C 'content':119C,369C 'content-typ':118C,368C 'decid':107C,284C 'detail':194C 'differ':133C,372C 'digit':316C 'disagre':301C 'empti':156C,242C,253C,348C,416C 'extra':181C 'fail':226C,231C,345C 'field':266C,338C,359C,383C,390C 'first':279C 'fix':174C 'form':106C,333C,358C,409C 'format':132C,190C,366C 'ghsa':170C 'ghsa-4h7h-rv7c-7m2v':169C 'handler':164C,260C,398C 'header':371C 'impact':350C 'includ':213C 'intend':393C 'issu':322C,400C 'json':103C,307C,312C,320C,330C,356C,406C 'lead':375C 'legal':130C 'list':379C 'longer':300C 'lowercas':282C 'match':115C,149C 'may':374C 'media':196C,272C 'middlewar':233C 'multipart/form-data':178C,218C 'name':143C 'never':363C 'object':157C,243C,254C,349C,417C 'one':205C 'outsid':210C 'paramet':142C,182C,189C,200C 'part':276C 'pass':240C 'pattern':125C,206C,212C 'per':207C 'problem':185C 'proceed':257C 'reach':396C 'read':110C,166C,236C,263C 'receiv':154C 'reject':335C,395C 'reli':327C 'remain':186C 'request':112C,256C,305C 'requir':382C 'required-field':381C 'restrict':337C 'rule':292C 'rv7c':172C 'see':364C 'send':355C 'skip':389C 'still':165C 'strict':124C 'structur':306C 'submit':265C 'subtyp':314C 'suffix':308C 'summari':101C 'take':270C 'target':208C 'togeth':203C 'trail':139C 'trim':280C 'two':297C 'type':120C,197C,273C,370C 'unauthent':352C 'underscor':146C 'use':294C,404C 'utf':216C 'valid':102C,105C,151C,246C,268C,329C,332C,341C,362C,387C,405C,408C,412C 'valu':121C,127C,179C 'whether':108C 'whitespac':136C 'whole':117C 'whose':411C 'x':220C,223C 'y':224C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-11T08:54:55+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-92p4-j3wq-jmqx","url":"https://github.com/honojs/hono/security/advisories/GHSA-92p4-j3wq-jmqx","severity":"medium","published_at":"2026-11-11T08:54:55+00:00","modified_at":"2026-11-11T08:54:56+00:00","first_seen_at":"2026-11-11T08:59:08+00:00","fetched_at":"2026-11-11T08:59:08+00:00","note":null}],"documents":[{"id":124179,"url":"https://github.com/honojs/hono/security/advisories/GHSA-92p4-j3wq-jmqx","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}