AI Component Security Platform — static security analysis for AI components (CLI engine)
Project description
SkillTotal
AI Component Security Platform — open-source CLI engine.
SkillTotal statically analyzes AI-related components (skills, plugins, MCP servers, npm / Python packages, repositories) to surface supply-chain risks, dangerous capabilities, prompt-injection surfaces, and data-exfiltration paths before the component is installed or trusted.
Try it online (no install, no account): www.skilltotal.ai —
the website runs this same engine. Prefer the CLI? pipx install skilltotal (below).
It analyzes only the component itself — never your user, company, environment, deployment, or runtime context. Every score and finding is derived exclusively from the files inside the component.
Core principle: every confirmed finding carries evidence (file, line range, code snippet). Anything that cannot be evidenced is placed in
needs_review, never infindings, and never affects the score.
Why SkillTotal
- 100% local & offline — the component's code never leaves your machine. No account, no API token, no cloud upload (unlike cloud scanners that send your components to a backend).
- Zero runtime dependencies, pure Python stdlib — auditable and easy to vendor/air-gap.
- Deterministic — regex + AST, no LLM in the static engine; the same input always yields the same report.
- Evidence-anchored & low false-positive — every finding points at an exact file:line.
- Free and open source (Apache-2.0) — the full static report is free, forever.
Install
Requires Python 3.10+. Zero runtime dependencies. git is required only for scanning
remote URLs.
Recommended for the CLI — pipx (isolated install; also works on
Debian/Ubuntu where bare pip install is blocked by PEP 668):
pipx install skilltotal
Or into a virtual environment / as a library:
pip install skilltotal
From source (development):
pip install -e ".[dev]"
Usage
# Human-readable report
skilltotal scan ./path/to/component
# Scan a remote repository (shallow git clone)
skilltotal scan https://github.com/owner/repo
# Scan a package from a registry (latest, or a pinned version)
skilltotal scan npm:left-pad
skilltotal scan npm:left-pad@1.3.0
skilltotal scan pypi:requests
skilltotal scan pypi:requests==2.31.0
# JSON to stdout
skilltotal scan ./component --json
# SARIF 2.1.0 (GitHub Code Scanning / IDE)
skilltotal scan ./component --sarif --output report.sarif
# Write the report to a file (SARIF if --sarif, else JSON)
skilltotal scan ./component --output report.json
# CI gate: exit code 2 if any finding is high or critical
skilltotal scan ./component --fail-on-high
# Baseline: snapshot current findings, then suppress them on later scans
skilltotal scan ./component --write-baseline .skilltotal-baseline.json
skilltotal scan ./component --baseline .skilltotal-baseline.json --fail-on-high
# Inventory: discover AI components already installed on this machine and scan them
# (reads agent configs for Claude Desktop/Code, Cursor, Windsurf, VS Code, Gemini, and
# local skills; derives an npm:/pypi:/local source per MCP server and runs the engine)
skilltotal inventory
skilltotal inventory --json
skilltotal inventory --no-scan # list only, do not scan
skilltotal inventory --project . # also include this project's agent configs
# List every detection rule
skilltotal rules list
skilltotal rules list --json
Baseline suppresses findings by a stable fingerprint of
(rule id, file, code snippet) — independent of line numbers, so it survives edits.
Suppressed findings are removed before scoring and do not affect the risk score.
python -m skilltotal ... works identically to the skilltotal console script.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Usage / collection error (e.g. path missing, clone failed) |
| 2 | --fail-on-high set and a finding of severity ≥ high was produced |
What it detects
| Category | Examples |
|---|---|
| Shell execution | subprocess.*, os.system, child_process.exec |
| Filesystem access | open, read_text/write_text, fs.readFile/writeFile |
| Sensitive paths | ~/.ssh, ~/.aws, .env, id_rsa, credentials, secrets |
| Network egress | requests, urllib, aiohttp, fetch, axios |
| Install-time execution | npm preinstall/postinstall/prepare, setup.py hooks |
| Dynamic code execution | eval, exec, compile, new Function, vm.runInNewContext |
| Obfuscation | decode-and-execute chains, base64 blobs, hex escaping, minification |
| MCP risks | manifests, dangerous tools (shell/fs/network/credential), server commands |
| Prompt surface | "ignore previous instructions", "reveal system prompt", exfiltration phrasing |
Output
A normalized report containing the component identity, a risk score (0–100) and risk level (low / medium / high / critical), detected capabilities (each evidence-backed), findings, needs_review, and metadata. See docs/report-schema.md and docs/scoring.md.
Architecture
The package under skilltotal/ (except cli.py) is a pure, side-effect-free library so the
same engine can power the future web app and enterprise SaaS. See
docs/architecture.md.
Development
pip install -e ".[dev]"
pytest
Accuracy notes
- Python is analyzed via an AST (resolves import aliases, tells
open(p,'w')from a read, ignores API names that only appear in strings/comments). Node.js/config use regex. - Test code (
__tests__/,*.test.*,tests/,conftest.py, …) is demoted toneeds_review— it is not executed by consumers, so it does not affect the score. - Ambiguous signals (bare
secrets/credentialswords, lone base64 blobs, "before answering" phrasing, minified files) go toneeds_review, never tofindings. - Hidden Unicode (ASCII-smuggling tag characters, Trojan-Source bidi overrides,
zero-width chars) is detected and decoded — a real evasion used to smuggle instructions
past human review. See
tests/manual_eval/for calibration against real-world attacks. - Shell execution covers
subprocess/os.system,asyncio.create_subprocess_*, Nodechild_process, and common process-spawning libraries (Pythonsh/plumbum/pexpect/invoke/fabric; Nodezx/execa/cross-spawn/shelljs/tinyexec/node-pty). - MCP dangerous tools are classified by name/description both in JSON manifests and when
defined in code (
server.tool("run_command", …),@mcp.tooloverdef read_file). - Limitations: detection is at the call/import level. Capability via an unrecognized higher-level library (e.g. a git library that writes files internally, a browser library) may not be flagged as a raw filesystem/shell call. Capabilities indicate presence, not proven misuse.
Open source vs SkillTotal Cloud
SkillTotal is open core. This engine (analysis + all detection rules + CLI) is open source and complete on its own — run it locally or in CI, free, offline, with zero runtime dependencies. It tells you what a component does, with evidence.
Paid features are delivered only via SkillTotal Cloud (the website) and explain why it matters: LLM interpretation and prioritization of findings, dynamic sandbox execution, hosting, scan history, and monitoring. They are server-side services on top of this engine — their code is not part of this repository. See docs/open-core.md.
License
Apache-2.0. See also NOTICE.
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 skilltotal-0.7.3.tar.gz.
File metadata
- Download URL: skilltotal-0.7.3.tar.gz
- Upload date:
- Size: 82.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
440fe16c450becc608902eeb5cb9f09d58c13d8f986df55cd0049dcfb4568d9b
|
|
| MD5 |
d60492b1357989fdcab88de25053fae0
|
|
| BLAKE2b-256 |
030fe6984483f181ebc67c3d16028c7d73c5c3d298462967745ec48b95b415cb
|
Provenance
The following attestation bundles were made for skilltotal-0.7.3.tar.gz:
Publisher:
release.yml on pezhik/skilltotal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skilltotal-0.7.3.tar.gz -
Subject digest:
440fe16c450becc608902eeb5cb9f09d58c13d8f986df55cd0049dcfb4568d9b - Sigstore transparency entry: 1805009552
- Sigstore integration time:
-
Permalink:
pezhik/skilltotal@8bf0bf78a89c9961fb78de8771211c6a0aad0d4c -
Branch / Tag:
refs/tags/v0.7.3 - Owner: https://github.com/pezhik
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8bf0bf78a89c9961fb78de8771211c6a0aad0d4c -
Trigger Event:
push
-
Statement type:
File details
Details for the file skilltotal-0.7.3-py3-none-any.whl.
File metadata
- Download URL: skilltotal-0.7.3-py3-none-any.whl
- Upload date:
- Size: 72.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eebc98c39bd9d13e744e2390284abefd20f6de8ba1e4e37b9fa9c031e0e1850e
|
|
| MD5 |
5da963883da73c401423154d44517e99
|
|
| BLAKE2b-256 |
90b600228560d9c41dd1fb001ccda06958e13ce55e8bf8940182680b5d4885d6
|
Provenance
The following attestation bundles were made for skilltotal-0.7.3-py3-none-any.whl:
Publisher:
release.yml on pezhik/skilltotal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skilltotal-0.7.3-py3-none-any.whl -
Subject digest:
eebc98c39bd9d13e744e2390284abefd20f6de8ba1e4e37b9fa9c031e0e1850e - Sigstore transparency entry: 1805009559
- Sigstore integration time:
-
Permalink:
pezhik/skilltotal@8bf0bf78a89c9961fb78de8771211c6a0aad0d4c -
Branch / Tag:
refs/tags/v0.7.3 - Owner: https://github.com/pezhik
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8bf0bf78a89c9961fb78de8771211c6a0aad0d4c -
Trigger Event:
push
-
Statement type: