Skip to main content

User-space sandbox runner for Python console scripts

Project description

hermetic

Run a python tool, or your application with certain APIs disabled, such as network or subprocess.

The previously safe library you depend on was hijacked and will be sending your password files to a remote server. Or you installed this and the malicious hackers didn't include evasive code to defeat this fig leaf of a security feature and the day is saved.

If Alice and Bob know about your application and specifically are targeting this, this tool won't help.

Usage

Command-Line Interface

Use the hermetic command to run any Python console script, separating its arguments with --.

Syntax: hermetic [flags] -- <command> [command_args]

Common Flags:

  • --no-network: Disable all network activity.
  • --allow-localhost: Allows network connections to localhost (used with --no-network).
  • --allow-domain <domain>: Allows connections to a specific domain (repeatable).
  • --no-subprocess: Disable creating new processes.
  • --fs-readonly[=/path/to/root]: Make the filesystem read-only. Optionally, restrict all reads to be within the specified root directory.
  • --no-environment: Disable environment variable reads and mutations.
  • --no-code-exec: Disable eval, exec, compile, and runpy execution helpers.
  • --deny-import <module>: Deny importing a module or package prefix (repeatable).
  • --no-interpreter-mutation: Disable sys.path, cwd, and site mutation surfaces.
  • --block-native: Block imports of native C extensions.
  • --profile <name>: Apply a pre-configured profile (e.g., block-all).
  • --trace: Print a message to stderr when an action is blocked.

CLI Examples:

Block network access for the httpie tool:

$ hermetic --no-network -- http [https://example.com](https://example.com)

hermetic: blocked action: network disabled: DNS(example.com)

Run a script in a read-only filesystem where it can only read from ./sandbox:

$ hermetic --fs-readonly=./sandbox -- python my_script.py

# my_script.py will raise PolicyViolation if it tries to read outside ./sandbox
# or write anywhere.

Apply the block-all profile to completely lock down a script:

$ hermetic --profile block-all -- my_analyzer.py --input data.csv

Programmatic API

You can use hermetic directly in your Python code via the hermetic_blocker context manager or the @with_hermetic decorator.

Decorator

The @with_hermetic decorator is the easiest way to apply guards to an entire function.

from hermetic import with_hermetic
import requests

@with_hermetic(block_network=True, allow_domains=["api.internal.com"])
def process_data():
    # This will fail because all network access is blocked by default.
    # requests.get("https://example.com") # --> raises PolicyViolation

    # This is allowed because the domain is on the allow-list.
    return requests.get("https://api.internal.com/data")

process_data()

Context Manager

For more granular control, use the hermetic_blocker context manager.

from hermetic import hermetic_blocker
import os

def check_system():
    # Subprocesses are allowed here
    os.system("echo 'Checking system...'")

    with hermetic_blocker(block_subprocess=True):
        # Inside this block, os.system() would raise a PolicyViolation
        print("Running in a sandboxed context.")
        os.system("echo 'This will fail.'") # --> raises PolicyViolation

    # Subprocesses are allowed again
    os.system("echo 'Exited sandbox.'")

check_system()

Where could this work?

There are APIs you don't need but an application or 3rd party library you depend on needs. So you block them.

The 3rd party library must be unaware of hermetic or monkeypatching. Import order is important, hermetic must run early enough to intercept all imports to the banned API. Then use of the banned API is blocked and the whole app stops.

This already works in unit testing where there isn't an adversarial relationship between the developers testing the code and writing the code under test, where you block network traffic to guarantee a unit test is pure of network side effects.

Is this defeatable?

Yes, by many routes. Native code, import order tricks, undoing a monkey patch, bringing along a vendorized copy of APIs, and so on.

This is "envelope instead of postcard" level security. This is "lock your door with standard key that can be picked with a $5 purchase on Ebay" level security.

Real sandboxing is running your code in a docker container.

Prior Art

This technique of monkey-patching for isolation is well-established, particularly in the testing ecosystem.

For stronger sandboxing, consider:

  • pysandbox: Uses Linux seccomp for kernel-level syscall filtering.
  • RestrictedPython: Rewrites Python AST to enforce constraints.
  • Docker: OS-level virtualization.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hermetic_seal-0.2.0.tar.gz (32.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hermetic_seal-0.2.0-py3-none-any.whl (40.5 kB view details)

Uploaded Python 3

File details

Details for the file hermetic_seal-0.2.0.tar.gz.

File metadata

  • Download URL: hermetic_seal-0.2.0.tar.gz
  • Upload date:
  • Size: 32.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for hermetic_seal-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5c22b91f4dfbe7435729c1042150b0dbd9fce2d54cb031ac34ead18d5fec6379
MD5 226f1989071bc0943d7256b8f8a84001
BLAKE2b-256 16645d8bfd21d9fb051237c79ffa7824cb023a6ebe16e09a1a51bec42ff654e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for hermetic_seal-0.2.0.tar.gz:

Publisher: publish_to_pypi.yml on matthewdeanmartin/hermetic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hermetic_seal-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: hermetic_seal-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 40.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for hermetic_seal-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 02a19e039d0c037f824244752e2b716a05349baac90e6788f6d37000531801ac
MD5 c30b7e2237ffd5fc9a4a5c062621fb77
BLAKE2b-256 33c187316a083093ef35e9ecfd0376964d80ccd8d086b8011a02f50e379c299b

See more details on using hashes here.

Provenance

The following attestation bundles were made for hermetic_seal-0.2.0-py3-none-any.whl:

Publisher: publish_to_pypi.yml on matthewdeanmartin/hermetic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page