{"record":{"id":"931a75d43a797acf","repo":"abhigyanpatwari/GitNexus","slug":"invalid-content-length-header-from-mcp-client","errorCode":null,"errorMessage":"Invalid Content-Length header from MCP client","messagePattern":"Invalid Content-Length header from MCP client","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/mcp/compatible-stdio-transport.ts","lineNumber":152,"sourceCode":"    const header = findHeaderEnd(this._readBuffer);\n    if (header === null) {\n      return null;\n    }\n\n    const headerText = this._readBuffer\n      .toString('utf8', 0, header.index)\n      .replace(/\\r\\n/g, '\\n')\n      .replace(/\\r/g, '\\n');\n    const match = headerText.match(/(?:^|\\n)content-length\\s*:\\s*(\\d+)/i);\n    if (!match) {\n      this.discardBufferedInput();\n      throw new Error('Missing Content-Length header from MCP client');\n    }\n\n    const contentLength = Number.parseInt(match[1], 10);\n    if (!Number.isFinite(contentLength) || contentLength < 0) {\n      this.discardBufferedInput();\n      throw new Error('Invalid Content-Length header from MCP client');\n    }\n    if (contentLength > MAX_BUFFER_SIZE) {\n      this.discardBufferedInput();\n      throw new Error(\n        `Content-Length ${contentLength} exceeds maximum allowed size (${MAX_BUFFER_SIZE} bytes)`,\n      );\n    }\n    const bodyStart = header.index + header.separatorLength;\n    const bodyEnd = bodyStart + contentLength;\n    if (this._readBuffer.length < bodyEnd) {\n      return null;\n    }\n\n    const body = this._readBuffer.toString('utf8', bodyStart, bodyEnd);\n    this._readBuffer = this._readBuffer.subarray(bodyEnd);\n    return deserializeMessage(body);\n  }\n","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/aac7515d2a8c50a1f8f923c6fb77218b333560d6/gitnexus/src/mcp/compatible-stdio-transport.ts#L134-L170","documentation":"Defensive validation in the stdio transport's frame parser: after the content-length regex captures a digit run, the value must parse to a finite, non-negative integer. Because the regex only captures \\d+, ordinary malformed headers fail earlier as 'Missing Content-Length header'; this branch catches degenerate values such as a digit string so long that parseInt yields Infinity.","triggerScenarios":"Corrupted or fuzzed stdin bytes that happen to form a header terminator plus a content-length line with an astronomically long digit run (overflowing Number to Infinity); a broken client or test harness computing the header value in a way that produces a non-representable number; memory-corrupted pipes writing garbage.","commonSituations":"Fuzzing the transport with random bytes; a client bug that stringifies NaN/Infinity into a length computation despite the digit-only regex; almost never seen with SDK-based clients — its appearance almost always indicates a broken hand-rolled client or corrupted stream.","solutions":["Fix the client to compute Content-Length from Buffer.byteLength of the serialized body and to validate Number.isFinite before writing.","Replace hand-rolled framing with the official MCP SDK transport.","Restart the session: the parser already discarded all buffered input, so the connection state is unrecoverable.","If fuzzing/testing intentionally, feed well-formed frames instead."],"exampleFix":"// before: length computed from a possibly non-finite value\nconst len = maybeCorruptedCounter;\nsock.write(`Content-Length: ${len}\\r\\n\\r\\n` + body);\n\n// after: derive from serialized bytes and validate before writing\nconst buf = Buffer.from(JSON.stringify(msg), 'utf8');\nif (!Number.isFinite(buf.length) || buf.length < 0) throw new Error('bad length');\nsock.write(`Content-Length: ${buf.length}\\r\\n\\r\\n`);\nsock.write(buf);","handlingStrategy":"validation","validationCode":"// Validate a length before it ever reaches the wire\nfunction frame(msg: unknown): Buffer {\n  const body = Buffer.from(JSON.stringify(msg), 'utf8');\n  const len = body.length;\n  if (!Number.isFinite(len) || len < 0 || !Number.isInteger(len)) {\n    throw new Error(`computed invalid Content-Length: ${len}`);\n  }\n  return Buffer.concat([Buffer.from(`Content-Length: ${len}\\r\\n\\r\\n`), body]);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await transport.handleData(chunk);\n} catch (err) {\n  const msg = err instanceof Error ? err.message : String(err);\n  if (msg.includes('Invalid Content-Length')) {\n    // stream already discarded — treat the session as corrupt and restart it\n    await restartMcpSession();\n    return;\n  }\n  throw err;\n}","preventionTips":["Derive Content-Length only from byte counts of the serialized payload.","Assert Number.isFinite on any computed protocol field before writing it.","Keep fuzz tests away from production transports, or feed only well-formed frames."],"tags":["mcp","stdio-transport","content-length","protocol","defensive-check"],"backgroundTag":"invalid-content-length-header","analyzedSha":"aac7515d2a8c50a1f8f923c6fb77218b333560d6","analyzedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}