{"id":"GHSA-39q9-qp46-w8xg","kind":"vulnerability","aliases":["GHSA-39q9-qp46-w8xg"],"related":[],"title":"`bodyLimit()` keeps every transfer chunk of a request body in memory, allowing memory exhaustion with tiny chunks","description":"### Summary\n\nSince 4.12.16, `bodyLimit()` reads the whole request body before the handler runs so that the limit also applies to chunked requests. It kept every chunk delivered by the runtime as a separate array and later replayed them. A client that sends the body in very small transfer chunks makes the middleware retain millions of small arrays for a body that is within the configured limit. The memory used is many times the body size, and the process can be terminated before the handler runs.\n\n### Details\n\nThe size check counted the payload bytes correctly, so the configured `maxSize` was respected. The problem is the per-chunk overhead: each `Uint8Array` the runtime delivers was kept as its own object until the body was complete, then enqueued again into a new stream. With one-byte HTTP transfer chunks, a 10 MiB upload becomes about ten million retained objects.\n\n`bodyLimit()` now copies the incoming chunks into one buffer that grows up to `maxSize`, and forwards that buffer as the request body. Memory use is bounded by the configured limit regardless of how the body is chunked.\n\nObserved on Bun and Node.js, where the HTTP parser delivers transfer chunks as they arrive.\n\n### Impact\n\nAn unauthenticated client can exhaust the memory of a server that uses `bodyLimit()` with a single request that stays within the configured limit, terminating the process.\n\nThis issue affects applications that use `bodyLimit()` on runtimes that deliver small transfer chunks individually, such as Bun and Node.js.","summary":"Hono's bodyLimit() middleware from 4.12.16 stores each transfer chunk of a request body as a separate object before the handler runs. A single unauthenticated request sending the body in very small chunks can use many times its size in memory and crash the process.","severity":"medium","cvss":5.3,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"hono","fixed":["4.13.18"],"affected":">= 4.12.16, <= 4.13.17","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["bun","cwe-400","hono","node","package","self-hosted"],"not_affected_if":["no-bodylimit","version-outside-range"],"how_to_check":"- Check the installed version with `npm ls hono` and confirm it is between `4.12.16` and `4.13.17`.\n- Search the codebase for `bodyLimit(` to see whether the middleware is used.","fix":"- `hono` moves to `4.13.18` (fixed version per the advisory data).","status":"open","published_at":"2026-11-11T08:54:36+00:00","first_seen_at":"2026-11-11T08:59:08+00:00","triaged_at":"2026-11-11T09:01:18+00:00","updated_at":"2026-11-11T09:01:18+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-11T09:01:18Z","model":"claude-haiku-5-5","output":{"fix":"- `hono` moves to `4.13.18` (fixed version per the advisory data).","reach":"internet","title":"Hono: bodyLimit() keeps every tiny chunk in memory, exhausting server memory","impact":"medium","summary":"Hono's bodyLimit() middleware from 4.12.16 stores each transfer chunk of a request body as a separate object before the handler runs. A single unauthenticated request sending the body in very small chunks can use many times its size in memory and crash the process.","audience":"developers","category":"package","nicknames":[],"who_cares":["hono","node","bun","self-hosted"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"unauthenticated client crashes the server process by exhausting memory","analyst_note":"","how_to_check":"- Check the installed version with `npm ls hono` and confirm it is between `4.12.16` and `4.13.17`.\n- Search the codebase for `bodyLimit(` to see whether the middleware is used.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["no-bodylimit","version-outside-range"],"who_is_affected":"Applications built on Hono that use the bodyLimit() middleware to cap request body size, on runtimes such as Bun and Node.js that deliver small transfer chunks individually. Apps that do not use bodyLimit(), or that run on versions outside the affected range, are not exposed.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000767,"input_tokens":5035,"output_tokens":528,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-400':31B '10':222C '39q9':20A,25A '4.12.16':43B,85C 'affect':312C 'allow':12A 'also':100C 'appli':101C 'applic':313C 'array':116C,139C 'arriv':282C 'becom':225C 'bodi':9A,51B,66B,91C,126C,142C,156C,204C,252C,265C 'bodylimit':1A,40B,86C,231C,296C,316C 'bound':256C 'buffer':239C,248C 'bun':29B,270C,327C 'byte':175C,217C 'check':171C 'chunk':5A,17A,47B,70B,103C,108C,131C,189C,220C,236C,267C,279C,323C 'client':122C,286C 'complet':206C 'configur':147C,179C,259C,305C 'copi':233C 'correct':176C 'count':172C 'crash':80B 'cwe':30B 'deliv':109C,195C,277C,320C 'detail':168C 'enqueu':208C 'everi':3A,107C 'exhaust':14A,288C 'forward':246C 'ghsa':19A,24A 'ghsa-39q9-qp46-w8xg':18A,23A 'grow':241C 'handler':58B,94C,166C 'hono':28A,32B,38B 'host':37B 'http':218C,275C 'impact':283C 'incom':235C 'individu':324C 'issu':311C 'keep':2A 'kept':106C,197C 'later':118C 'limit':99C,148C,260C,306C 'make':132C 'mani':73B,153C 'maxsiz':180C,244C 'memori':11A,13A,78B,150C,253C,290C 'mib':223C 'middlewar':41B,134C 'million':136C,228C 'new':212C 'node':33B 'node.js':272C,329C 'object':55B,201C,230C 'observ':268C 'one':216C,238C 'one-byt':215C 'overhead':190C 'packag':34B 'parser':276C 'payload':174C 'per':188C 'per-chunk':187C 'problem':184C 'process':82B,160C,309C 'qp46':21A,26A 'read':87C 'regardless':261C 'replay':119C 'request':8A,50B,63B,90C,104C,251C,300C 'respect':182C 'retain':135C,229C 'run':59B,95C,167C 'runtim':112C,194C,318C 'self':36B 'self-host':35B 'send':64B,124C 'separ':54B,115C 'server':293C 'sinc':84C 'singl':61B,299C 'size':76B,157C,170C 'small':69B,129C,138C,321C 'stay':302C 'store':44B 'stream':213C 'summari':83C 'ten':227C 'termin':163C,307C 'time':74B,154C 'tini':16A 'transfer':4A,46B,130C,219C,278C,322C 'uint8array':192C 'unauthent':62B,285C 'upload':224C 'use':72B,151C,254C,295C,315C 'w8xg':22A,27A 'whole':89C 'within':145C,303C","nicknames":[],"mitigations":[],"who_affected":"Applications built on Hono that use the bodyLimit() middleware to cap request body size, on runtimes such as Bun and Node.js that deliver small transfer chunks individually. Apps that do not use bodyLimit(), or that run on versions outside the affected range, are not exposed.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["hono"],"ptokens":["hono"],"labels":["bun","cwe400","hono","medium","node","npm","package","selfhosted"],"campaign_type":null,"search_a":"'39q9':20A,25A 'allow':12A 'bodi':9A 'bodylimit':1A 'chunk':5A,17A 'everi':3A 'exhaust':14A 'ghsa':19A,24A 'ghsa-39q9-qp46-w8xg':18A,23A 'hono':28A 'keep':2A 'memori':11A,13A 'qp46':21A,26A 'request':8A 'tini':16A 'transfer':4A 'w8xg':22A,27A","search_b":"'-400':31B '4.12.16':43B 'bodi':51B,66B 'bodylimit':40B 'bun':29B 'chunk':47B,70B 'crash':80B 'cwe':30B 'handler':58B 'hono':32B,38B 'host':37B 'mani':73B 'memori':78B 'middlewar':41B 'node':33B 'object':55B 'packag':34B 'process':82B 'request':50B,63B 'run':59B 'self':36B 'self-host':35B 'send':64B 'separ':54B 'singl':61B 'size':76B 'small':69B 'store':44B 'time':74B 'transfer':46B 'unauthent':62B 'use':72B","search_c":"'10':222C '4.12.16':85C 'affect':312C 'also':100C 'appli':101C 'applic':313C 'array':116C,139C 'arriv':282C 'becom':225C 'bodi':91C,126C,142C,156C,204C,252C,265C 'bodylimit':86C,231C,296C,316C 'bound':256C 'buffer':239C,248C 'bun':270C,327C 'byte':175C,217C 'check':171C 'chunk':103C,108C,131C,189C,220C,236C,267C,279C,323C 'client':122C,286C 'complet':206C 'configur':147C,179C,259C,305C 'copi':233C 'correct':176C 'count':172C 'deliv':109C,195C,277C,320C 'detail':168C 'enqueu':208C 'everi':107C 'exhaust':288C 'forward':246C 'grow':241C 'handler':94C,166C 'http':218C,275C 'impact':283C 'incom':235C 'individu':324C 'issu':311C 'kept':106C,197C 'later':118C 'limit':99C,148C,260C,306C 'make':132C 'mani':153C 'maxsiz':180C,244C 'memori':150C,253C,290C 'mib':223C 'middlewar':134C 'million':136C,228C 'new':212C 'node.js':272C,329C 'object':201C,230C 'observ':268C 'one':216C,238C 'one-byt':215C 'overhead':190C 'parser':276C 'payload':174C 'per':188C 'per-chunk':187C 'problem':184C 'process':160C,309C 'read':87C 'regardless':261C 'replay':119C 'request':90C,104C,251C,300C 'respect':182C 'retain':135C,229C 'run':95C,167C 'runtim':112C,194C,318C 'send':124C 'separ':115C 'server':293C 'sinc':84C 'singl':299C 'size':157C,170C 'small':129C,138C,321C 'stay':302C 'stream':213C 'summari':83C 'ten':227C 'termin':163C,307C 'time':154C 'transfer':130C,219C,278C,322C 'uint8array':192C 'unauthent':285C 'upload':224C 'use':151C,254C,295C,315C 'whole':89C 'within':145C,303C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-11T08:54:36+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-39q9-qp46-w8xg","url":"https://github.com/honojs/hono/security/advisories/GHSA-39q9-qp46-w8xg","severity":"medium","published_at":"2026-11-11T08:54:36+00:00","modified_at":"2026-11-11T08:54:36+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":124180,"url":"https://github.com/honojs/hono/security/advisories/GHSA-39q9-qp46-w8xg","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"}