hydra-sandbox 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hydra_sandbox-0.1.0/.github/workflows/docs.yml +46 -0
- hydra_sandbox-0.1.0/.github/workflows/publish.yml +35 -0
- hydra_sandbox-0.1.0/.github/workflows/test.yml +55 -0
- hydra_sandbox-0.1.0/.gitignore +5 -0
- hydra_sandbox-0.1.0/CHANGELOG.md +15 -0
- hydra_sandbox-0.1.0/LICENSE +21 -0
- hydra_sandbox-0.1.0/PKG-INFO +177 -0
- hydra_sandbox-0.1.0/README.md +131 -0
- hydra_sandbox-0.1.0/SECURITY.md +41 -0
- hydra_sandbox-0.1.0/docs/BENCHMARKS.md +34 -0
- hydra_sandbox-0.1.0/docs/api.md +185 -0
- hydra_sandbox-0.1.0/docs/comparison.md +67 -0
- hydra_sandbox-0.1.0/docs/faq.md +111 -0
- hydra_sandbox-0.1.0/docs/index.md +42 -0
- hydra_sandbox-0.1.0/docs/launch/BLOG_POST_1.md +96 -0
- hydra_sandbox-0.1.0/docs/launch/BLOG_POST_2.md +98 -0
- hydra_sandbox-0.1.0/docs/launch/BLOG_POST_3.md +129 -0
- hydra_sandbox-0.1.0/docs/launch/HN_SHOW_HN.md +33 -0
- hydra_sandbox-0.1.0/docs/launch/REDDIT_LANGCHAIN.md +57 -0
- hydra_sandbox-0.1.0/docs/launch/REDDIT_PYTHON.md +58 -0
- hydra_sandbox-0.1.0/docs/launch/TWITTER_THREAD.md +50 -0
- hydra_sandbox-0.1.0/docs/quickstart.md +86 -0
- hydra_sandbox-0.1.0/docs/strategies.md +89 -0
- hydra_sandbox-0.1.0/docs/threat-model.md +79 -0
- hydra_sandbox-0.1.0/docs/verify.md +92 -0
- hydra_sandbox-0.1.0/examples/github_pr_reviewer.py +65 -0
- hydra_sandbox-0.1.0/examples/llm_repl_tool.py +42 -0
- hydra_sandbox-0.1.0/examples/student_grader.py +75 -0
- hydra_sandbox-0.1.0/examples/verified_function.py +61 -0
- hydra_sandbox-0.1.0/mkdocs.yml +50 -0
- hydra_sandbox-0.1.0/pyproject.toml +104 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/__init__.py +27 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/_version.py +3 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/audit.py +201 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/cli.py +136 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/executor.py +205 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/guard.py +103 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/static_analyzer.py +114 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/strategies/__init__.py +146 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/strategies/base.py +44 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/strategies/landlock_strategy.py +101 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/strategies/seccomp_strategy.py +182 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/strategies/subprocess_strategy.py +99 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/telemetry.py +49 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/verified_executor.py +228 -0
- hydra_sandbox-0.1.0/src/hydra_sandbox/verify/__init__.py +133 -0
- hydra_sandbox-0.1.0/tests/__init__.py +0 -0
- hydra_sandbox-0.1.0/tests/benchmarks/__init__.py +0 -0
- hydra_sandbox-0.1.0/tests/benchmarks/test_performance.py +94 -0
- hydra_sandbox-0.1.0/tests/test_audit.py +176 -0
- hydra_sandbox-0.1.0/tests/test_escape_attempts.py +592 -0
- hydra_sandbox-0.1.0/tests/test_executor.py +356 -0
- hydra_sandbox-0.1.0/tests/test_guard.py +110 -0
- hydra_sandbox-0.1.0/tests/test_static_analyzer.py +146 -0
- hydra_sandbox-0.1.0/tests/test_verified.py +129 -0
- hydra_sandbox-0.1.0/tests/test_verify.py +108 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "mkdocs.yml"
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
pages: write
|
|
13
|
+
id-token: write
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
deploy:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
environment:
|
|
19
|
+
name: github-pages
|
|
20
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.13"
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: pip install mkdocs-material mkdocstrings[python]
|
|
32
|
+
|
|
33
|
+
- name: Build docs
|
|
34
|
+
run: mkdocs build
|
|
35
|
+
|
|
36
|
+
- name: Setup Pages
|
|
37
|
+
uses: actions/configure-pages@v4
|
|
38
|
+
|
|
39
|
+
- name: Upload artifact
|
|
40
|
+
uses: actions/upload-pages-artifact@v3
|
|
41
|
+
with:
|
|
42
|
+
path: site/
|
|
43
|
+
|
|
44
|
+
- name: Deploy to GitHub Pages
|
|
45
|
+
id: deployment
|
|
46
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pypi:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write # OIDC trusted publishing
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.13"
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip build
|
|
26
|
+
python -m build
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
30
|
+
|
|
31
|
+
- name: Create GitHub Release
|
|
32
|
+
uses: softprops/action-gh-release@v1
|
|
33
|
+
with:
|
|
34
|
+
generate_release_notes: true
|
|
35
|
+
files: dist/*
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
16
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
17
|
+
exclude:
|
|
18
|
+
# Reduce matrix size — skip some combos for speed
|
|
19
|
+
- os: macos-latest
|
|
20
|
+
python-version: "3.10"
|
|
21
|
+
- os: macos-latest
|
|
22
|
+
python-version: "3.11"
|
|
23
|
+
- os: windows-latest
|
|
24
|
+
python-version: "3.10"
|
|
25
|
+
- os: windows-latest
|
|
26
|
+
python-version: "3.11"
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
32
|
+
uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: ${{ matrix.python-version }}
|
|
35
|
+
|
|
36
|
+
- name: Install dependencies
|
|
37
|
+
run: |
|
|
38
|
+
python -m pip install --upgrade pip
|
|
39
|
+
pip install -e ".[dev,verify]"
|
|
40
|
+
|
|
41
|
+
- name: Lint with ruff
|
|
42
|
+
run: ruff check src/ tests/
|
|
43
|
+
|
|
44
|
+
- name: Type check with mypy
|
|
45
|
+
run: pip install mypy && mypy src/hydra_sandbox --ignore-missing-imports || true
|
|
46
|
+
|
|
47
|
+
- name: Run tests with coverage
|
|
48
|
+
run: pytest tests/ -v --cov=src/hydra_sandbox --cov-report=xml --cov-report=term --ignore=tests/benchmarks
|
|
49
|
+
|
|
50
|
+
- name: Upload coverage to Codecov
|
|
51
|
+
uses: codecov/codecov-action@v4
|
|
52
|
+
with:
|
|
53
|
+
file: ./coverage.xml
|
|
54
|
+
flags: ${{ matrix.os }},python${{ matrix.python-version }}
|
|
55
|
+
continue-on-error: true
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to hydra-sandbox will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] — Unreleased
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- `execute_python()` with subprocess, seccomp, and landlock strategies
|
|
9
|
+
- Import guard blocking dangerous stdlib modules
|
|
10
|
+
- AST signature verification (`verify_ast_signature`, `extract_expected_signature`)
|
|
11
|
+
- Z3 formal specification checker (`check_spec`, `VerificationSpec`, `VerificationResult`)
|
|
12
|
+
- `verified_execute()` combining sandbox execution with Z3 proofs
|
|
13
|
+
- Merkle audit trail (`AuditLog`)
|
|
14
|
+
- CLI entry point (`hydra-sandbox`)
|
|
15
|
+
- Escape attempt test suite
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hydra Sandbox Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hydra-sandbox
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Hardened Python sandbox for running untrusted code — subprocess, seccomp, landlock strategies with Z3 formal verification.
|
|
5
|
+
Project-URL: Homepage, https://github.com/akaradje/hydra-sandbox
|
|
6
|
+
Project-URL: Documentation, https://github.com/akaradje/hydra-sandbox
|
|
7
|
+
Project-URL: Repository, https://github.com/akaradje/hydra-sandbox.git
|
|
8
|
+
Project-URL: Issues, https://github.com/akaradje/hydra-sandbox/issues
|
|
9
|
+
Author: Hydra Sandbox Contributors
|
|
10
|
+
Maintainer: Hydra Sandbox Contributors
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: code-execution,formal-verification,landlock,llm,sandbox,seccomp,security,z3
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
19
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
26
|
+
Classifier: Topic :: Security
|
|
27
|
+
Classifier: Topic :: Software Development :: Testing
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Provides-Extra: all
|
|
30
|
+
Requires-Dist: landlock>=0.1; extra == 'all'
|
|
31
|
+
Requires-Dist: pyseccomp>=0.1; extra == 'all'
|
|
32
|
+
Requires-Dist: z3-solver>=4.12.0; extra == 'all'
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-timeout>=2.0.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
39
|
+
Provides-Extra: landlock
|
|
40
|
+
Requires-Dist: landlock>=0.1; extra == 'landlock'
|
|
41
|
+
Provides-Extra: seccomp
|
|
42
|
+
Requires-Dist: pyseccomp>=0.1; extra == 'seccomp'
|
|
43
|
+
Provides-Extra: verify
|
|
44
|
+
Requires-Dist: z3-solver>=4.12.0; extra == 'verify'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# hydra-sandbox
|
|
48
|
+
|
|
49
|
+
[](https://pypi.org/project/hydra-sandbox/)
|
|
50
|
+
[](https://pypi.org/project/hydra-sandbox/)
|
|
51
|
+
[](https://github.com/akaradje/hydra-sandbox/blob/main/LICENSE)
|
|
52
|
+
[](https://github.com/akaradje/hydra-sandbox/actions)
|
|
53
|
+
[](https://codecov.io/gh/akaradje/hydra-sandbox)
|
|
54
|
+
|
|
55
|
+
Hardened Python execution sandbox for running untrusted code.
|
|
56
|
+
|
|
57
|
+
Built for developers building LLM agents, code review bots, and online
|
|
58
|
+
coding platforms who need to execute user-submitted or model-generated
|
|
59
|
+
code without risking the host system.
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
- **Multiple isolation strategies** — subprocess (cross-platform), seccomp
|
|
64
|
+
(Linux syscall filtering), landlock (Linux filesystem sandbox)
|
|
65
|
+
- **Import guard** — blocks dangerous stdlib modules (`subprocess`, `ctypes`,
|
|
66
|
+
`socket`, `multiprocessing`, etc.)
|
|
67
|
+
- **Network isolation** — monkey-patches `socket.socket` to block outbound
|
|
68
|
+
connections
|
|
69
|
+
- **Resource limits** — CPU time, memory, and file descriptor caps (POSIX)
|
|
70
|
+
- **Secret purging** — strips API keys and tokens from the child environment
|
|
71
|
+
- **AST signature verification** — validates function name and parameter lists
|
|
72
|
+
before execution (zero latency, no LLM cost)
|
|
73
|
+
- **Z3 formal verification** — optional pre/post-condition checking with
|
|
74
|
+
mathematical proofs
|
|
75
|
+
|
|
76
|
+
## Installation
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install hydra-sandbox
|
|
80
|
+
|
|
81
|
+
# With optional dependencies
|
|
82
|
+
pip install hydra-sandbox[verify] # Z3 formal verification
|
|
83
|
+
pip install hydra-sandbox[seccomp] # Linux seccomp support
|
|
84
|
+
pip install hydra-sandbox[landlock] # Linux landlock support
|
|
85
|
+
pip install hydra-sandbox[all] # everything
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Quick start
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from hydra_sandbox import execute_python
|
|
92
|
+
|
|
93
|
+
# Run untrusted code in an isolated subprocess
|
|
94
|
+
result = execute_python(
|
|
95
|
+
"print(1 + 1)",
|
|
96
|
+
timeout=5,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
print(result.success) # True
|
|
100
|
+
print(result.stdout) # "2"
|
|
101
|
+
print(result.exit_code) # 0
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Strategy selection
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# Auto-detect the strongest available strategy (default)
|
|
108
|
+
result = execute_python(code, strategy="auto")
|
|
109
|
+
|
|
110
|
+
# Explicit strategies
|
|
111
|
+
result = execute_python(code, strategy="subprocess") # cross-platform
|
|
112
|
+
result = execute_python(code, strategy="seccomp") # Linux only
|
|
113
|
+
result = execute_python(code, strategy="seccomp+landlock") # strongest
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## AST verification
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from hydra_sandbox import verify_ast_signature, extract_expected_signature
|
|
120
|
+
|
|
121
|
+
# Verify a function signature without executing
|
|
122
|
+
error = verify_ast_signature(
|
|
123
|
+
"def add(x, y): return x + y",
|
|
124
|
+
"add",
|
|
125
|
+
["x", "y"],
|
|
126
|
+
)
|
|
127
|
+
print(error) # None — signature is correct
|
|
128
|
+
|
|
129
|
+
# Extract expected signature from a description
|
|
130
|
+
sig = extract_expected_signature(
|
|
131
|
+
"Write function 'process(data: bytes, key: str) -> str'"
|
|
132
|
+
)
|
|
133
|
+
print(sig) # ("process", ["data", "key"])
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Z3 formal verification
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from z3 import Int
|
|
140
|
+
from hydra_sandbox.verify import check_spec, VerificationSpec
|
|
141
|
+
|
|
142
|
+
x, y = Ints("x y")
|
|
143
|
+
spec = VerificationSpec(
|
|
144
|
+
precondition=x > 0,
|
|
145
|
+
postcondition=x + y > y,
|
|
146
|
+
)
|
|
147
|
+
result = check_spec(spec)
|
|
148
|
+
print(result.valid) # True — mathematically proven
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Security
|
|
152
|
+
|
|
153
|
+
See [SECURITY.md](SECURITY.md) for the threat model and supported versions.
|
|
154
|
+
|
|
155
|
+
The `subprocess` strategy provides Python-level isolation suitable for
|
|
156
|
+
most use cases. For production deployments handling truly untrusted code,
|
|
157
|
+
use `seccomp+landlock` on a Linux host with additional hardening.
|
|
158
|
+
|
|
159
|
+
## Telemetry
|
|
160
|
+
|
|
161
|
+
hydra-sandbox includes optional, **opt-in** telemetry. It is **disabled by
|
|
162
|
+
default** and sends nothing unless you explicitly enable it.
|
|
163
|
+
|
|
164
|
+
When enabled, it sends exactly two data points ONCE per process lifetime:
|
|
165
|
+
- Package version (`__version__`)
|
|
166
|
+
- Strategy selected (`subprocess`, `seccomp`, etc.)
|
|
167
|
+
|
|
168
|
+
No user code, no environment variables, no PII, no IP address logging.
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
export HYDRA_SANDBOX_TELEMETRY=1 # opt in
|
|
172
|
+
export HYDRA_SANDBOX_NO_TELEMETRY=1 # explicitly opt out (default)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# hydra-sandbox
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/hydra-sandbox/)
|
|
4
|
+
[](https://pypi.org/project/hydra-sandbox/)
|
|
5
|
+
[](https://github.com/akaradje/hydra-sandbox/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/akaradje/hydra-sandbox/actions)
|
|
7
|
+
[](https://codecov.io/gh/akaradje/hydra-sandbox)
|
|
8
|
+
|
|
9
|
+
Hardened Python execution sandbox for running untrusted code.
|
|
10
|
+
|
|
11
|
+
Built for developers building LLM agents, code review bots, and online
|
|
12
|
+
coding platforms who need to execute user-submitted or model-generated
|
|
13
|
+
code without risking the host system.
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- **Multiple isolation strategies** — subprocess (cross-platform), seccomp
|
|
18
|
+
(Linux syscall filtering), landlock (Linux filesystem sandbox)
|
|
19
|
+
- **Import guard** — blocks dangerous stdlib modules (`subprocess`, `ctypes`,
|
|
20
|
+
`socket`, `multiprocessing`, etc.)
|
|
21
|
+
- **Network isolation** — monkey-patches `socket.socket` to block outbound
|
|
22
|
+
connections
|
|
23
|
+
- **Resource limits** — CPU time, memory, and file descriptor caps (POSIX)
|
|
24
|
+
- **Secret purging** — strips API keys and tokens from the child environment
|
|
25
|
+
- **AST signature verification** — validates function name and parameter lists
|
|
26
|
+
before execution (zero latency, no LLM cost)
|
|
27
|
+
- **Z3 formal verification** — optional pre/post-condition checking with
|
|
28
|
+
mathematical proofs
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install hydra-sandbox
|
|
34
|
+
|
|
35
|
+
# With optional dependencies
|
|
36
|
+
pip install hydra-sandbox[verify] # Z3 formal verification
|
|
37
|
+
pip install hydra-sandbox[seccomp] # Linux seccomp support
|
|
38
|
+
pip install hydra-sandbox[landlock] # Linux landlock support
|
|
39
|
+
pip install hydra-sandbox[all] # everything
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from hydra_sandbox import execute_python
|
|
46
|
+
|
|
47
|
+
# Run untrusted code in an isolated subprocess
|
|
48
|
+
result = execute_python(
|
|
49
|
+
"print(1 + 1)",
|
|
50
|
+
timeout=5,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
print(result.success) # True
|
|
54
|
+
print(result.stdout) # "2"
|
|
55
|
+
print(result.exit_code) # 0
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Strategy selection
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
# Auto-detect the strongest available strategy (default)
|
|
62
|
+
result = execute_python(code, strategy="auto")
|
|
63
|
+
|
|
64
|
+
# Explicit strategies
|
|
65
|
+
result = execute_python(code, strategy="subprocess") # cross-platform
|
|
66
|
+
result = execute_python(code, strategy="seccomp") # Linux only
|
|
67
|
+
result = execute_python(code, strategy="seccomp+landlock") # strongest
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## AST verification
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from hydra_sandbox import verify_ast_signature, extract_expected_signature
|
|
74
|
+
|
|
75
|
+
# Verify a function signature without executing
|
|
76
|
+
error = verify_ast_signature(
|
|
77
|
+
"def add(x, y): return x + y",
|
|
78
|
+
"add",
|
|
79
|
+
["x", "y"],
|
|
80
|
+
)
|
|
81
|
+
print(error) # None — signature is correct
|
|
82
|
+
|
|
83
|
+
# Extract expected signature from a description
|
|
84
|
+
sig = extract_expected_signature(
|
|
85
|
+
"Write function 'process(data: bytes, key: str) -> str'"
|
|
86
|
+
)
|
|
87
|
+
print(sig) # ("process", ["data", "key"])
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Z3 formal verification
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from z3 import Int
|
|
94
|
+
from hydra_sandbox.verify import check_spec, VerificationSpec
|
|
95
|
+
|
|
96
|
+
x, y = Ints("x y")
|
|
97
|
+
spec = VerificationSpec(
|
|
98
|
+
precondition=x > 0,
|
|
99
|
+
postcondition=x + y > y,
|
|
100
|
+
)
|
|
101
|
+
result = check_spec(spec)
|
|
102
|
+
print(result.valid) # True — mathematically proven
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Security
|
|
106
|
+
|
|
107
|
+
See [SECURITY.md](SECURITY.md) for the threat model and supported versions.
|
|
108
|
+
|
|
109
|
+
The `subprocess` strategy provides Python-level isolation suitable for
|
|
110
|
+
most use cases. For production deployments handling truly untrusted code,
|
|
111
|
+
use `seccomp+landlock` on a Linux host with additional hardening.
|
|
112
|
+
|
|
113
|
+
## Telemetry
|
|
114
|
+
|
|
115
|
+
hydra-sandbox includes optional, **opt-in** telemetry. It is **disabled by
|
|
116
|
+
default** and sends nothing unless you explicitly enable it.
|
|
117
|
+
|
|
118
|
+
When enabled, it sends exactly two data points ONCE per process lifetime:
|
|
119
|
+
- Package version (`__version__`)
|
|
120
|
+
- Strategy selected (`subprocess`, `seccomp`, etc.)
|
|
121
|
+
|
|
122
|
+
No user code, no environment variables, no PII, no IP address logging.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
export HYDRA_SANDBOX_TELEMETRY=1 # opt in
|
|
126
|
+
export HYDRA_SANDBOX_NO_TELEMETRY=1 # explicitly opt out (default)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
| ------- | ------------------ |
|
|
7
|
+
| 0.1.x | :white_check_mark: |
|
|
8
|
+
|
|
9
|
+
## Threat Model
|
|
10
|
+
|
|
11
|
+
hydra-sandbox is designed to protect against:
|
|
12
|
+
|
|
13
|
+
1. **Malicious code execution** — code that attempts to access the filesystem,
|
|
14
|
+
network, or spawn subprocesses
|
|
15
|
+
2. **Resource exhaustion** — CPU, memory, and file descriptor limits
|
|
16
|
+
3. **Import-based escapes** — using `__import__`, `importlib`, or `ctypes` to
|
|
17
|
+
bypass restrictions
|
|
18
|
+
4. **Information disclosure** — leaking environment variables, secrets, or
|
|
19
|
+
host filesystem paths
|
|
20
|
+
|
|
21
|
+
## Limitations
|
|
22
|
+
|
|
23
|
+
- **subprocess strategy** (default, cross-platform): Relies on Python-level
|
|
24
|
+
import guards and socket monkey-patching. Determined attackers may bypass
|
|
25
|
+
via AST manipulation or compiled extensions.
|
|
26
|
+
- **seccomp strategy** (Linux only): Kernel-level syscall filtering. Requires
|
|
27
|
+
`libseccomp` and the `pyseccomp` package.
|
|
28
|
+
- **landlock strategy** (Linux 5.13+): Filesystem access control at the
|
|
29
|
+
kernel level. Requires the `landlock` Python package.
|
|
30
|
+
|
|
31
|
+
For production deployments handling truly untrusted code, use the
|
|
32
|
+
`seccomp+landlock` strategy on a Linux host with additional hardening
|
|
33
|
+
(container, VM, or dedicated machine).
|
|
34
|
+
|
|
35
|
+
## Reporting a Vulnerability
|
|
36
|
+
|
|
37
|
+
If you discover a sandbox bypass or security vulnerability, please
|
|
38
|
+
open a GitHub Security Advisory at:
|
|
39
|
+
https://github.com/akaradje/hydra-sandbox/security/advisories
|
|
40
|
+
|
|
41
|
+
Do NOT open a public issue for security vulnerabilities.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
All benchmarks measured on Windows 11, Python 3.13, Intel Core i7.
|
|
4
|
+
|
|
5
|
+
Run with: `pytest tests/benchmarks --benchmark-only`
|
|
6
|
+
|
|
7
|
+
## AST Signature Verification
|
|
8
|
+
|
|
9
|
+
| Test | Mean | OPS/sec | Target |
|
|
10
|
+
|------|------|---------|--------|
|
|
11
|
+
| `verify_ast_signature` (valid) | 24.5 μs | 40,837 | >10,000 ✅ |
|
|
12
|
+
| `verify_ast_signature` (mismatch) | 23.0 μs | 43,506 | >10,000 ✅ |
|
|
13
|
+
|
|
14
|
+
The AST verifier runs in **~24 microseconds** — zero latency, zero LLM cost.
|
|
15
|
+
At 40,000+ operations per second it can gate every code generation call
|
|
16
|
+
without becoming a bottleneck.
|
|
17
|
+
|
|
18
|
+
## Sandbox Execution Roundtrip
|
|
19
|
+
|
|
20
|
+
| Test | Mean | Baseline |
|
|
21
|
+
|------|------|----------|
|
|
22
|
+
| Raw `subprocess.run` | 26.2 ms | — |
|
|
23
|
+
| `execute_python` (auto strategy) | 36.3 ms | +39% |
|
|
24
|
+
| `execute_python` (subprocess strategy) | 43.9 ms | +68% |
|
|
25
|
+
|
|
26
|
+
The sandbox adds **10-18 ms** overhead over raw `subprocess.run`, primarily
|
|
27
|
+
from the import guard preamble compilation and environment setup. This is
|
|
28
|
+
well within acceptable bounds for interactive use cases.
|
|
29
|
+
|
|
30
|
+
## Strategy Overhead
|
|
31
|
+
|
|
32
|
+
The `auto` strategy has ~3 ms detection overhead at first call (probing
|
|
33
|
+
seccomp/landlock availability), cached for subsequent calls. Explicit
|
|
34
|
+
strategy selection (`strategy="subprocess"`) skips the probe entirely.
|