Menu

#352 feat(detectors): built-in detector for oversized base64 blobs (#212)

closed
nobody
None
2026-08-13
2026-08-12
Anonymous
No

Originally created by: harshitagrawal2O

Pull Request

Slice

  • Repo: doberman-core
  • Feature / Slice: [#212] — built-in Detector for oversized base64 blobs in tool arguments
  • Plan reference: n/a (self-contained level-7 issue)

What this PR does

Adds Base64BlobDetector, a second built-in subjective detector (mirroring TokenChannelDetector), that flags a suspiciously large base64-looking blob in a tool call's arguments — a common encode-and-exfiltrate shape, where bulk file or secret contents are smuggled out as one encoded payload.

  • Shape and size only — it never base64-decodes, logs, or echoes the payload. A test asserts the blob never reaches the explanation.
  • Raise-only — runs in the subjective guardrail, so it can only ever step up to AUTH (the execution rule clamps a subjective BLOCK to AUTH); it never blocks and never lowers a verdict.
  • Tolerates PEM/MIME newline wrapping — line wrapping (64/76-col newlines) is stripped before scanning, so the canonical wrapped-key exfil shape is caught; spaces/tabs are left intact so ordinary whitespace-separated text does not merge into a false blob.
  • Configurable size threshold (min_blob_chars, default ~1500 base64 chars ≈ 1.1 KB) — not a magic number baked into the logic. A character-diversity heuristic (mixed case + digits + ≥20 distinct chars) rejects long hex / identifier / repetitive-filler runs that merely share the base64 charset.
  • New ReasonCode.oversized_encoded_blob, registered in BUILTIN_DETECTOR_TYPES.

Scope: this targets bulk encoded dumps. Small credentials (an API key, a short token) are below the threshold by design and remain the objective secrets rule's job.

Tests added (run in CI)

  • tests/unit/test_detector_base64_blob.py — 14 tests: oversized blob → AUTH; short/benign → PASS; long lowercase-hex / letters-only / repetitive-filler runs do not flag; configurable threshold; newline-wrapped (PEM/MIME) blob is caught; space-separated short tokens do not merge; blob in target/destination caught; never BLOCK (raise-only); the blob never appears in the explanation (redaction); wired into SubjectiveGuardrail as a built-in and disable-able.

Public-release safety (doberman-core only)

  • [x] Contains nothing from the "not allowed" list: no enterprise/hosted code, no proprietary detection, no customer data, no secrets, no commercial-license code
  • [x] Core still builds/tests/runs with NO enterprise package installed

Security checklist

  • [x] Fails closed on error / uncertainty — the detector only adds signal; nothing here can drop a verdict, and a miss falls through to the rest of the stack
  • [x] No secret, full file, or unredacted prompt logged or committed — shape/size only; never decodes; a test asserts the payload never reaches the explanation or logs
  • [x] Any guardrail/learning change is raise-only (no silent loosening) — subjective detector, AUTH at most; test_detector_never_blocks and the raise-only subjective contract enforce it
  • [x] Every BLOCK/AUTH carries reason codes + a human explanation — oversized_encoded_blob + a one-line explanation on every AUTH
  • [x] doberman-core does not import doberman_enterprise

Edge cases covered / Deviations from plan / Risks introduced

  • Defense-in-depth, documented (README known-limitations): evadable by splitting the blob across sub-threshold arguments/calls, interleaving non-alphabet separators, or switching encodings. Raise-only, so a miss is never a weakened verdict.
  • Known duplication (accepted, matches existing pattern): like TokenChannelDetector, this detector calls collect_scan_strings(action, ctx) itself rather than sharing one collected list across detectors. Sharing collection across the built-in detector fan-out is a separate infra change, out of scope here.
  • No existing behavior changes for actions without a large base64 blob (verified: existing encoded-exfil fixtures route through the objective secrets rule and are under threshold).

Related

Tickets: #212

Discussion

  • Anonymous

    Anonymous - 2026-08-13

    Ticket changed by: fu351

    • status: open --> closed
     
  • Anonymous

    Anonymous - 2026-08-13

    Originally posted by: fu351

    Solid work, and the honesty in it is what makes it good. A shape-only base64 heuristic will false-positive on a legitimate large embedded asset, and instead of hiding that you documented it in the docstring, README, and CHANGELOG and bounded it by only ever raising to AUTH, never BLOCK. That's the correct call for a defense-in-depth signal: the cost of a false positive is one confirmation prompt, not a broken workflow. The redaction test (asserting a slice of the blob never reaches the explanation or a reason code) and the false-positive guards (hex dumps, long word runs, whitespace-separated short tokens) are exactly the tests this kind of detector needs.

    Merging. You've got the detector seam down now, so [#321] (a PII / financial-data-class exfil detector) is the natural next one — same seam, and it would give the lethal-trifecta floor a real target leg to line up on. Want it? I can assign it to you.

    If you're not already in the Discord: https://discord.gg/Sfy5XGNqty

    Thanks, harshitagrawal2O.

     

    Related

    Tickets: #321


Log in to post a comment.