1jehuang / 1jehuang/jcode

feat: armed one-shot bypass mode for the bash risk gate, with danger alert and auto-expiry

Open
#931 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no enhancement priority: medium triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Problem

The bash risk gate has two escape hatches today, and neither is a user-facing, consciously-armed bypass:

  1. Agent-side justification — the model re-issues the call explaining itself. The agent decides to proceed; the user is never consulted. (#722)
  2. Proposed permanent toggle (#897) — /settings risk-gate off. Correct for its purpose, but it's a durable state change. Flip it once during a frustrating false positive and the protection is silently gone for every later session.

What's missing is the case in between: "I know exactly what this next command does, it's genuinely destructive, let me through this once, and make me acknowledge the risk before you do."

Today the only way to get that is to disable the gate wholesale, which is exactly the wrong trade. The user reaches for a permanent switch to solve a momentary problem.

Proposal: armed bypass mode

A bypass that must be explicitly armed, shows a danger alert first, and disarms itself.

/bypass

Does not enable anything. It shows the warning and asks for confirmation:

  ⚠  DANGER: BYPASS MODE

  This disables the destructive-command gate. While armed, jcode can run
  commands that PERMANENTLY DESTROY DATA with no confirmation:

    • rm -rf on paths resolved at runtime
    • mkfs, dd to block devices, partition edits
    • DROP DATABASE / TRUNCATE
    • git push --force, git reset --hard, history rewrites

  There is no undo. Nothing here is recoverable.

  Scope   : this session only
  Expires : after 1 command, or 5 minutes, whichever is first
  Audit   : every bypassed command is logged to ~/.jcode/bypass-audit.log

  Type ARM BYPASS to continue, or anything else to cancel:

Requiring a typed phrase rather than y/N is deliberate. Muscle memory defeats y/N, and this is precisely the prompt that must not be dismissed reflexively.

Design points that matter

Auto-expiry is the core of it. A bypass that stays on is just #897 with extra steps. Default to a single command, since the honest use case is almost always one specific command the user has already reasoned about. Suggested: /bypass = next 1 command, /bypass 5m = time-boxed for a known-messy sequence like a disk migration.

Visible while armed. Persistent indicator in the status line (⚠ BYPASS ARMED (1 cmd)). Nobody should be unsure whether they're currently unprotected.

The agent must not arm it. This is a user-only control. If the model could invoke /bypass, the whole gate becomes decorative, since a sufficiently determined agent would arm and proceed. Enforce at the tool boundary: the bypass command is not exposed as a callable tool, only as a TUI slash command. This is the single most important constraint in the proposal.

Audit trail. Append every bypassed command with timestamp and cwd. When a bypass eats a directory, the user needs to reconstruct what ran.

Print what's being bypassed. At arm time, if the blocked command is already known, show it verbatim in the alert. Confirming an abstract capability is much weaker than confirming rm -rf ./build/$TARGET_DIR.

Relationship to existing issues

  • #897 (permanent toggle) — complementary, different need. #897 = "this classifier is too noisy for my workflow." This = "let me through this one genuinely dangerous command." Both can exist; if only one ships, this is the safer default because it fails closed.
  • #751 / #709 / #725 / #922 (false positives) — these reduce demand for a bypass but don't remove it. Even a perfect classifier correctly blocks commands users legitimately want to run. That's not a bug, and a bypass is the honest answer to it.

Why this shape

The failure mode of a safety gate isn't being too strict, it's being routinely too strict, because users then build a permanent workaround and lose the protection everywhere. An armed, expiring, loudly-announced bypass keeps the pressure release local to the moment that needed it.

It also improves agent behavior. Right now, when the gate blocks inert content (#922), the tempting workaround is base64 -d, printf-assembly, or sed-splicing, all of which are more opaque to the scanner. A legitimate front door means less incentive to tunnel under the wall.

Open questions

  • Should /bypass require the gate to have actually fired first? Arming pre-emptively is more flexible; arming only in response to a specific block is safer and lets the alert quote the exact command. I lean toward the latter as the default with a flag for the former.
  • Should time-boxed mode exist at all, or is 1-command-only sufficient? Time-boxed serves real multi-step recovery work, but it's also the mode most likely to be left armed while someone gets distracted.
  • Non-interactive/headless: probably should never be armable, since there's no human to read the alert. JCODE_BYPASS=1 would recreate the exact problem this avoids.

Came up after hitting #922, where the gate blocked writing a shell script whose text contained rm -f. In that case the right answer was a file-write tool rather than a bypass, but it raised the question of what to do when the command really is destructive and really is intended.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the bash risk gate, the TUI slash-command handling, the status-line indicator, and the command audit logging entry points. Resolve the open questions around one-command versus time-boxed expiry and pre-emptive arming, then verify that only an interactive user can arm the bypass and that expiry, visibility, and audit behavior work as specified.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, rust
Domain
cli, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.