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 (strict exec/network blocking via seccomp on Linux)

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), 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
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.2.0.tar.gz (33.7 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.2.0-py3-none-any.whl (40.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: secure_torch-0.2.0.tar.gz
  • Upload date:
  • Size: 33.7 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.2.0.tar.gz
Algorithm Hash digest
SHA256 96c47115e7a2259b47f4dba352a81a6da635f4f0f21c09343375e678405fb380
MD5 a272dd7a9b7776d72bf25e338ee3830e
BLAKE2b-256 66da26b44083953aa2f03a117870a8180f7147b6792b874691c14f1a65735a9e

See more details on using hashes here.

Provenance

The following attestation bundles were made for secure_torch-0.2.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: secure_torch-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 40.1 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e4e69fbf3b1f54750d68e281bf009fba3a0543feaf83eabddb86bd948e478a6e
MD5 d820992a3b3a6c111cea87c4384472d3
BLAKE2b-256 81606c55e54a9afb5588f53f1af5b091a178fd433d06a1ce7250ed08a9f58538

See more details on using hashes here.

Provenance

The following attestation bundles were made for secure_torch-0.2.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