Skip to content

feat(gatekeeper): support safe fd redirects in chain parser#95

Merged
amondnet merged 5 commits intomainfrom
feat/gatekeeper-fd-redirect
Mar 25, 2026
Merged

feat(gatekeeper): support safe fd redirects in chain parser#95
amondnet merged 5 commits intomainfrom
feat/gatekeeper-fd-redirect

Conversation

@amondnet
Copy link
Copy Markdown
Contributor

@amondnet amondnet commented Mar 25, 2026

Summary

  • Allow safe fd-to-fd redirects (2>&1, >&2, <&3, >&-, <&-) in the chain parser instead of marking them as unparseable
  • Allow /dev/null redirects (>/dev/null, 2>/dev/null, >>/dev/null) with optional whitespace
  • Arbitrary file redirects (> file.txt, >> file.txt, < file.txt) remain blocked as unparseable
  • Enables auto-approve for commands like cd /path && bun test 2>&1 that were previously sent to AI review

Test plan

  • All 191 existing + new tests pass (bun test)
  • fd-to-fd redirects (2>&1, >&2, 2>&-, <&3, <&-) parsed as single commands
  • /dev/null redirects with/without whitespace parsed as single commands
  • Chains containing fd redirects split correctly (cmd1 && cmd2 2>&1)
  • Unsafe file redirects (> file.txt, >> file.txt, < file.txt) still unparseable
  • Pipe after fd redirect (ls 2>&1 | grep foo) still unparseable (passthrough)
  • bun run build produces updated dist

Summary by cubic

Add support for safe fd redirects and /dev/null redirects in the Gatekeeper chain parser while still blocking file redirects. Hardened /dev/null parsing and auto-approve chains like cd /path && bun test 2>&1.

  • New Features

    • Allow fd redirects: 2>&1, 2>&-, >&2, <&3, <&-
    • Allow /dev/null redirects with optional whitespace and FDs: >/dev/null, N>/dev/null, >>/dev/null, N>>/dev/null
    • Split chains that include safe redirects (e.g., cd /path && bun test 2>&1); pipe after fd redirect remains passthrough
  • Bug Fixes

    • Bounds check when skipping whitespace before /dev/null
    • Enforce a word boundary after /dev/null to avoid paths like /dev/nullicious
    • Regression test asserts passthrough for /dev/nullicious using evaluate(bash(...))

Written for commit 98c6860. Summary will update on new commits.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
claude-code-plugins Ready Ready Preview, Comment Mar 25, 2026 8:44am

Request Review

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the gatekeeper's command chain parser by introducing more granular handling of shell redirects. It specifically allows safe file descriptor (FD) to FD redirects and /dev/null redirects, which are common and harmless, while continuing to block potentially dangerous arbitrary file redirects. This refinement reduces the number of legitimate commands incorrectly flagged for AI review, streamlining the approval process and improving the overall efficiency of command execution without compromising security.

Highlights

  • Safe FD Redirects: The chain parser now correctly identifies and allows safe file descriptor (FD) to FD redirects (e.g., 2>&1, >&2, <&3, >&-), which were previously marked as unparseable.
  • /dev/null Redirects: Redirects to /dev/null (e.g., >/dev/null, 2>/dev/null, >>/dev/null), including those with optional whitespace, are now permitted.
  • Unsafe Redirects Blocked: Arbitrary file redirects (e.g., > file.txt, >> file.txt, < file.txt) continue to be blocked as unparseable, maintaining security.
  • Improved Auto-Approval: This change enables auto-approval for common commands containing safe redirects, such as cd /path && bun test 2>&1, which previously required manual AI review.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refines the chain-parser logic to allow specific safe shell redirect syntaxes, such as file descriptor redirects (e.g., 2>&1, >&-) and redirects to /dev/null, which were previously marked as unparseable. It introduces an isDigit helper function and updates the parsing mechanism to differentiate these safe operations from potentially dangerous arbitrary file redirects. New test cases have been added to validate these changes. A review comment points out a potential out-of-bounds read in the whitespace skipping loop within the parseChainedCommand function, suggesting a boundary check for robustness.

Comment thread plugins/gatekeeper/src/chain-parser.ts Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Confidence score: 3/5

  • There is a concrete parser correctness risk in plugins/gatekeeper/src/chain-parser.ts: matching the /dev/null prefix without a word-boundary/next-character check can incorrectly approve paths like /dev/nullicious.
  • Because this issue is severity 7/10 with high confidence (9/10) and can affect redirect validation behavior, this carries real user-impacting regression risk before merge.
  • The change still appears narrowly scoped to parser logic, so risk is manageable once the boundary check is added and validated.
  • Pay close attention to plugins/gatekeeper/src/chain-parser.ts - ensure /dev/null matching enforces a proper boundary so only the exact target is accepted.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="plugins/gatekeeper/src/chain-parser.ts">

<violation number="1" location="plugins/gatekeeper/src/chain-parser.ts:121">
P1: Missing word-boundary check after `/dev/null` match allows the parser to approve redirects to files like `/dev/nullicious`. After confirming the 9-character prefix matches `/dev/null`, verify the next character is a word boundary (end-of-string, whitespace, `;`, `&`) — otherwise fall through to the "unsafe" path.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant User as User/System
    participant GK as Gatekeeper Service
    participant CP as Chain Parser
    participant AI as AI Review Layer
    participant Exec as Execution Engine

    Note over User,Exec: Command Submission Flow

    User->>GK: Request command execution (e.g., 'cd /app && bun test 2>&1')
    GK->>CP: parseChainedCommand(cmd)

    rect rgb(240, 240, 240)
        Note over CP: Tokenization & Safety Check
        
        CP->>CP: Identify chain operators (&&, ;)
        
        alt NEW: Safe Redirect Detected
            Note right of CP: Matches 2>&1, >&2, <&3, >&-, <&- or /dev/null
            CP->>CP: Include redirect in command segment
        else CHANGED: Unsafe Redirect Detected
            Note right of CP: Matches > file.txt, < file.txt, >> file.txt
            CP-->>GK: Return { kind: 'unparseable' }
        else Pipe or Subshell
            CP-->>GK: Return { kind: 'unparseable' }
        end
    end

    alt Command is Parseable
        CP-->>GK: Return list of commands
        GK->>GK: Validate commands against allow-list
        alt All commands approved
            GK->>Exec: Run commands sequentially
            Exec-->>User: Command Output
        else Safety violation
            GK->>AI: Request manual/AI review
            AI-->>User: Review results
        end
    else Command is Unparseable
        GK->>AI: Request manual/AI review
        AI-->>User: Review results
    end
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread plugins/gatekeeper/src/chain-parser.ts Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="plugins/gatekeeper/src/pre-tool-use.test.ts">

<violation number="1" location="plugins/gatekeeper/src/pre-tool-use.test.ts:100">
P2: This assertion is ambiguous: `splitChainedCommands(...).toBeNull()` passes for both safe-single and unparseable, so it does not actually verify `/dev/nullicious` is rejected.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread plugins/gatekeeper/src/pre-tool-use.test.ts Outdated
Allow fd-to-fd redirects (2>&1, >&2, <&3, >&-) and /dev/null
redirects (>/dev/null, 2>/dev/null, >>/dev/null) in the chain
parser instead of immediately classifying them as unparseable.
Arbitrary file redirects (> file.txt, >> file.txt, < file.txt)
remain blocked.
- Add bounds check to whitespace-skipping while loop in /dev/null redirect parser (gemini-code-assist)
- Add word-boundary check after /dev/null match to prevent approving paths like /dev/nullicious (cubic-dev-ai P1)
- Add regression test for /dev/nullicious boundary case
Replace ambiguous splitChainedCommands assertion for /dev/nullicious with
evaluate(bash(...)) to explicitly verify the unsafe redirect is passed through
@amondnet amondnet enabled auto-merge (squash) March 25, 2026 08:44
@amondnet amondnet merged commit d4808dc into main Mar 25, 2026
7 checks passed
@amondnet amondnet deleted the feat/gatekeeper-fd-redirect branch March 25, 2026 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant