Binary Data Detection Methods in law-chain-hot/websocket-devtools: Base64, Hex, and Protobuf
The websocket-devtools extension employs a layered defense-in-depth strategy for binary data detection, combining native type checks, regex-based Base64 and hex validation, statistical heuristics for binary-looking strings, and wire-format parsing to identify protobuf payloads without prior schema knowledge.
The law-chain-hot/websocket-devtools repository inspects WebSocket traffic in real-time and must reliably distinguish binary payloads from plain text. Its binary data detection system operates through five distinct validation layers, ranging from fast instanceof checks to sophisticated protocol signature analysis.
Native Binary Type Detection
The fastest detection path occurs in src/content/injected.js through immediate type inspection. The isBinaryData function checks for native binary objects before attempting any string parsing.
if (data instanceof ArrayBuffer ||
data instanceof Uint8Array ||
data instanceof Blob) {
return true; // directly binary
}
This check appears at lines 21‑27 of src/content/injected.js and serves as the first gate in the detection pipeline. When the WebSocket message arrives as a true binary type, the system bypasses all encoding detection logic entirely.
Base64 String Detection
For encoded strings, the extension validates Base64 detection through pattern matching and length validation. The isBase64String function resides in both src/content/injected.js (lines 101‑106) and src/utils/protobufUtils.js (lines 71‑77).
function isBase64String(str) {
if (!str || str.length < 4) return false;
const base64Pattern = /^[A-Za-z0-9+/]*={0,2}$/;
return base64Pattern.test(str) && str.length % 4 === 0;
}
The method enforces two strict criteria: the string must match the Base64 character set with optional padding, and its length must be divisible by four. This same routine supports the protobuf utilities when decoding Base64-encoded protobuf payloads.
Hexadecimal String Detection
Hex detection handles common encoding prefixes and validates character sets. Implemented in src/content/injected.js (lines 107‑111) and src/utils/protobufUtils.js (lines 84‑91), the isHexString function strips 0x or \x prefixes before validation.
function isHexString(str) {
if (!str || str.length < 2) return false;
const cleanStr = str.replace(/^(0x|\\x)/i, '');
return cleanStr.length % 2 === 0 && /^[0-9a-fA-F]+$/.test(cleanStr);
}
The logic requires even-length strings consisting solely of hexadecimal digits after prefix removal. This enables the extension to recognize hex-encoded binary data regardless of whether developers include explicit prefix markers.
Statistical Heuristic for Binary Content
When strings fail explicit encoding patterns, the system applies a binary-looking string heuristic. The containsBinaryData function samples the first 1000 characters and counts non-printable bytes.
function containsBinaryData(str) {
const len = Math.min(str.length, 1000); // limit for performance
let binaryCount = 0;
for (let i = 0; i < len; i++) {
const c = str.charCodeAt(i);
if ((c < 32 && c !== 9 && c !== 10 && c !== 13) || c > 126) {
binaryCount++;
}
}
return binaryCount / len > 0.2; // >20% non-printable → binary
}
Located at lines 124‑136 in src/content/injected.js and lines 115‑127 in src/utils/protobufUtils.js, this method flags content as binary when more than 20% of characters fall outside the printable ASCII range (excluding standard whitespace).
Protobuf Signature Detection
The most specialized layer performs protobuf detection by analyzing wire-format structure without requiring .proto schema files. Located in src/utils/protobufUtils.js, the isProtobufData wrapper converts inputs to Uint8Array, then delegates to checkProtobufSignature (lines 65‑103) for validation.
function checkProtobufSignature(bytes) {
if (!bytes || bytes.length < 2) return false;
let position = 0, validFields = 0;
while (position < bytes.length && validFields < 10) {
const header = readVarint(bytes, position);
if (!header) break;
const tag = header.value >>> 3;
const wireType = header.value & 0x07;
if (tag === 0 || wireType > 5) break;
const skip = skipFieldData(bytes, header.nextPosition, wireType);
if (!skip) break;
position = skip.nextPosition;
validFields++;
}
return validFields >= 2;
}
The algorithm parses varint headers, validates field tags (non-zero) and wire types (0‑5), and attempts to skip field data. The payload qualifies as protobuf only if the parser successfully identifies at least two valid fields without encountering malformed varints or buffer overruns.
Practical Implementation Examples
Runtime WebSocket Interception
To detect binary data within intercepted WebSocket traffic, the injected script combines multiple checks:
// Assume `msg` is the data received from a WebSocket
if (isBinaryData(msg)) {
console.log('Binary payload detected');
// Further handling – e.g. decode as protobuf
}
This leverages isBinaryData, isBase64String, isHexString, and containsBinaryData from src/content/injected.js according to the source code implementation.
Protobuf Decoding Workflow
For dedicated protobuf handling, import the utility library:
import { isProtobufData, decodeProtobufData } from './utils/protobufUtils.js';
if (isProtobufData(message)) {
const { success, decoded, raw, error } = decodeProtobufData(message);
if (success) {
console.log('Protobuf decoded:', decoded);
} else {
console.warn('Protobuf decode failed:', error);
}
}
The isProtobufData function handles type conversion for ArrayBuffer, Uint8Array, or string inputs, while decodeProtobufData and reflectiveDecodeProtobuf manage the actual deserialization in src/utils/protobufUtils.js.
Summary
- Native type detection in
src/content/injected.jsimmediately identifiesArrayBuffer,Uint8Array, andBlobinstances without parsing overhead. - Base64 validation uses regex pattern matching and modulo-4 length verification across both the content script and protobuf utilities.
- Hex detection strips common prefixes (
0x,\x) before enforcing even-length hexadecimal digit requirements. - Statistical heuristics classify strings as binary when over 20% of sampled characters are non-printable ASCII.
- Protobuf signature analysis validates wire-format structure by parsing varints and requiring at least two valid field tags with legal wire types.
Frequently Asked Questions
How does websocket-devtools detect protobuf without knowing the schema?
The extension uses wire-format analysis rather than schema-dependent parsing. The checkProtobufSignature function in src/utils/protobufUtils.js validates the structural integrity of protobuf encoding by checking varint headers, field tag validity, and wire-type ranges. It confirms protobuf only when finding at least two valid consecutive fields, ensuring robust detection even for unknown message types.
What is the difference between binary detection in injected.js versus protobufUtils.js?
The src/content/injected.js module provides runtime detection for WebSocket interception, combining native type checks with encoding heuristics for Base64, hex, and binary-looking strings. The src/utils/protobufUtils.js module reuses these string detection methods but adds specialized protobuf signature parsing and decoding capabilities, serving as a dedicated utility library for protobuf-specific operations.
Why does the binary heuristic use a 20% non-printable threshold?
The 20% threshold in containsBinaryData represents a statistical compromise that minimizes false positives while capturing escaped binary content that happens to include printable characters. The implementation limits analysis to the first 1000 characters for performance, counting characters outside the 32‑126 ASCII range (excluding tabs, newlines, and carriage returns) to classify the payload efficiently.
Can the extension handle mixed-encoding payloads?
Yes, the detection pipeline processes inputs sequentially. The isProtobufData wrapper in src/utils/protobufUtils.js first attempts Base64 and hex decoding on string inputs before treating the resulting bytes as potential protobuf. This layered approach allows the extension to handle Base64-encoded protobuf messages or hex-encoded binary data transparently.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →