Security Features

SBOM generation, signing, auditing, and PII redaction

Security Features CLI

Security features for recipes including SBOM generation, bundle signing, dependency auditing, and PII redaction.

Quick Start

bash
# Generate SBOM
praisonai recipe sbom ./my-recipe -o sbom.json

# Audit dependencies
praisonai recipe audit ./my-recipe

# Sign a bundle
praisonai recipe sign my-recipe.praison --key private.pem

# Verify signature
praisonai recipe verify my-recipe.praison --key public.pem

Commands

sbom

Generate Software Bill of Materials (SBOM).

bash
praisonai recipe sbom <recipe> [options]

Options:

OptionDescription
--format <type>Output format: cyclonedx, spdx (default: cyclonedx)
-o, --output <path>Output file path
--jsonOutput JSON to stdout

Examples:

bash
# Generate CycloneDX SBOM
praisonai recipe sbom ./my-recipe --format cyclonedx -o sbom.json

# Generate SPDX SBOM
praisonai recipe sbom ./my-recipe --format spdx -o sbom.spdx.json

# Output to stdout
praisonai recipe sbom ./my-recipe --json

audit

Audit recipe dependencies for vulnerabilities. The scan checks the recipe’s own pinned dependencies (name==version), not the packages installed in your current Python environment.

bash
praisonai recipe audit <recipe> [options]

Options:

OptionDescription
--strictFail on any issues
--jsonOutput JSON format

Examples:

bash
# Basic audit
praisonai recipe audit ./my-recipe

# Strict mode (fail on issues)
praisonai recipe audit ./my-recipe --strict

# JSON output
praisonai recipe audit ./my-recipe --json

Output:

Audit Report: my-recipe
  Lockfile: lock/requirements.lock
  Dependencies: 15
  Vulnerabilities: 0
  Warnings: 1
    - Outdated: requests (2.28.0 -> 2.31.0)
✓ Audit passed

Output when the scan could not run:

Audit Report: my-recipe
  Lockfile: lock/requirements.lock
  Dependencies: 15

  Warnings:
    - Vulnerability scan incomplete: pip-audit is not installed (pip install pip-audit)
✓ Audit passed

Warnings

A Vulnerability scan incomplete: ... warning means the scan did not fully run. Treat it as “not checked”, not as “clean”. The audit still reports Audit passed and --strict does not fail on it, so check the warnings yourself.

WarningMeaning
Vulnerability scan incomplete: pip-audit is not installed (pip install pip-audit)Install pip-audit and re-run
Vulnerability scan incomplete: pip-audit timed out after 60sThe scan took longer than 60s; re-run with a faster network
Vulnerability scan incomplete: pip-audit failed (exit N): ...pip-audit crashed or returned unreadable output; re-run
Vulnerability scan incomplete: no pinned dependencies to scanThe recipe declares no name==version pins
Vulnerability scan incomplete: skipped <pkg>: <reason><pkg> could not be checked (e.g. private or not on PyPI)

sign

Sign a recipe bundle with a private key.

bash
praisonai recipe sign <bundle> --key <private.pem> [options]

Options:

OptionDescription
--key <path>Path to private key (PEM format)
-o, --output <path>Output signature path
--jsonOutput JSON format

Examples:

bash
# Sign a bundle
praisonai recipe sign my-recipe.praison --key private.pem

# Custom signature output
praisonai recipe sign my-recipe.praison --key private.pem -o my-recipe.sig

verify

Verify a signed bundle.

bash
praisonai recipe verify <bundle> --key <public.pem> [options]

Options:

OptionDescription
--key <path>Path to public key (PEM format)
--signature <path>Path to signature file
--jsonOutput JSON format

Examples:

bash
# Verify signature
praisonai recipe verify my-recipe.praison --key public.pem

# Custom signature path
praisonai recipe verify my-recipe.praison --key public.pem --signature my-recipe.sig

SBOM Format

CycloneDX

json
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "metadata": {
    "component": {
      "name": "my-recipe",
      "version": "1.0.0"
    }
  },
  "components": [
    {
      "type": "library",
      "name": "openai",
      "version": "1.0.0",
      "purl": "pkg:pypi/openai@1.0.0"
    }
  ]
}

Lockfile Validation

Validate that recipes have proper lockfiles:

bash
# Validate with lockfile requirement
praisonai recipe validate ./my-recipe --require-lockfile

Supported lockfile formats:

  • lock/requirements.lock (pip-compile)
  • lock/uv.lock (uv)
  • lock/poetry.lock (poetry)

PII Redaction

Configure PII redaction in TEMPLATE.yaml:

yaml
data_policy:
  pii:
    mode: redact  # allow, deny, redact
    fields:
      - email
      - phone
      - ssn
      - credit_card

Python API

python
from praisonai.recipe.security import (
    generate_sbom,
    audit_dependencies,
    sign_bundle,
    verify_bundle,
    validate_lockfile,
    redact_pii,
    detect_pii,
)

# Generate SBOM
sbom = generate_sbom("./my-recipe", format="cyclonedx")

# Audit dependencies — check both vulnerabilities and warnings
report = audit_dependencies("./my-recipe")
if report["vulnerabilities"]:
    print(f"Vulnerabilities: {report['vulnerabilities']}")
if any(w.startswith("Vulnerability scan incomplete") for w in report["warnings"]):
    print(f"Scan incomplete: {report['warnings']}")

# Validate lockfile
result = validate_lockfile("./my-recipe", strict=True)

# Sign bundle
sig_path = sign_bundle("my-recipe.praison", "private.pem")

# Verify bundle
valid, message = verify_bundle("my-recipe.praison", "public.pem")

# Redact PII
data = {"email": "test@example.com"}
policy = {"pii": {"mode": "redact", "fields": ["email"]}}
redacted = redact_pii(data, policy)

# Detect PII
detections = detect_pii(data)

Key Generation

Generate RSA keys for signing:

bash
# Generate private key
openssl genrsa -out private.pem 2048

# Extract public key
openssl rsa -in private.pem -pubout -out public.pem

Exit Codes

CodeMeaning
0Success
2Validation error
6Missing dependencies (cryptography)

Next Steps