schollz/croc · error · Error

A remote path contains a null byte

Error message

A remote path contains a null byte

What it means

cleanSegments() sanitizes every remote path coming from the peer's transfer offer. A NUL byte in a path is never legitimate and is a classic trick against path-based filesystems and logging pipelines, so it is rejected outright before any segment splitting.

Source

Thrown at web/src/protocol/metadata.ts:11

import { base64ToBytes } from "./bytes";
import type {
  OfferedFile,
  SenderInfoWire,
  TransferOffer,
  WireFileInfo,
} from "./types";

function cleanSegments(value: string) {
  const replaced = value.replaceAll("\\", "/");
  if (replaced.includes("\0")) throw new Error("A remote path contains a null byte");
  const segments: string[] = [];
  for (const segment of replaced.split("/")) {
    if (segment === "" || segment === ".") continue;
    if (segment === "..") throw new Error(`Remote path escapes the destination: ${value}`);
    if ([...segment].some((character) => !/\P{C}/u.test(character))) {
      throw new Error(`Remote path contains a non-printable character: ${value}`);
    }
    segments.push(segment);
  }
  return segments;
}

export function normalizeFolder(value = ".") {
  if (/^(?:[a-zA-Z]:|\/)/.test(value)) {
    throw new Error(`Remote path must be relative: ${value}`);
  }
  const segments = cleanSegments(value);
  const normalized = segments.join("/") || ".";

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Reject or terminate the transfer from the offending peer — the metadata is malformed or malicious; there is no safe reinterpretation.
  2. If you are the sender side, strip NUL bytes from paths before building the offer.
  3. When fuzzing, treat this as an expected rejection, not a crash: wrap validateSenderInfo in try/catch and assert the error message.
Defensive patterns

Strategy: validation

Validate before calling

function hasNoNullByte(path: string): boolean {
  return !path.includes("\0");
}
// before validating an offer:
if (!hasNoNullByte(wire.fr ?? ".") || !hasNoNullByte(wire.n ?? "")) {
  rejectOffer("null byte in remote path");
}

Try / catch

try {
  const offer = validateSenderInfo(info);
} catch (error) {
  if (error instanceof Error && error.message === "A remote path contains a null byte") {
    abortTransfer(); // hostile/malformed peer metadata; do not continue
  }
  throw error;
}

Prevention

When it happens

Trigger: A received SenderInfo offer where a file's folder (fr), name (n), or an EmptyFoldersToTransfer entry contains '\0' — e.g. crafted by a hostile sender ("file.sh\0.txt") or produced by a mis-encoding peer.

Common situations: Security review / fuzzing of the receive path; a peer running on a system that allows NUL in filenames passed through verbatim; hostile sender attempting path-confusion attacks against the browser download sink.

Related errors


AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15). Data as JSON: /api/errors/77c43fbf8304c602. Report an issue: GitHub.