sficheck
sficheck (SFI-check) finds proprietary software at every level, kernel drivers, the hypervisor, the BIOS/UEFI and devices that need nonfree drivers or firmware.
Origins
sficheck is a fork of absolutely-proprietary by Vasilis Mavromatis and contributors. The original was a single script for Arch-based distros: it checked pacman packages against Parabola's blacklists and printed your Stallman Freedom Index. This fork adds:
- system package managers beyond pacman (dpkg, rpm, nix, flatpak, snap, brew) and 28 language package managers
- the kernel, hypervisor, firmware and hardware scans (rings 0 to -3), each selectable on its own
- opt-in browser and Android scans, anti-feature tags, and
--in-use - install-time warnings for pacman, apt and dnf
- the classification chain: user blacklists, ecosystem authorities, curated lists, SPDX parsing and online license lookups
- JSON output, a config file, caching, and a test suite with Hypothesis property tests
Install
uv tool install sficheck # or: pipx install sficheck
sficheck
Python 3.11 or newer. Dependencies: msgspec (list files), license-expression (licenses), httpx2 (online lookups), psutil (--in-use), and on Linux pyudev (devices; needs libudev).
- From a clone,
python -m sficheck. - On Arch, build the
PKGBUILDin this repo withmakepkg -si.
Usage
sficheck # scan every layer, list what's nonfree
sficheck --full # also list semifree and uses-nonfree findings
sficheck --firmware # scan one layer only
sficheck --in-use # only what is running right now
sficheck --sort ring # deepest findings first
sficheck --browser # add browser extensions and DRM (opt-in)
sficheck --android # rate a phone connected over adb (opt-in)
sficheck --format json | jq # machine-readable report
sficheck --list-sources # what sficheck can scan on this machine
Output
=============================================
5 ABSOLUTELY PROPRIETARY PACKAGES INSTALLED
=============================================
Your system is infected with 5 proprietary packages out of 1311 found (8 unknown) across 11 sources.
Your Stallman Freedom Index is 99.62
By protection ring: 3 user: 5
+--------+----------+-------------+---------+---------------+
| Source | Packages | Proprietary | Unknown | Freedom index |
+--------+----------+-------------+---------+---------------+
| dpkg | 1081 | 5 | 0 | 99.54 |
| pip | 131 | 0 | 4 | 100.00 |
| gem | 95 | 0 | 2 | 100.00 |
...
+--------+-------+------------+---------+--------+--------------------+--------------------------------------------+
| Source | Name | Version | Status | Ring | Libre alternatives | Description |
+--------+-------+------------+---------+--------+--------------------+--------------------------------------------+
| dpkg | nikto | 1:2.1.5-3 | nonfree | 3 user | | in Debian's non-free archive area |
+--------+-------+------------+---------+--------+--------------------+--------------------------------------------+
Other formats: --format markdown, csv or json, and -o FILE writes to a file.
System & Language package managers (--software)
pacman— Arch and derivatives, checked against Parabola's blacklist and aur-blacklist.--include-privacyaddsyour-privacy-blacklist.txt. Packages that aren't blacklisted count as free.dpkg— Debian, Ubuntu, Mint… The archive area decides:non-free,non-free-firmware,restrictedandmultiverseare nonfree,contribis uses-nonfree. Third-party packages (Chrome, VS Code, Teams…) come from the curated list.rpm— Fedora, RHEL, openSUSE, Mageia… The License tag from the rpm database, as SPDX on current Fedora or as older Callaway names likeGPLv2+andASL 2.0. Firmware taggedLicenseRef-Fedora-FirmwareorRedistributable, no modification permittedis nonfree.nix—nix-env,nix profileand NixOSsystemPackages, using nixpkgsmeta.license.free.Python—pip(default interpreter),uvtools,pipxJavaScript/TypeScript—npm,pnpm,yarn,bun,denoJVM—sdkman(Oracle JDK and GraalVM builds are nonfree),coursier, and the opt-in cachesmavenandgradle- .
NET—dotnetglobal tools, and the opt-innugetcache C/C++ —vcpkg,conanOthers— Rustcargo· Gogo· Rubygem· PHPcomposer· Perlcpan· Lualuarocks· Rr· Juliajulia· Haskellghc-pkg· Elixirmix· Dart/Flutterpub· Swiftmint
Opt-in sources only run when named, e.g. --sources maven,gradle.
Browser (--browser, opt-in)
browser— extensions you installed in Firefox and Chromium-based browsers (Chrome, Chromium, Brave, Edge, Vivaldi), and the Widevine DRM module those browsers download to play protected video. Widevine is nonfree and taggeddrm.- It reads only these local files, never history, cookies or passwords:
- Firefox:
extensions.jsonand thegmp-widevinecdmfolder in each profile, under~/.mozilla/firefox(plus its flatpak and snap locations). - Chromium-based: each extension's
manifest.json(and its_localesfolder for the display name) under<profile>/Extensions, and theWidevineCdmfolder, under~/.config/<browser>.
- Firefox:
- Firefox's built-in add-ons, themes, dictionaries and language packs are skipped.
- With
--online-licenses, Firefox extensions are looked up on addons.mozilla.org, which publishes the license each developer declares; a custom license stays unknown. Chrome Web Store doesn't publish licenses, so Chromium extensions rely on the curatedbrowser.jsonand are unknown otherwise.
How a package is classified
- nonfree — blatantly nonfree software.
- semifree — mostly free, but contains some nonfree software.
- uses-nonfree — free, but depends on, recommends or integrates with nonfree software or services.
- free — free software.
- unknown — no license information could be found.
Protection rings
Proprietary findings also carry the CPU protection ring the software runs in. A proprietary calendar can only see what you give it. A kernel anticheat sees everything the OS does, and the Intel ME keeps running while the machine is off.
| Ring | Runs as | Examples |
|---|---|---|
| -3 ME | a coprocessor (ME = Management Engine) or the CPU itself, below the OS | Intel ME, AMD PSP, CPU microcode |
| -2 firmware | system firmware | BIOS/UEFI |
| -1 hypervisor | underneath every OS on the machine | Hyper-V, VMware, Parallels, the VirtualBox Extension Pack |
| 0 kernel | the kernel | Riot Vanguard, Easy Anti-Cheat, BattlEye, FACEIT AC, nvidia |
| 3 user | an ordinary program | everything else |
Only what runs now: --in-use
--in-use keeps only what is in use right now
- Running programs come from the process list (psutil).
- Kernel drivers, firmware and devices always count as in use.
Warnings at install time
sudo sficheck --install-hook pacman (or apt, or dnf) adds a hook that warns before the package manager installs something proprietary:
sficheck: unrar is nonfree (proprietary license); free alternatives: unar
The hook only warns. It never blocks an install, even when sficheck itself is broken or has been uninstalled. It checks new installs only, never upgrades,
The package manager runs the hook as root, so sficheck must be installed where only root can change it: your distro's package, the PKGBUILD, or sudo pipx install --global. --install-hook refuses a copy under your home directory, since anyone who could edit it could then run code as root. The hook runs sficheck by the absolute path it was installed from, so reinstall the hook if you move sficheck.
| Package manager | File written | How it's called |
|---|---|---|
| pacman | /etc/pacman.d/hooks/sficheck.hook |
a PreTransaction hook for Operation = Install, given the package names |
| apt | /etc/apt/apt.conf.d/50sficheck |
DPkg::Pre-Install-Pkgs with protocol version 2, which tells new installs from upgrades; each .deb's section is read with dpkg-deb |
| dnf5 | /etc/dnf/libdnf5-plugins/actions.d/sficheck.actions |
a pre_transaction action, run per new package with its name and License tag; needs libdnf5-plugin-actions |
Options
what to scan (every layer except the opt-in ones by default)
--software system and language package managers (ring 3)
--kernel kernel modules and third-party drivers (ring 0)
--hypervisors the hypervisor this OS runs on, and installed ones (ring -1)
--firmware BIOS/UEFI (ring -2), Intel ME / AMD PSP and microcode (ring -3)
--hardware devices that need a nonfree driver or firmware blobs
--browser browser extensions and DRM modules (opt-in)
--android a phone's apps over adb (opt-in; scored separately)
--kind system|lang package managers of this kind only (repeatable)
--sources A,B / --skip A,B name sources / skip sources
--list-sources show every source and whether it's available, then exit
what to show
--status S nonfree|semifree|uses-nonfree|free|unknown|all (repeatable; default: nonfree)
-f, --full nonfree, semifree and uses-nonfree
--all every package, free ones too
--show-unknown also packages that couldn't be classified
--unknown-as-nonfree count unknown packages against the index
--in-use only what is in use now
--max-ring N only ring N or deeper (-3 … 3)
--sort source|name|status|ring|alternatives -s (status) -a (alternatives) -r (reverse)
output
--format table|markdown|json|csv -o, --output FILE --color auto|always|never
-q, --quiet -v, --verbose --exit-code (exit 1 if anything proprietary is found)
lists and lookups
--blacklist PATH|https-URL (repeatable) --ignore PKG (repeatable) --no-bundled --include-privacy
--online-licenses --offline --refresh --cache-ttl HOURS (default 24) --jobs N (default 8)
install-time hooks (Linux, root)
--install-hook pacman|apt|dnf --remove-hook pacman|apt|dnf
Configuration and cache
Defaults for any option can live in ~/.config/sficheck/config.json
{
"full": true,
"ignore": ["steam"],
"blacklist": ["~/my-blacklist.txt"],
"skip": ["gradle"]
}
User blacklists use either Parabola's text format (name:replacement:ref:id:[status] description) or the bundled JSON format. They're read from a local path or an https:// URL.
Downloads (Parabola lists, registry lookups) are cached for 24 hours in ~/.cache/sficheck. If the network fails, a stale cache is used. --offline never touches the network.
Development
With uv and make:
make sync # dev environment from uv.lock
make format # sort imports, reformat
make lint # ruff, mypy, complexipy, vulture, deptry, zizmor
make test # pytest, including Hypothesis property tests
make audit # pip-audit the locked dependencies
make install # install the command for your user (uv tool install)
make schema # regenerate the JSON Schemas in docs/
make clean # caches and build output
uv run tox -p # the tests on every supported Python
uv run python scripts/check_lists.py --online # after editing the lists
License
GPL-3.0-or-later, the same as upstream. See LICENSE and NOTICE.
Metadata
Release files for sficheck 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sficheck-0.2.0.tar.gz | 113.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sficheck-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 216.3 kB
Release files / sficheck-0.2.0.tar.gz
| Download URL | sficheck-0.2.0.tar.gz |
|---|---|
| Size | 113.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6502a0a87d7eb73622f94fce8c06bf52897e5e23ebe3b71bd42075fa01c6cfe0
|
|
BLAKE2b-256 checksum How to use checksums |
350d982fdefe22b95dd102647f533f9ece85604027b7e3341d8dfbf1a0b7f850
|
| 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 Oct 15, 2026.
Transparency logRelease files / sficheck-0.2.0-py3-none-any.whl
| Download URL | sficheck-0.2.0-py3-none-any.whl |
|---|---|
| Size | 102.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bc0c2c54b6037c8db5566f9e83f8d477a277e91a88cca9e5eb8c197a01ed58f9
|
|
BLAKE2b-256 checksum How to use checksums |
6d8a32240d57cbb5fa0879fbd9a105ff6c1e143fe619a36401343d08e66ce3d7
|
| 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 Oct 15, 2026.
Transparency log