Skip to main content

An AI Supply Chain security tool that that detects Pickle bombs and generates CycloneDX SBOMs for Machine Learning models.

Project description

AIsbom: The Supply Chain for Artificial Intelligence

PyPI version GitHub Marketplace License Python Compliance

Detect malware and license risks hidden inside ML model files โ€” statically, before you load them.

AIsbom disassembles Pickle bytecode and parses SafeTensors / GGUF binary headers to surface RCE-capable payloads and restrictive licenses that generic SBOM tools miss. Pure static analysis โ€” no model code is ever executed.

๐Ÿ’ก Also available as a GitHub Action that posts an idempotent PR comment on every commit. See it on the Marketplace โ†’

AIsbom CLI demo


Try it in one command

Zero-install โ€” pipx fetches the latest release, runs it, then cleans up:

pipx run --spec aisbom-cli aisbom scan hf://google-bert/bert-base-uncased

That scans BERT directly over HTTP, without downloading 400 MB of weights to disk. You'll see a security + legal risk table in your terminal and a sbom.json file in your current directory.

Want to see the same scan visualized? Open the live demo โ†’

For persistent install:

pipx install aisbom-cli           # or: pip install aisbom-cli
aisbom scan hf://google-bert/bert-base-uncased

The PyPI package name is aisbom-cli, but the command you run is aisbom. That's why pipx run needs --spec aisbom-cli.


What it finds

A typical scan against a project with mixed artifacts:

                           ๐Ÿง  AI Model Artifacts Found                           
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
โ”ƒ Filename            โ”ƒ Framework   โ”ƒ Security Risk        โ”ƒ Legal Risk                  โ”ƒ
โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ
โ”‚ bert_finetune.pt    โ”‚ PyTorch     โ”‚ CRITICAL (RCE Found) โ”‚ UNKNOWN                     โ”‚
โ”‚ safe_model.st       โ”‚ SafeTensors โ”‚ LOW                  โ”‚ UNKNOWN                     โ”‚
โ”‚ restricted_model.st โ”‚ SafeTensors โ”‚ LOW                  โ”‚ LEGAL RISK (cc-by-nc-4.0)   โ”‚
โ”‚ llama-3-quant.gguf  โ”‚ GGUF        โ”‚ LOW                  โ”‚ LEGAL RISK (cc-by-nc-sa)    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

A compliant sbom.json (CycloneDX v1.6) including SHA256 hashes and license data is generated in your working directory. SPDX 2.3 export is one flag away (--format spdx).

Don't like reading JSON? Open the viewer โ†’, drag your sbom.json in, and get an instant dashboard of risks, license issues, and compliance stats. The viewer is client-side only โ€” your data never leaves your browser.


Install

Method Best for
pipx run --spec aisbom-cli aisbom ... Trying it without committing
pipx install aisbom-cli Daily use; isolated venv
pip install aisbom-cli Python projects with their own venv
Standalone binary Air-gapped / offline / no-Python environments

Standalone binaries

Single-file executables for Linux x86_64, macOS Intel, and macOS Silicon. Download from the Releases page. Zero dependencies. Runs on bare metal.

๐Ÿ“š How to Audit Air-Gapped / Offline Systems

macOS quarantine note

macOS tags downloaded files with a "quarantine" attribute, and unsigned open-source binaries get blocked by Gatekeeper. Run once:

chmod +x aisbom-macos-*
xattr -d com.apple.quarantine aisbom-macos-*
./aisbom-macos-arm64 --help

Common workflows

Scan a Hugging Face model

aisbom scan hf://google-bert/bert-base-uncased

We use HTTP Range requests to inspect just the headers โ€” scans complete in seconds and use zero disk. Verify SafeTensors compliance before you git clone.

Authentication (private & gated Hugging Face models)

To scan a private or gated Hugging Face model, set a Hugging Face access token in the environment. AIsbom reads HF_TOKEN first, then HUGGING_FACE_HUB_TOKEN (the same precedence as huggingface_hub):

export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxx
aisbom scan hf://your-org/private-model

The token is sent only to huggingface.co as a bearer credential on the model-metadata requests; it is dropped on the redirect to the presigned LFS CDN and is never attached to any other host. It is never written to logs and never included in telemetry โ€” the only token-related field we emit is a token_present boolean (whether a token was set), never the value itself. See Telemetry & Privacy.

In CI, supply the token from a secret and make sure the runner can reach Hugging Face:

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - run: pip install aisbom-cli
      - run: aisbom scan hf://your-org/private-model
        env:
          HF_TOKEN: ${{ secrets.HF_TOKEN }}

Egress note: hosted/firewalled CI runners must allow outbound HTTPS to huggingface.co and its LFS CDN (cdn-lfs.huggingface.co and the presigned object-storage hosts it redirects to). A blocked CDN hop surfaces as a network/timeout error, not an auth failure.

Share a scan with your team

aisbom scan ./my-project-folder --share

Generates a hosted, shareable link. The SBOM is uploaded to aisbom.io and remains viewable for 30 days. You'll be prompted to confirm before upload (use --share-yes to skip the prompt in CI). For exactly what the uploaded document contains, see Telemetry & Privacy.

Detect drift between two scans

aisbom diff baseline_sbom.json new_sbom.json

Exits with code 1 when:

  • A new CRITICAL risk is introduced
  • A component's risk level escalates (e.g., LOW โ†’ CRITICAL)
  • A verified file's hash changes (marked INTEGRITY FAIL)
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
โ”ƒ Component     โ”ƒ Type     โ”ƒ Change  โ”ƒ Security Risk        โ”ƒ Legal Risk         โ”ƒ Details        โ”ƒ
โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ
โ”‚ drift-risk.pt โ”‚ Modified โ”‚ DRIFT   โ”‚ LOW โ†’ CRITICAL       โ”‚ -                  โ”‚                โ”‚
โ”‚ drift-license โ”‚ Modified โ”‚ DRIFT   โ”‚ -                    โ”‚ UNKNOWN โ†’          โ”‚ Lic: MIT โ†’     โ”‚
โ”‚               โ”‚          โ”‚         โ”‚                      โ”‚ LEGAL RISK         โ”‚ CC-BY-NC       โ”‚
โ”‚ drift-hash.pt โ”‚ Modified โ”‚ DRIFT   โ”‚ INTEGRITY FAIL       โ”‚ -                  โ”‚ Hash: ...      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Strict mode (allowlist)

For high-security environments, switch from blocklisting (looking for known-bad imports) to allowlisting (blocking everything unknown):

aisbom scan model.pkl --strict

Allowed modules: torch (and submodules), numpy, collections, typing, datetime, re, pathlib, copy, functools, dataclasses, uuid. Any unknown global import is flagged CRITICAL.

Migration readiness (weights_only=True)

PyTorch 2.6+ defaults to weights_only=True, which breaks many legacy models:

aisbom scan model.pt --lint

The Migration Linter statically simulates the unpickling stack to predict runtime failures without executing code.

๐Ÿ›ก๏ธ  Migration Readiness (weights_only=True)
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
โ”ƒ File           โ”ƒ Issue                         โ”ƒ Recommendation                         โ”ƒ
โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ
โ”‚ mock_broken.pt โ”‚ Custom Class Import Detected: โ”‚ Module 'aisbom' is not in PyTorch      โ”‚
โ”‚                โ”‚ aisbom.mock.Layer             โ”‚ default allowlist. Use                 โ”‚
โ”‚                โ”‚                               โ”‚ `torch.serialization.add_safe_globals` โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Markdown report (CI/CD)

aisbom scan . --format markdown --output report.md

Generates a GitHub-flavored Markdown report suitable for PR comments and CI artifacts.

SPDX 2.3 export (enterprise compliance)

aisbom scan . --format spdx --output sbom.spdx.json

Use as a GitHub Action

Scan ML artifacts on every PR and post a single idempotent comment summarizing findings, with a link to the hosted viewer:

# .github/workflows/aisbom.yml
name: AIsbom Security Scan
on:
  pull_request:
    paths: ['models/**', 'requirements.txt']

permissions:
  contents: read
  pull-requests: write    # required for the PR comment

jobs:
  aisbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Lab700xOrg/aisbom@v1
        with:
          directory: models/

When CRITICAL or HIGH findings are detected, the Action posts a comment like this:

AIsbom Action โ€” CRITICAL findings

When the scan is clean, the comment collapses to a one-line โœ…:

AIsbom Action โ€” clean PR

Re-runs update the same comment in place via a hidden <!-- aisbom-action --> marker โ€” you'll never see stacked AIsbom comments on the same PR.

Hosted dashboard (optional)

The PR comment shows you each scan; the hosted dashboard at app.aisbom.io keeps the history. Set the optional token input and every scan's SBOM is posted to your inventory dashboard, where you can browse artifacts across repos and branches, track drift over time, and share an executive view with compliance stakeholders:

      - uses: Lab700xOrg/aisbom@v1
        with:
          directory: models/
          token: ${{ secrets.AISBOM_TOKEN }}

Get a per-repo token at https://app.aisbom.io/connect (sign in with GitHub). Leave token unset and the Action stays purely local โ€” nothing is sent to the dashboard.

Data flow & privacy

When (and only when) token is set, the Action POSTs the generated CycloneDX SBOM JSON to https://app.aisbom.io/v1/scan-result, along with the branch/tag name (GITHUB_REF_NAME) so the dashboard can attribute results to the right ref. That's the entire payload: the SBOM describes the structure and findings of your model files (names, hashes, licenses, risk levels) โ€” never the weights or file contents, which don't leave the GitHub runner. Data is stored in the EU (Cloudflare R2/D1, EU jurisdiction). Every upload is announced in a loud log group in your CI output, so your logs always show when a network call happened and where the data went. To stop uploading, remove the token input โ€” there is no background or implicit sending.

See action/README_ACTION.md for the full inputs/outputs reference, permissions block, and troubleshooting.


Try it on a real pickle bomb

Don't trust the scanner? Scan a bomb yourself. AIsbom ships a built-in mock-malware generator so you can confirm the scanner catches a real RCE payload (and that it's not just lighting up false positives on safe files).

# 1. Generate the mock artifacts
aisbom generate-test-artifacts

# 2. Scan them
aisbom scan .

You'll see mock_malware.pt flagged as CRITICAL, license issues flagged on the restricted models, and (with --lint) mock_broken.pt appear in the Migration Readiness table.


Defense in Depth

AIsbom advocates for a two-layer approach:

  1. Layer 1 โ€” Pre-execution. aisbom scan --lint statically analyzes the file structure. Catches obvious malware and incompatible globals without ever loading the file.
  2. Layer 2 โ€” Runtime isolation. If you must load a model with REDUCE opcodes or unsafe globals (common in legacy files), don't run it on bare metal. Use Sandboxed Execution (e.g., uvx + amazing-sandbox) to contain any potential RCE.

[!TIP] Why both? Static analysis is fast but can be defeated by complex obfuscation. Runtime sandboxing is secure but slow. Together, they give you speed and safety.


Why AIsbom?

AI models aren't just text files โ€” they're executable programs and IP assets.

  • The security risk. PyTorch (.pt) files are Zip archives containing Pickle bytecode. A malicious model executes arbitrary code (RCE) the moment it's loaded.
  • The legal risk. A developer might download a "non-commercial" model (e.g., CC-BY-NC) and ship it to production. The license is embedded in the binary header โ€” standard SBOM tools miss it entirely.
  • The solution. AIsbom looks inside. We decompile bytecode and parse binary metadata headers without loading the heavy weights into memory.

How it works

AIsbom uses a static analysis engine to disassemble Python Pickle opcodes. It looks for specific GLOBAL and STACK_GLOBAL instructions referencing dangerous modules:

  • os / posix (system calls)
  • subprocess (shell execution)
  • builtins.eval / exec (dynamic code execution)
  • socket (network reverse shells)

SafeTensors and GGUF use binary formats with structured headers โ€” AIsbom parses these headers directly to extract metadata (artifact names, license info, architecture details) without loading tensor weights.

For weekly scan findings on the top 50 most-downloaded Hugging Face text-generation models, see aisbom.io/advisories.


Telemetry & Privacy

AIsbom collects a small amount of anonymous usage telemetry โ€” what model formats people scan, how often critical findings appear, whether scans run in CI โ€” to help us prioritize what to build. We treat this with the same care we expect from any security tool. Read what we collect, then opt out if you'd rather not participate.

What's collected

Per aisbom scan: target_type (the bucket: local / huggingface / http / https โ€” never the actual path or URL), model_format (the file-type bucket), risk_level_max, scan_duration_ms, file_count, parse_error_count, strict_mode. A cli_scan_critical_found event with a count is added when at least one CRITICAL is found.

If you explicitly use --share: the generated sbom.json document is uploaded to our servers and retained for 30 days to generate the shareable viewer link. That document is the full CycloneDX SBOM โ€” for each scanned model it carries the file name, SHA-256 hash, detected license, and structured aisbom:* properties describing the file's format and scan findings (such as dangerous pickle opcodes, tensor/header metadata, model architecture details, and the assessed risk and legal status) so the hosted viewer can render per-format detail. These describe the structure and findings of your model files, never their weights or data. Nothing leaves your machine unless you pass --share and confirm the prompt (or pass --share-yes). A cli_share_created event is fired tracking whether has_share_yes=true|false.

Per aisbom diff: a cli_diff event with has_drift=true|false.

On a scan fetch failure or unhandled exception: a cli_error event records the exception class name only (e.g. JSONDecodeError), a low-cardinality http_status bucket (e.g. 401, timeout), and a token_present boolean (whether an HF_TOKEN / HUGGING_FACE_HUB_TOKEN was set) โ€” never the token value, the message, the traceback, a URL, or any file content.

Each event carries an anonymous user_id โ€” a SHA-256 of your machine's MAC address plus an app salt, truncated to 16 hex chars. Stored in ~/.aisbom/config.json. Lets us see returning users without identifying anyone.

What's never collected

File paths, directory contents, model names, target URLs, file hashes from your SBOMs, exception messages, tracebacks, or anything that could identify you, your project, or your organization.

Opt out

Set AISBOM_NO_TELEMETRY=1. This wins over every other setting โ€” telemetry will not fire and ~/.aisbom/config.json will not be written.

# Permanent
export AISBOM_NO_TELEMETRY=1

# Single invocation
AISBOM_NO_TELEMETRY=1 aisbom scan ./my-project

Where the data goes

Events POST to https://api.aisbom.io/v1/telemetry (a Cloudflare Worker we operate), which sanitizes the payload and forwards to Google Analytics 4 on the dedicated cli.aisbom.io data stream. We don't share, sell, or use this data for ad targeting.

CI environments

When CI=true or GITHUB_ACTIONS=true, the cli_install_first_seen event is suppressed (containers are ephemeral and would otherwise spam the metric). Other events still fire, tagged is_ci=true.

Status

As of 0.9.1, telemetry is on by default. AISBOM_NO_TELEMETRY=1 is the single opt-out lever and is honored on every code path. The previous AISBOM_TELEMETRY_V2=1 opt-in flag was retired once the rollout soak completed โ€” setting it today is a harmless no-op.


Links


Built with โค๏ธ in Austin.

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

aisbom_cli-1.2.0.tar.gz (49.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aisbom_cli-1.2.0-py3-none-any.whl (48.8 kB view details)

Uploaded Python 3

File details

Details for the file aisbom_cli-1.2.0.tar.gz.

File metadata

  • Download URL: aisbom_cli-1.2.0.tar.gz
  • Upload date:
  • Size: 49.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1018-azure

File hashes

Hashes for aisbom_cli-1.2.0.tar.gz
Algorithm Hash digest
SHA256 36f9a7821e642d0e9a3407d1999e316daba9e2edc97d4122f791c6f607e82592
MD5 f863c5d77df199b9d07dc1c8a5b6e7e2
BLAKE2b-256 3ece10b1cb66abf9f14693758aaf533d86064bd4a388bb2f1d895d702a483b0e

See more details on using hashes here.

File details

Details for the file aisbom_cli-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: aisbom_cli-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 48.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1018-azure

File hashes

Hashes for aisbom_cli-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0cf820ecf971f2f7a0fb5af3208717f9f2df90103ffb1e74d01a3012ffdbdc4c
MD5 f0cc126c3fde391f0cb4f1a29349c60d
BLAKE2b-256 33a3d959d8a760dbdcf57660c2a558ef32902cb6e6599e44c67f44b809e90d16

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page