# Binary Data Detection Methods in law-chain-hot/websocket-devtools: Base64, Hex, and Protobuf

> Discover how law-chain-hot/websocket-devtools detects binary data using Base64, hex, and Protobuf. Learn about its layered approach including regex, heuristics, and wire-format parsing.

- Repository: [Brian 阿布/websocket-devtools](https://github.com/law-chain-hot/websocket-devtools)
- Tags: deep-dive
- Published: 2026-03-05

---

**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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/content/injected.js) through immediate type inspection. The `isBinaryData` function checks for native binary objects before attempting any string parsing.

```javascript
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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/content/injected.js) (**lines 101‑106**) and [`src/utils/protobufUtils.js`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/utils/protobufUtils.js) (**lines 71‑77**).

```javascript
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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/content/injected.js) (**lines 107‑111**) and [`src/utils/protobufUtils.js`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/utils/protobufUtils.js) (**lines 84‑91**), the `isHexString` function strips `0x` or `\x` prefixes before validation.

```javascript
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.

```javascript
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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/content/injected.js) and **lines 115‑127** in [`src/utils/protobufUtils.js`](https://github.com/law-chain-hot/websocket-devtools/blob/main/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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/utils/protobufUtils.js), the `isProtobufData` wrapper converts inputs to `Uint8Array`, then delegates to `checkProtobufSignature` (**lines 65‑103**) for validation.

```javascript
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:

```javascript
// 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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/content/injected.js) according to the source code implementation.

### Protobuf Decoding Workflow

For dedicated protobuf handling, import the utility library:

```javascript
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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/utils/protobufUtils.js).

## Summary

- **Native type detection** in [`src/content/injected.js`](https://github.com/law-chain-hot/websocket-devtools/blob/main/src/content/injected.js) immediately identifies `ArrayBuffer`, `Uint8Array`, and `Blob` instances 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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/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`](https://github.com/law-chain-hot/websocket-devtools/blob/main/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.