A proactive supply-chain defense tool for Python environments.
Project description
Note: This repository received assistance from generative AI tools for refactoring, tests, and documentation. All AI-assisted changes were reviewed and approved by a human maintainer — see
docs/policies/AI_POLICY.mdfor details.
🛡️ Skopos (v0.25.0)
Overview
The Zero-Trust Gatekeeper for your Python Environment.
Skopos (Greek for "watcher/lookout") is a high-speed forensic audit tool designed to stop supply-chain attacks before they touch your disk. It sits between you and the internet, ensuring that every uv add or pip install is safe, verified, and free of "keyword-stuffing" or "brand-jacking" attempts.
Table of Contents
- Overview
- Why Skopos?
- Installation
- Automatic Bouncer (Shim)
- Usage & Examples
- Performance
- Forensic Heuristics
- License
- Contributing
Why Skopos?
Standard package managers are built for speed, not security. They assume that if a package exists on PyPI, it’s safe to run. They are wrong.
Skopos protects you from:
- Keyword Stuffing: Malicious packages like
requests-ultraorpip-security-patch. - Brand-jacking: Fake versions of popular tools (e.g.,
google-auth-v2by an unknown dev). - Account Hijacking: Suddenly active projects after years of silence.
- Obfuscated Payloads: Detection of "packed" or encrypted code in package metadata.
Installation
Choose the workflow that matches your environment. Both approaches are supported — pick one.
For Pip users
If you prefer standard Python packaging and virtual environments, follow these steps.
Create and activate a virtual environment (recommended):
python -m venv .venv
source .venv/bin/activate
Install Skopos into the active environment:
# During development
pip install -e .
# Or install the released package
pip install skopos-audit
Reload your shell if you modified rc files:
source ~/.bashrc
# or
source ~/.zshrc
Quick verification for Pip users:
which skopos || skopos --version
For UV users (recommended workflow)
If you use uv as your package manager, Skopos can be installed as an uv tool and hooked into uv add.
Install via uv:
uv tool install skopos-audit
After installing via uv, refresh uv so it picks up the new tool entry:
uvx --refresh skopos
If you still want to isolate the CLI into a virtual environment (recommended for development), create and activate one first and then install into it via pip install -e ..
Example (recommended development workflow):
# create and activate a venv
python3 -m venv .venv
source .venv/bin/activate
# install the project in editable mode
pip install -e .
# verify the CLI is available
which skopos || skopos --version
If you prefer not to install, run the shim from the repository root (this sets PYTHONPATH to src/):
PYTHONPATH="$PWD/src" ./scripts/skopos-uv.sh add <package>
Automatic Bouncer (Shim)
The best way to use Skopos is to let it intercept your commands automatically. This adds a split-second security check whenever you try to add a new dependency.
- Locate the Shim: The script is located in
scripts/skopos-uv.sh. - Add to your shell (append to
~/.bashrcor~/.zshrc):
alias uv='source /path/to/your/skopos/scripts/skopos-uv.sh'
Now, when you run uv add <package>, Skopos audits the package first. If the score is too high (malicious), the installation is blocked.
Usage & Examples
You can audit any package without installing it:
skopos check requests-ultra
Example Output (Malicious Package):
🔍 Auditing: requests-ultra
------------------------------------------------------------
❌ Typosquatting: FLAG (Match: requests - Keyword stuffing)
⚠️ Identity: Unknown (New Account / Unverified)
✅ Payload: Clean (No obfuscation)
------------------------------------------------------------
🚨 SKOPOS SCORE: 120/100 (MALICIOUS)
🚫 Action: Installation Blocked.
Performance
Is it slow? No. Version 0.23.0 removed the heavy RestrictedPython sandbox. Skopos now performs "Static Metadata Forensics."
- Speed: Checks usually take < 500ms.
- Safety: We never execute the code we are auditing. We analyze the "fingerprints" left on PyPI.
Forensic Heuristics
Skopos uses a weighted scoring system to evaluate risk:
- Name Similarity: reqests vs requests (Levenshtein)
- Keyword Stuffing: requests-security-update
- Author Reputation: Brand new accounts uploading high-value names
- Entropy Scan: Encrypted or obfuscated code strings
- Project Velocity: "Zombie" projects that suddenly wake up
License
MIT. Built for developers who value their ssh keys and environment variables.
Configuration
Skopos supports a user-overridable configuration file at ~/.skopos/config.toml.
You can bootstrap a template with:
skopos config init
Key configuration options (defaults shown in etc/skopos_default_config.toml):
targets: a table mapping high-value package names to a Levenshtein threshold (integer).keyword_extra_chars: how many extra characters beyond a brand name still trigger a keyword-stuffing flag.scoring_weights: numeric weights used when aggregating heuristic failures into a final score.
Example ~/.skopos/config.toml snippet:
[targets]
requests = 1
openai = 1
keyword_extra_chars = 6
[scoring_weights]
typosquatting = 120
payload_risk = 60
If the file is missing or malformed, Skopos falls back to safe defaults so behavior does not change.
Security Caveats
-
Install-time execution risk: Some malicious packages execute code during build or installation (for example via
setup.pyor custom build backends inpyproject.toml). Skopos inspects metadata and performs static forensics; it does not and must not execute package build or install scripts. As a result, certain installation-time behaviors may not be detectable by static checks alone. Treat Skopos as an added safety layer — not a replacement for isolated analysis of untrusted artifacts. -
Operational advice: Never build or install untrusted packages on your primary workstation. If you need to analyze package contents, do so in an isolated VM or container with no secrets and limited network access, and prefer static inspection (unpacking archives and scanning files) over executing any build scripts.
-
Limitations While
skoposperforms metadata forensics and reduces risk, it is not perfect and may not catch every malicious package or installation-time behavior. Consider Skopos' findings advisory — for high-risk or sensitive packages, perform isolated, in-depth analysis in a disposable VM or container.
Examples (Good vs Malicious)
These examples show typical output from uvx skopos check <package> and what happens when you run uv add <package> with the shim installed.
Good package (example):
$ uvx skopos check requests
🔍 Auditing: requests
------------------------------------------------------------
✅ Typosquatting: PASS
✅ Identity: PASS (Known maintainer)
✅ Payload: Clean
------------------------------------------------------------
✅ SKOPOS SCORE: 95/100 (SAFE)
The project was previously named spectr; some older docs or tools may still reference that name. The same audit behavior is shown here using the legacy command (replace with skopos if you have the newer CLI):
$ uvx spectr check requests
🔍 Auditing: requests
------------------------------------------------------------
✅ Typosquatting: PASS
✅ Identity: PASS (Known maintainer)
✅ Payload: Clean
------------------------------------------------------------
✅ SPECTR/SKOPOS SCORE: 95/100 (SAFE)
Malicious package (example):
$ uvx skopos check evil-package
🔍 Auditing: evil-package
------------------------------------------------------------
❌ Typosquatting: FLAG (Match: requests - Keyword match)
⚠️ Identity: Unknown (New Account / Unverified)
✅ Payload: Clean
------------------------------------------------------------
🚨 SKOPOS SCORE: 10/100 (MALICIOUS)
What happens during uv add when the shim is active:
- If the package passes the check,
uv addproceeds as normal. - If the package is flagged (non-zero failure), the shim aborts the install and returns a non-zero exit code. Example:
$ uv add evil-package
[Skopos] Security Gate: Installation aborted due to high risk score.
# installation aborted; package not added
Which commands are wrapped
Skopos provides two ways to intercept package installs:
- The shell shim script
scripts/skopos-uv.sh(recommended foruvusers) interceptsuv addanduv runand performs a pre-install audit. - The built-in
--install-hook(viaskopos --install-hook) installs a minimaluv()wrapper into your shell rc which currently interceptsuv addbefore invoking the realuvcommand.
Both approaches are conservative and will skip blocking behavior if the skopos CLI is not available on PATH (in which case they print a warning and allow the underlying command to continue).
Using the repository shims (local development)
If you are developing Skopos or want to run the CLI without installing, use the provided shims in scripts/.
- Bash (Unix/macOS):
# Run a local check using the repo sources (no install required)
bash scripts/skopos-uv.sh check requests
# Intercept an install (shim will audit then forward to your `uv` binary)
bash scripts/skopos-uv.sh add some-package
- PowerShell (Windows):
# From repo root
.\scripts\skopos-uv.ps1 check requests
Notes:
- The shims prefer
python3but will fall back topythonif needed. - The bash shim resolves the repository root using the script location, then runs the module with
PYTHONPATHset to the repo'ssrc/directory so you don't need topip installduring development. - If you prefer a persistent alias, add the following to your shell rc (use with care):
alias uv='bash /path/to/skopos/scripts/skopos-uv.sh'
Troubleshooting:
- If you see
skopos not found, ensure you ran the shim from the repository root, or installskopos-auditinto your environment. - On systems where
pythonresolves to Python 2, the shim will trypython3. If neither is present, install Python 3.10+.
If you want, I can also add annotated screenshots or richer example logs for CI usage and a short section describing how to tune thresholds for your organization.
Offline Snyk enrichment (quick start)
Skopos can include offline Snyk-like vulnerability feeds as optional enrichment. This is useful for air-gapped environments or when you want a deterministic, local vulnerability dataset.
- Put a Snyk-style JSON feed on disk (example:
etc/snyk_offline_sample.json). - Register the feed with Skopos:
# Writes the path into ~/.skopos/config.toml under [integrations.snyk]
skopos integrations load-snyk /full/path/to/snyk_offline.json
- Enable the adapter in your
~/.skopos/config.toml:
[integrations.snyk]
enabled = true
offline_file = "/full/path/to/snyk_offline.json"
When enabled, Snyk findings from the offline feed will be included in reports and factored into scoring (weight: snyk_vuln). The loader only edits your configuration file and performs no network activity.
Note: the demo script and the offline sample feed are intentionally excluded from packaged releases (see MANIFEST.in) and therefore won't be installed via pip or uv tool install. To run the demo, clone the repository and run scripts/demo_offline_snyk.sh locally.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file skopos_audit-0.25.0.tar.gz.
File metadata
- Download URL: skopos_audit-0.25.0.tar.gz
- Upload date:
- Size: 29.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30af2b2a29a0ca71fae85cdeaa32ea1039b8e792e39bdf7a7280c67dd9817300
|
|
| MD5 |
276f133f5bbd6ff18f42ea95f499a937
|
|
| BLAKE2b-256 |
a66eff7f4727f453bc937d4797dbe4934f044b55d99bcd887767710abf46952c
|
File details
Details for the file skopos_audit-0.25.0-py3-none-any.whl.
File metadata
- Download URL: skopos_audit-0.25.0-py3-none-any.whl
- Upload date:
- Size: 20.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09c7f8a4d7c2e0014c6133f7a3fa41ff20bb851cbbb914702944a6fa5ea023db
|
|
| MD5 |
831745d0b734f3d4e6ae7476e3b1e9f6
|
|
| BLAKE2b-256 |
fee99218cae99b95b8e5e7607439892a6141773d70d2084ef9b5ec9aafec000c
|