Skip to main content

Model Trust Gateway — unified secure loader with signature verification, trust policy enforcement, and sandbox isolation

Project description

secure-torch

Model Trust Gateway — Unified, defense-in-depth Python library for safely loading AI model files.

CI PyPI Python License: Apache 2.0


What is secure-torch?

Loading third-party AI models is a supply chain risk. torch.load, ONNX Runtime, and safetensors have all been vectors for RCE, data exfiltration, and silent model tampering.

secure-torch is a Model Trust Enforcement Layer — not just a safe loader wrapper.

It adds what the ML ecosystem is missing:

Feature What it does
Signature verification Verify model provenance before loading (online + offline)
Trust policy enforcement Block models from untrusted publishers
Pickle opcode validation Inspect opcodes without executing — blocks RCE payloads
Sandbox isolation Load in restricted subprocess (seccomp on Linux)
Explainable threat scoring Named breakdown, not a magic number
SBOM parsing SPDX AI Profile support (experimental)

How it complements safetensors

safetensors solves unsafe deserialization and memory safety. secure-torch adds the trust layer on top — signature verification, publisher policy, and provenance validation — for safetensors, PyTorch pickle, and ONNX alike.


Quick Start

pip install secure-torch

Drop-in usage

import secure_torch as torch          # drop-in replacement

model = torch.load("model.pt")        # safe by default

Require a valid signature

model = torch.load(
    "model.pt",
    require_signature=True,
    bundle_path="model.pt.sigstore",  # online Rekor verification
)

Offline verification (enterprise / air-gapped)

model = torch.load(
    "model.pt",
    require_signature=True,
    pubkey_path="trusted.pub",        # Ed25519 public key
    bundle_path="model.pt.sig",       # raw signature bytes
)

Trusted publishers allowlist

model = torch.load(
    "model.pt",
    trusted_publishers=["huggingface.co/meta", "openai.com"],
)

Audit first, block later (gradual adoption)

model, report = torch.load("model.pt", audit_only=True)

print(report.threat_level)       # ThreatLevel.LOW
print(report.score_breakdown)    # {'unsigned_model': 40}
print(report.warnings)           # ['No signature bundle found']

Sandbox isolation

model = torch.load("model.pt", sandbox=True)
# Model loaded in restricted subprocess — no network, no exec

Other compatibility surfaces

torch.jit.load("model.pt")  # secure pipeline for local artifacts
torch.hub.load("pytorch/vision", "resnet50")      # remote convenience passthrough
torch.from_pretrained("bert-base-uncased")        # remote convenience passthrough
torch.save(model, "model.pt")

torch.hub.load and direct torch.from_pretrained calls do not currently enforce secure-torch security checks for remote fetches. Passing security arguments (require_signature, trusted_publishers, audit_only, max_threat_score, sandbox, sbom_*, bundle_path, pubkey_path) raises SecurityError. For enforced security controls, download artifacts first and call torch.load(local_path, ...), or use secure_torch.patch_huggingface(...) for Hugging Face download interception.

Hugging Face integration (automatic download scanning)

import secure_torch
from transformers import AutoModel

# Global monkey-patch: intercept hf_hub_download and validate model files.
secure_torch.patch_huggingface(require_signature=False, max_threat_score=20)

model = AutoModel.from_pretrained("gpt2")

# Optional cleanup when done.
secure_torch.unpatch_huggingface()

patch_huggingface(...) hooks huggingface_hub.file_download.hf_hub_download. For model-like files (.pt, .pth, .bin, .safetensors, .onnx, .h5, .keras), secure-torch runs format detection, validators, signature/publisher checks, and threat policy evaluation before returning the downloaded file path. Unsafe artifacts are blocked with UnsafeModelError.

Interactive CLI audit

# Styled report (rich-enabled when available)
secure-torch audit model.pt

# Machine-readable output
secure-torch audit model.pt --json

Pipeline

Every secure_load() call runs this fixed pipeline — steps cannot be skipped:

secure_load(file)
  1. format detect        ← .safetensors / .pt / .onnx / magic bytes
  2. signature verify     ← fail fast if require_signature=True
  3. threat score         ← explainable named dict
  4. policy enforce       ← trusted_publishers check
  5. sandbox load         ← subprocess (+ seccomp on Linux)
  6. return tensors

Threat Scoring

Scores are named and explainable — not a magic number:

model, report = torch.load("model.pt", audit_only=True)
print(report.score_breakdown)
# {
#   'unsigned_model': 40,
#   'custom_ops_detected': 30,
#   'unknown_publisher': 20,
# }
# total: 90 → ThreatLevel.CRITICAL
Score Threat Level
0 SAFE
1–19 LOW
20–49 MEDIUM
50–79 HIGH
80+ CRITICAL

Default max_threat_score is 20 (MEDIUM). Adjust with max_threat_score=N.


SBOM Policy (Experimental)

Note: SPDX AI Profile is not yet widely adopted (early 2026). This feature is forward-looking — secure-torch is helping establish the standard.

from secure_torch.sbom.spdx_parser import parse_sbom
from secure_torch.sbom.opa_runner import OPAPolicyRunner

sbom = parse_sbom("model.spdx.json")
runner = OPAPolicyRunner("policy/production.rego")
denials = runner.evaluate(sbom, context={"environment": "production"})

if denials:
    raise RuntimeError(f"Policy violations: {denials}")

Example policy (policy/production.rego):

package secure_torch.policy

deny[msg] {
    input.sensitivePersonalInformation == "yes"
    msg := "Model contains sensitive personal information"
}

deny[msg] {
    ds := input.aiProfile.trainingDatasets[_]
    startswith(ds.license, "GPL")
    input.environment == "production"
    msg := sprintf("GPL dataset '%v' blocked in production", [ds.name])
}

Supported Formats

Format Validator Notes
.safetensors Header + dtype allowlist Complements safetensors library
.pt / .pth / .bin Pickle opcode validator Never executes pickle
.onnx Protobuf inspector Custom op domain detection

Signature Verification

Mode 1 — Online (Sigstore / Rekor)

# Sign your model
cosign sign-blob model.pt --bundle model.pt.sigstore

# Verify on load
torch.load("model.pt", require_signature=True, bundle_path="model.pt.sigstore")

Mode 2 — Offline (Ed25519 pubkey)

# Sign
openssl genpkey -algorithm ed25519 -out private.pem
openssl pkey -in private.pem -pubout -out public.pem
openssl pkeyutl -sign -inkey private.pem -in model.pt -out model.pt.sig

# Verify on load
torch.load("model.pt", require_signature=True, pubkey_path="public.pem", bundle_path="model.pt.sig")

CVE Coverage

CVE Attack Status
CVE-2023-44271 PyTorch pickle RCE (Salesforce) ✅ Blocked
CVE-2023-32686 Keras Lambda RCE ✅ Blocked
GHSA-v9fq-2296 HuggingFace metadata injection ✅ Scored
CVE-2024-5980 NVIDIA Triton ONNX custom op RCE ✅ Scored

Installation

pip install secure-torch

# With ONNX support
pip install secure-torch[onnx]

# With Sigstore online verification
pip install secure-torch[sigstore]

# With offline public-key verification
pip install secure-torch[crypto]

# Everything
pip install secure-torch[all]

Development

git clone https://github.com/Avanishk05/secure-torch
cd secure-torch
pip install -e .
pip install pytest pytest-cov mypy ruff bandit
pytest tests/

License

Apache 2.0 — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

secure_torch-0.1.0.tar.gz (31.1 kB view details)

Uploaded Source

Built Distribution

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

secure_torch-0.1.0-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

File details

Details for the file secure_torch-0.1.0.tar.gz.

File metadata

  • Download URL: secure_torch-0.1.0.tar.gz
  • Upload date:
  • Size: 31.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for secure_torch-0.1.0.tar.gz
Algorithm Hash digest
SHA256 43fb6839145ebb2da53501cf7abb1eb8e6cd431cac11573514a1adcf0d91372d
MD5 512b61b871e78e4f8417aba153854d83
BLAKE2b-256 787992d7e67c36e2970b536d1a89f1afec938c8778e6ad4381ca7ca20a8e62aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for secure_torch-0.1.0.tar.gz:

Publisher: ci.yml on Avanishk05/secure-torch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file secure_torch-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: secure_torch-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for secure_torch-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1bd5a84c111ffd01cb71a9cc15fcd5dd692fa3fd2ba671a38fb5b95d58aab9da
MD5 124c3baf41ee3421d97cd73b9f78f0c8
BLAKE2b-256 37fff43f7d3c65bdc33f89f60bf20567c3152c61fdcb940068b64e9d4a0b6a7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for secure_torch-0.1.0-py3-none-any.whl:

Publisher: ci.yml on Avanishk05/secure-torch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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