// blog

Three guards before any token is spent.

The secret scanner, the cost preflight, and the .commitbrief/ guard — three pre-send checks that fire before CommitBrief talks to a provider, and why --yes deliberately doesn't bypass two of them anymore.

· CommitBrief

The most expensive bug in a code-review CLI isn’t a missed finding. It’s the diff that should never have been sent. A credential pasted into a debug line, a 50,000-line generated file scoped into the review by accident, an unstaged .commitbrief/ overwrite that ships your local config to the model — these are the failure modes that turn a helpful tool into a liability the first time they fire.

CommitBrief runs three guards before any provider call to make those failures harder to stumble into. Two of them have a bypass flag; one of them has a confirmation prompt. None of them are bypassed by --yes anymore, and that change is its own small story.

The pipeline position

Every guard runs in the same fixed order, after the diff is fetched and filtered, before the cache lookup:

  1. .commitbrief/ guard — does the diff touch files under the project’s own config directory?
  2. Secret scanner — does the diff contain credential-shaped patterns on newly-added lines?
  3. Cost preflight — is the estimated cost above your threshold?

A cache hit short-circuits the cost preflight (no provider call is happening; nothing to cost). The other two run unconditionally, because their concern isn’t “what will this cost” but “should this be sent at all.”

The secret scanner

Eight credential patterns ship hardcoded — AWS access keys, GitHub tokens, GitLab tokens, Anthropic keys, OpenAI keys, JWTs, Stripe live keys, and PEM private-key headers. The scanner walks two surfaces: the +-prefixed lines of your diff (new additions only — we don’t re-flag history that’s already on disk somewhere), and the user-authored content of COMMITBRIEF.md and OUTPUT.md if those files differ from the embedded defaults. Both surfaces matter because both end up verbatim in the model’s input.

When the scanner hits, stderr shows the line numbers and the pattern names — and only those. The matched substring is never printed. That detail isn’t an aesthetic choice; it’s the whole point. Most CI logs are captured and indexed somewhere. If the scanner echoed the matched key to stderr while warning you about it, the scanner itself would become a secondary leak vector. By printing only line 42: AWS Access Key, you learn enough to act without the key making it into a log.

The bypass is --allow-secrets, with an explicit info notice that the bypass fired. You opt in, but you still see the flagged lines in the notice. The whole-binary opt-out is guard.secret_scan: false, appropriate when you have an external secret scanner (gitleaks, trufflehog) already doing the same work and CommitBrief’s prompt would be noise.

What the scanner deliberately doesn’t do: entropy-based detection. High-entropy random strings often look like credentials but are usually fixture data, generated UUIDs, or test vectors. False positives in a pre-send guard are corrosive — users learn to reflex-bypass them — so the scanner sticks to specific service-shaped patterns where the false-positive rate is low.

The cost preflight

The preflight estimates the dollar cost before firing the provider call, using the chars-divided-by-4 token approximation for input and a clamped input/4 range (200 to 1500) for output. Cost is then the provider’s per-model pricing applied to those token counts, including cached-input discounts where the provider supports them.

The default threshold is $0.50. Above that, you get a TTY prompt or a non-TTY abort. Why $0.50 rather than $5 or $0.05? It’s the right shape of magnitude for catching the failure mode the preflight exists for: the diff that’s accidentally enormous. A real working review on staged changes lands in the $0.005 to $0.05 range for any of the cloud providers. A diff that crosses $0.50 is almost always a scoping accident — you forgot to ignore a generated file, you staged a vendored library by mistake, you ran commitbrief diff main...feature on a branch with a year of history. Hitting the prompt is the signal to look at what you’re about to send.

The per-invocation bypass is --no-cost-check. The per-config knob is cost.warn_threshold_usd — raise it for scheduled jobs that legitimately run on big diffs, lower it if you want a tighter belt. Setting it to 0 disables the check entirely.

Providers that return zero pricing — Ollama, claude-cli, gemini-cli — short-circuit the preflight silently. Estimated cost is always 0, so the threshold is never crossed. The verbose footer shows instead of a dollar figure in those cases.

The .commitbrief/ guard

The guard fires when your diff touches files under the .commitbrief/ directory (excluding the root COMMITBRIEF.md and .commitbriefignore, which are explicitly team artifacts and meant to be committed). The rationale is symmetric to the secret scanner: .commitbrief/ typically holds per-user state — your OUTPUT.md template, your repo-local config.yml with an API key, your backups/ directory — and committing those files breaks other developers’ configs or leaks credentials.

In a TTY the guard prompts; the default answer is no. In a non-TTY (CI, hook), the guard auto-aborts unless --yes is set. This is the one guard --yes still bypasses — the prompt is structurally a “did you mean to do this?” check, not a safety net for credential or cost data.

Why --yes stopped being a sledgehammer

Through v0.9.0, --yes had a side effect I quietly regretted: it bypassed all three guards. The intent was “auto-confirm prompts so this works in CI.” The actual behaviour was “silently approve any flagged credential and any above-threshold cost as a side effect of skipping the guard prompt.”

This was a footgun in practice. Users routinely wired --yes into CI to skip the .commitbrief/ guard prompt — and that side-effected into a regime where a flagged AWS key in a diff would be sent to the model without anyone seeing the warning. The whole point of the secret scanner was being defeated by a flag whose advertised purpose was unrelated.

v0.9.1 fixed it by narrowing --yes to only the .commitbrief/ guard prompt. The secret scanner and cost preflight got dedicated bypass flags: --allow-secrets and --no-cost-check. The migration story is uncomfortable — every CI script that used --yes to bypass guards needs to opt in explicitly to whichever guards it wants bypassed — but the alternative was a tool that was provably less safe than it claimed to be.

The general principle: bypass flags should match the scope of the thing they bypass. --yes answers a prompt; it shouldn’t double as a security setting. --allow-secrets is explicit about what’s being allowed; the user reading the script later can tell exactly what risk is being accepted.

What the guards add up to

A pre-send architecture is the inverse of a post-hoc one. Post-hoc detection — looking at logs, auditing what was sent after the fact — depends on the data already having left your machine. Pre-send detection stops it leaving in the first place. For a tool whose value proposition is local-first, the pre-send shape is the only one that’s coherent with the rest of the design.

Each individual guard’s signal is small. The secret scanner catches a fraction of a percent of diffs. The cost preflight fires on the occasional generated-file accident. The .commitbrief/ guard catches a rare staging mistake. Stacked together, they cover the three failure modes a careful operator would worry about — and they cover them with the user still having the data in their hand, before any network call has happened.

If you’re wiring CommitBrief into a regulated environment, the compliance post covers how the JSON output and cache fingerprints supplement the human-review layer. If you’re worried about the cost shape specifically, the next post in this series is about turning the --fail-on severity gate into a CI signal that fails fast without burning a full review cycle.


← all posts