fix: sanitize Buffer and long string output in CLI/MCP logging

Buffer instances (from screenshots, PDFs, responses) were dumping hundreds of
chars of hex bytes via util.inspect. Long strings nested in objects (base64,
HTML) also wasted context window space.

- Add Buffer.prototype[util.inspect.custom] in all entry points (cli, mcp,
  cdp-relay) so Buffers display as '<Buffer N bytes>' instead of hex dumps
- Add maxStringLength: 1000 to all util.inspect calls so strings inside
  inspected objects get capped (top-level strings are untouched, the existing
  10k char overall truncation handles those)
This commit is contained in:
Tommy D. Rossi
2026-02-16 20:03:36 +01:00
parent 44370833f7
commit 55be6ec840
5 changed files with 24 additions and 3 deletions
+7
View File
@@ -17,6 +17,13 @@ import type {
IsRecordingParams,
} from './protocol.js'
import pc from 'picocolors'
import util from 'node:util'
// Prevent Buffers from dumping hex bytes in util.inspect output.
Buffer.prototype[util.inspect.custom] = function () {
return `<Buffer ${this.length} bytes>`
}
import { EventEmitter } from 'node:events'
import { VERSION, EXTENSION_IDS } from './utils.js'
import { createCdpLogger, type CdpLogEntry, type CdpLogger } from './cdp-log.js'
+6
View File
@@ -2,8 +2,14 @@
import fs from 'node:fs'
import path from 'node:path'
import util from 'node:util'
import { fileURLToPath } from 'node:url'
import { cac } from '@xmorse/cac'
// Prevent Buffers from dumping hex bytes in util.inspect output.
Buffer.prototype[util.inspect.custom] = function () {
return `<Buffer ${this.length} bytes>`
}
import { killPortProcess } from './kill-port.js'
import { VERSION, LOG_FILE_PATH, LOG_CDP_FILE_PATH, parseRelayHost } from './utils.js'
import { ensureRelayServer, RELAY_PORT, waitForExtension, getExtensionOutdatedWarning, getExtensionStatus } from './relay-client.js'
+1 -1
View File
@@ -22,7 +22,7 @@ export function createFileLogger({ logFilePath }: { logFilePath?: string } = {})
const log = (...args: unknown[]): Promise<void> => {
const message = args.map(arg =>
typeof arg === 'string' ? arg : util.inspect(arg, { depth: null, colors: false })
typeof arg === 'string' ? arg : util.inspect(arg, { depth: null, colors: false, maxStringLength: 1000 })
).join(' ')
queue = queue.then(() => fs.promises.appendFile(resolvedLogFilePath, stripAnsi(message) + '\n'))
return queue
+2 -2
View File
@@ -514,7 +514,7 @@ export class PlaywrightExecutor {
const formattedArgs = args
.map((arg) => {
if (typeof arg === 'string') return arg
return util.inspect(arg, { depth: 4, colors: false, maxArrayLength: 100, breakLength: 80 })
return util.inspect(arg, { depth: 4, colors: false, maxArrayLength: 100, maxStringLength: 1000, breakLength: 80 })
})
.join(' ')
text += `[${method}] ${formattedArgs}\n`
@@ -853,7 +853,7 @@ export class PlaywrightExecutor {
const formatted =
typeof resolvedResult === 'string'
? resolvedResult
: util.inspect(resolvedResult, { depth: 4, colors: false, maxArrayLength: 100, breakLength: 80 })
: util.inspect(resolvedResult, { depth: 4, colors: false, maxArrayLength: 100, maxStringLength: 1000, breakLength: 80 })
if (formatted.trim()) {
responseText += `[return value] ${formatted}\n`
}
+8
View File
@@ -3,8 +3,16 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { z } from 'zod'
import fs from 'node:fs'
import path from 'node:path'
import util from 'node:util'
import { fileURLToPath } from 'node:url'
import { createRequire } from 'node:module'
// Prevent Buffers from dumping hex bytes in util.inspect output.
// Without this, returning a screenshot Buffer would log ~400+ chars of useless hex.
Buffer.prototype[util.inspect.custom] = function () {
return `<Buffer ${this.length} bytes>`
}
import dedent from 'string-dedent'
import { LOG_FILE_PATH, VERSION, parseRelayHost } from './utils.js'
import { ensureRelayServer, RELAY_PORT } from './relay-client.js'