Skip to main content

shellsafe

Run shell commands safely using Python 3.14 template strings. Values can never turn into commands.

from shellsafe import run

message = get_user_input()          # "fix; rm -rf ~"
run(t"git commit -m {message}")
# argv: ["git", "commit", "-m", "fix; rm -rf ~"]
# one command; the scary text is just an argument

Why this package exists

Python 3.14 added template strings (PEP 750). Now Python keeps your fixed text and your values separate at the language level.

Shell commands are the first place people want to use this. That is because f-strings inside shell commands have caused real security bugs for ten years:

subprocess.run(f"git commit -m {message}", shell=True)
# if message = "fix; rm -rf ~"  ->  two commands run. The second one is bad.

Python planned to solve this officially (PEP 787), but that PEP is still deferred. It is not in the Python 3.15 release candidates. So today there is no standard way to run shell commands safely with templates. This package fills that gap.

Install

pip install shellsafe

Needs Python 3.14 or newer.

How to use

Run a command. Your values always stay one argument each. run() never invokes a shell, so injection is impossible on any platform:

from shellsafe import run

run(t"mkdir {path}")
run(t"docker build -t {tag} .", check=True, timeout=300)

Get the output as text:

from shellsafe import capture

res = capture(t"grep {pattern} {file}")
print(res.stdout, res.returncode)

Need pipes? Works on Linux and macOS. Your values are quoted safely first:

from shellsafe import shx

shx(t"cat {file} | wc -l")

Want to see exactly what will run?

from shellsafe import plan

print(plan(t"git commit -m {message}"))
# argv: ["git","commit","-m","fix; rm -rf ~"]

Safety rules

Case What happens
Any value you pass becomes one argument, exactly as given
Value used as the program name error: program names must be written as fixed text
Shell features on Windows error: we cannot make Windows safe this way, so we say no
RAW() misuse error: one value only, used as-is, no nesting

RAW(...) marks content you have already made safe by hand. It is loud and easy to find in code review, so trust is never hidden.

Find old dangerous patterns

Already have code using f-strings in shell commands? The scanner finds them:

shellsafe audit src/

It detects f-strings passed to os.system, subprocess.run(shell=True), and other shell executors. Get machine-readable output:

shellsafe audit src/ --json

Filter by severity:

shellsafe audit src/ --severity warning

Suppress known-safe findings inline:

# shellsafe: ignore AU001 reason: tested, value is constant
os.system(f"echo {safe_value}")

Suppress from the command line:

shellsafe audit src/ --ignore AU004

Limits

  • Shell features (pipes, redirections) work on Linux and macOS only. Windows supports plain commands only.
  • run() refuses templates that contain shell metacharacters. Use shx() for those.
  • Byte values are rejected. Decode them first.
  • We keep your command safe to build and run. Testing what your command does is still your job.

Needs

  • Python 3.14 or newer
  • Linux, macOS, Windows (pipes work on Linux and macOS only)

More

License: MIT

Metadata

Release files for shellsafe 0.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for shellsafe 0.3.5
File Size Uploaded Provenance Actions
shellsafe-0.3.5.tar.gz 24.9 kB With provenance Details for shellsafe-0.3.5.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for shellsafe 0.3.5
File Interpreter ABI Platform Actions
shellsafe-0.3.5-py3-none-any.whl Python 3 none any Details for shellsafe-0.3.5-py3-none-any.whl

Total release size: 42.2 kB

Release files / shellsafe-0.3.5.tar.gz

Download URL shellsafe-0.3.5.tar.gz
Size 24.9 kB
Tags Source
SHA-256 checksum
How to use checksums
d42c544c07f5068e166284230499119f9fdb3f5159cca7927a673b2a1387992b
BLAKE2b-256 checksum
How to use checksums
d2521f9fdf42571a2f79686526dd1a4bb6fab3513d87b77a8acb73adf41e5c69
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / shellsafe-0.3.5-py3-none-any.whl

Download URL shellsafe-0.3.5-py3-none-any.whl
Size 17.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
adaf6a0f8f8a4ee2ad4eb18dbdc320476b39ac8691354749e5b7d8bd7d1ce162
BLAKE2b-256 checksum
How to use checksums
7ca31dd7a62c5837c0251a30235d625786a51f8dae6ddaaf0f91b1ff7378c7da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Security for shellsafe 0.3.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for shellsafe-0.3.5.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page