-
Notifications
You must be signed in to change notification settings - Fork 29
feat: Add sandbox execution for AWS CLI commands #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
alexei-led
merged 28 commits into
main
from
claude/sandbox-aws-cli-01EnE7BVjBvQKnDDwzBKM1Y7
Nov 29, 2025
Merged
feat: Add sandbox execution for AWS CLI commands #21
alexei-led
merged 28 commits into
main
from
claude/sandbox-aws-cli-01EnE7BVjBvQKnDDwzBKM1Y7
Nov 29, 2025
Conversation
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
Implement OS-level process isolation for running AWS CLI commands to provide defense-in-depth security against command injection. Key features: - Linux support: Landlock LSM (kernel 5.13+) with bubblewrap fallback - macOS support: Seatbelt (sandbox-exec) via subprocess - Two AWS credential passing modes: environment variables and ~/.aws access - Configurable via AWS_MCP_SANDBOX and AWS_MCP_SANDBOX_CREDENTIALS env vars The sandbox restricts filesystem access while allowing: - Read access to system binaries and libraries - Read access to AWS configuration (~/.aws) if configured - Write access to /tmp and current working directory - Network access for AWS API calls This complements the existing command validation security layer.
- Remove unused execute_piped_command() from tools.py and its tests - Move duplicated _build_env() method to SandboxBackend base class - Update module docstring in tools.py to reflect current purpose - Remove unused imports from test files - Use modern Python 3.13 type hints (list[str] instead of List[str])
- Add sandbox environment variables to README configuration table - Add Sandbox Execution section with backend support details - Update architecture diagrams to show Security → Sandbox flow - Update spec.md tool names (aws_cli_help, aws_cli_pipeline) - Add Security Validator and Sandbox to component architecture - Update directory structure with sandbox.py and security.py - Add Docker vs Sandbox comparison in Why Docker section - Streamline Example Interactions to show tool usage patterns - Add sandbox disable option to CLAUDE.md for development
- Add value proposition explaining CLI wrapper vs API wrapper approach - Reorganize README: move detailed content to dedicated docs - Create docs/SECURITY.md (architecture), docs/DEVELOPMENT.md - Create CONTRIBUTING.md, SECURITY.md (vulnerability reporting) - Fix tool names in INSTRUCTIONS (describe_command -> aws_cli_help) - Improve tool descriptions for AI-friendliness with examples
- Add AWS_ENV_VARS and AWS_SECRET_ENV_VARS constants - Filter out secret-bearing AWS vars when pass_aws_env is disabled - Add tests for env var filtering behavior
Convert subprocess.TimeoutExpired to asyncio.TimeoutError in execute_sandboxed_async to match the documented contract and ensure execute_aws_command catches timeouts correctly instead of falling through to generic exception handling. Also remove unsupported version/capabilities args from FastMCP init.
- Remove fake tests in test_main.py that tested mocks instead of code - Add platform-specific skip markers for Linux/macOS sandbox backends - Add timeout handling tests for sync and async sandbox execution - Add version parsing edge case tests for Landlock and Seatbelt - Add Seatbelt profile tests for AWS config disabled - Add backend selection tests for unsupported platforms - Coverage improved from 79% to 85% for sandbox.py
Previously, when Landlock failed to apply in the preexec_fn, it would log a warning and continue execution without sandboxing - even when sandbox_mode="required". This could give users false confidence that sandboxing was active when it wasn't. Now the behavior respects the configured mode: - required: raises RuntimeError if Landlock fails (fail-safe) - auto: logs warning with mode info and continues (graceful fallback) - disabled: no change Also adds sandbox_mode parameter to all backend execute() methods to enable this context-aware enforcement.
Update SECURITY.md to document that required mode provides fail-safe behavior: commands fail if sandbox cannot apply at execution time, not just if the backend is unavailable at startup.
Previously, execute_piped_sandboxed_async passed the same timeout to
each pipeline stage, so N commands could take N×timeout seconds. This
violated the documented contract ("timeout in seconds for the entire
pipeline").
Now tracks elapsed time with time.monotonic() and calculates remaining
time for each stage. Pipeline aborts immediately when total timeout is
exceeded.
Adds test verifying 3×0.15s sleeps timeout before 0.5s with 0.3s limit.
The region auto-injection only checked for exact "--region" match, so --region=eu-west-1 was not detected as having a region. This caused the default region to be appended, silently overriding user's intent since AWS CLI honors the last --region argument. Now checks if any arg starts with "--region" to handle both: - --region eu-west-1 (space-separated) - --region=eu-west-1 (equals syntax) Fixed in both execute_aws_command and execute_pipe_command.
Major version bumps: - fastmcp: 0.4.1 → 2.13.0 (major API changes) - mcp: 1.0.0 → 1.22.0 - boto3: 1.34.0 → 1.41.0 - pytest: 7.0.0 → 9.0.0 - pytest-cov: 4.0.0 → 7.0.0 - pytest-asyncio: 0.23.0 → 1.3.0 - ruff: 0.2.0 → 0.14.0 - moto: 4.0.0 → 5.1.0 - setuptools_scm: 7.0.0 → 9.0.0 All tests pass with new dependencies.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21 +/- ##
==========================================
- Coverage 95.06% 90.78% -4.28%
==========================================
Files 8 9 +1
Lines 669 977 +308
==========================================
+ Hits 636 887 +251
- Misses 33 90 +57
🚀 New features to boost your workflow:
|
- Use uv pip sync with lock file instead of installing from pyproject.toml - Ensures consistent dependency versions (especially ruff) across CI runs - Fix shellcheck warnings for unquoted GITHUB_PATH/GITHUB_OUTPUT
… paths - Make sandbox_available() catch SandboxError and return False instead of propagating, preventing uncaught exceptions when AWS_MCP_SANDBOX=required but no backend is available - Move log statements inside try blocks in execute_aws_command and execute_pipe_command to ensure sandbox errors are properly caught - Add get_aws_credential_paths() helper to discover credential paths from AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE, and AWS_WEB_IDENTITY_TOKEN_FILE - Update Landlock, Bubblewrap, and Seatbelt backends to whitelist custom credential paths, fixing "Unable to locate credentials" errors when using non-default credential locations
- Add tests for sandbox_available() returning False on SandboxError - Add tests for get_aws_credential_paths() helper covering default ~/.aws, custom credentials file, custom config file, web identity token file, non-existent paths, and deduplication
The test_build_profile test was failing in CI because ~/.aws doesn't exist. Mock the helper function to ensure consistent test behavior.
- get_aws_profiles() now reads from AWS_CONFIG_FILE and AWS_SHARED_CREDENTIALS_FILE environment variables - Documents custom credential path support in sandbox - Ensures consistency: sandbox whitelists custom paths and resources can discover profiles from them
- Replace verbose 25-line prompts with ~10-line focused templates - Add concrete AWS CLI examples for each prompt type - Extract common examples into module-level dictionaries - Each prompt now leads with example and specifies output format - Follows best practice: "concrete examples > verbose instructions"
- Replace pip/curl install with astral-sh/setup-uv@v7 action - Enable uv cache for faster builds - Read Python version from pyproject.toml (uv python install) - Update actions: checkout@v6, codecov-action@v5, build-push-action@v6 - Remove unnecessary matrix strategy and comments - Consistent patterns across ci.yml and release.yml
- Add comprehensive USAGE.md with integration examples - Simplify README with essential quickstart info - Move detailed content to dedicated doc files - Update CONTRIBUTING with cleaner setup reference - Refresh SECURITY and VERSION docs
Ubuntu's externally managed Python rejects --system installs. Switch to uv sync which creates a venv automatically and use uv run to execute commands in the virtual environment.
The old uv.lock was pip-compile format (requirements.txt style). uv sync requires TOML format lock file. Regenerated with uv lock. Also update Makefile to use uv sync commands.
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.
Implement OS-level process isolation for running AWS CLI commands
to provide defense-in-depth security against command injection.
Key features:
The sandbox restricts filesystem access while allowing:
This complements the existing command validation security layer.