Security hardening: command gate, secret redaction, macOS sandbox#1
Open
laplaque wants to merge 11 commits intourjitbhatia:masterfrom
Open
Security hardening: command gate, secret redaction, macOS sandbox#1laplaque wants to merge 11 commits intourjitbhatia:masterfrom
laplaque wants to merge 11 commits intourjitbhatia:masterfrom
Conversation
Adds a RedactEngine with a plugin pipeline that scrubs secrets from terminal output before it reaches the MCP client. Secrets can be used by tools (e.g. curl -H "Bearer $TOKEN") but never displayed. Architecture: - RedactPlugin ABC with patterns() and redact() methods - RedactEngine loads built-in + custom plugins, applies as pipeline - Custom plugin auto-discovery from ~/.config/it2mcp/redact-plugins/ Built-in plugins: - GitHub: ghp_, gho_, ghu_, ghs_, ghr_, github_pat_ tokens - GitLab: glpat-, gldt-, glrt-, glcbt-, glft-, glsoat- tokens - AWS: AKIA access keys, secret keys, session tokens - Generic: OpenAI sk-, Anthropic sk-ant-, JWTs, Bearer tokens, Slack, Stripe, SendGrid, Twilio, PEM blocks - Env vars: context-aware KEY=VALUE redaction for sensitive names
- Add RedactEngine to Config, loaded from config.yaml redact section - Add redact_output() convenience function for use by tools - Redact audit log result text before writing (audit log itself is clean) - Default: redaction enabled with [REDACTED] replacement
Wrap session_read and _b_session_read output through redact_output() so terminal content is scrubbed before reaching the MCP client. Only two lines changed in server.py — minimal invasive patch.
92 tests at 95% coverage: - RedactEngine: enabled/disabled, plugin loading, config, pipeline, custom plugin discovery, error resilience - GitHubPlugin: all 6 token prefixes, boundary cases - GitLabPlugin: all 6 token prefixes, boundary cases - AWSPlugin: AKIA/ASIA keys, secret keys, session tokens - GenericSecretsPlugin: OpenAI, Anthropic, JWT, Bearer, Slack, Stripe, SendGrid, Twilio, PEM blocks - EnvVarsPlugin: KEY=VALUE, export/declare, sensitive vs non-sensitive Run: uv run --extra test pytest tests/ -v
Shows all redaction options: enabled, replacement string, disabled_plugins list, and custom_plugin_dir path.
… Ctrl+C Fixes two bugs documented in the bug report: 1. No way to detect if a session is busy - session_status now returns job_name, job_pid, shell_pid, and is_at_shell_prompt boolean 2. Ctrl+C via session_send doesn't work - session_interrupt sends SIGINT directly via os.kill() with ETX fallback Implementation: - Extract pure functions (parse_pid, is_at_shell_prompt, build_session_status, determine_interrupt_action) for testability - Add InterruptAction class to encapsulate interrupt decision logic - Register new tools in security tiers (READ and INTERACT) - Add batch handlers for both tools - Add pytest-asyncio for async test support Tests: - 65 new unit tests covering all pure functions - 100% coverage on new code - Tests for shell detection, PID parsing, edge cases, security tiers
…w/window_new - Removed session_set_variable tool, batch handler, and TOOL_TIERS entry - tab_new and window_new always use 'MCP Sandboxed' profile (no profile param) - Updated session_list docstring to reflect auto-tagging via sandboxed profile - Updated README: session tagging section, removed session_set_variable from tables
- New cloud_cli plugin: catches GCP ya29 tokens, Azure accessToken JSON and bare TSV output - Generic plugin: full PEM/OpenSSH key block redaction (header+body+footer), standalone header fallback - Tests for all new patterns
- New gate.py: allow/deny/ask command classification with osascript confirmation dialog - macOS dialog with Allow, Allow for Session, Deny buttons + configurable timeout - Commands piped through secfilter before display in dialog - Session allow list (in-memory, resets on server restart) - Integrated into session_run, session_send, tab_new, window_new and all batch equivalents - New cloud_cli redaction plugin: GCP ya29 tokens, Azure accessToken JSON/TSV output - Enhanced generic plugin: full PEM/OpenSSH key block redaction (header+body+footer) - Config: commands section with allow/deny lists, timeout, enabled flag - Tests for gate pattern matching, command classification, all redaction plugins - Fixed _session_allowed type (set, not list) - Updated example config with command gate and cloud_cli plugin
- install.sh: sets up sandbox profile, iTerm2 dynamic profile, config - sandbox/iterm-sandbox.sb: macOS kernel-level file access restrictions - sandbox/sandboxed-shell.sh: auto-tagging wrapper with env -i stripping - config/env-passthrough.conf: environment variable allowlist - README rewritten: four security layers, command gate, all tools listed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds four security layers to it2mcp, turning it from a convenience tool into a hardened MCP server suitable for production use with AI assistants.
What's included
1. Command confirmation gate (
gate.py)config.yamlosascriptdialog for unknown commands: Allow / Allow for Session / Denysession_run,session_send,tab_new,window_new, and all batch equivalents2. Secret redaction engine (
redact/)~/.config/it2mcp/redact-plugins/session_readoutput before returning to the MCP client3. macOS sandbox (
sandbox/,install.sh)sandbox-exec.envfiles, cloud provider configs, shell history, password manager DBs, and moreenv -istripping of inherited environment variablessandbox-execcan't re-launch, debuggers blockedinstall.shsets up sandbox profile, iTerm2 dynamic profile, and default config4. Session hardening
session_set_variabletool (chicken-and-egg problem allowed bypassing session tagging)tab_newandwindow_newalways use "MCP Sandboxed" profile (no profile parameter)Other additions
session_statustool: busy/idle detection via foreground job inspectionsession_interrupttool: reliable SIGINT delivery to foreground processBreaking changes
session_set_variabletool removedtab_newandwindow_newno longer accept aprofileparametersession_run/session_sendare now subject to the command gate (requirescommandssection in config, or all commands will trigger the confirmation dialog)Installation
git clone https://github.com/laplaque/it2mcp.git cd it2mcp uv sync ./install.shSee README for full setup instructions.