Skip to main content

SSHfc

SSHfc is a command validator for SSH's ForceCommand. It lets an SSH user, a person or an agent, run only an explicit allowlist of commands, each with an explicit allowlist of arguments. Anything else is rejected with a short message that says why and what is allowed.

The allowlist is a policy: one or more TOML files in a directory, /etc/sshfc/commands.d/ by default. SSHfc ships sample policies you can use as they are or adapt.

Status: proof of concept. Try a deployment with --dry-run first.

Why SSHfc

  • Allowlist, not blocklist. A command runs only if the policy names it, and each option and argument must pass its validator. There's no "any string" default.
  • No shell. Commands are split with shlex and run directly, so shell syntax in a request does nothing. (The account still needs a login shell for sshd to start SSHfc, but SSH users can't reach it; see Deploying.)
  • Runs what was validated. SSHfc rebuilds the command from its parsed form, so the program never sees an argument the policy didn't allow, and a positional value can't be read as an option.
  • Fails closed. If the policy is missing, insecure or malformed, every command is rejected.
  • Audited. Every SSH invocation is logged to syslog as a JSON record, including what was requested and what ran.

What SSH users see

With SSHfc deployed in --dry-run mode and the sample policies:

$ ssh host "podman ps --format '{{ .ID }}  {{.Image}}'"
Would run: /usr/bin/podman ps --format '{{.ID}}  {{.Image}}'

$ ssh host "podman stop 'web;id'"
SSH command rejected: podman stop -- argument container: invalid value: 'web;id' (expected a container, image, or pod name or ID)

Documentation

Guide For
Deploying SSHfc Installing SSHfc, SSH and sshd configuration, a safe rollout, and the audit log.
Using the sample policies The shipped samples: what they allow and how to use or adapt them.
Adding your own commands Writing a policy, from a one-command file to the full reference.
Checking policies sshfc --check, what it verifies, and how to fix its errors.
Contributing Development setup, checks, tests, and the design rules.

Quick start

Install from PyPI into a root-owned virtual environment, and link the command onto the PATH (see Installing for uv, and for why each step matters):

$ sudo python3 -m venv /opt/sshfc
$ sudo /opt/sshfc/bin/pip install sshfc
$ sudo ln -s /opt/sshfc/bin/sshfc /usr/local/bin/sshfc

Then install a policy and try it:

$ sshfc --samples                          # list the shipped sample policies
$ sudo install -d -m 755 /etc/sshfc/commands.d
$ sshfc --samples podman-readonly | sudo tee /etc/sshfc/commands.d/podman-readonly.toml >/dev/null
$ sudo sshfc --check                       # check the policy and run its examples
$ sshfc --dry-run -c 'podman ps'           # see what a command would run
Would run: /usr/bin/podman ps

Then follow Deploying SSHfc to point an SSH key at it.

License

MIT. See LICENSE.

Metadata

Release files for sshfc 0.3.0

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

Source distribution (sdist)

Source distribution for sshfc 0.3.0
File Size Uploaded Provenance
sshfc-0.3.0.tar.gz 24.0 kB With provenance Details

Built distribution (wheel)

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

Total release size: 54.3 kB

Release files / sshfc-0.3.0.tar.gz

Download URL sshfc-0.3.0.tar.gz
Size 24.0 kB
Tags Source
SHA-256 checksum
How to use checksums
1bb108b06be337ad337a6c8be4bfbc910ee86c7fd061289157f701588d9770b2
BLAKE2b-256 checksum
How to use checksums
a94bc8a53be02acd03296080281790d280a6ea4ddf030597b84f48848d921f39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 26, 2026.

Transparency log

Release files / sshfc-0.3.0-py3-none-any.whl

Download URL sshfc-0.3.0-py3-none-any.whl
Size 30.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
df751569e850d2816f447b9dcc75a6af156452d0ac008a6e40caa0fc0f94fd1c
BLAKE2b-256 checksum
How to use checksums
621afc9227ef63222b32375cae3c4f8225c61accf4c53cf583c911d88fa5e5fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 26, 2026.

Transparency log

Security for sshfc 0.3.0

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 sshfc-0.3.0.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 Oct 26, 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