Skip to content

build(deps): bump actions/upload-pages-artifact from 3 to 4 #873

build(deps): bump actions/upload-pages-artifact from 3 to 4

build(deps): bump actions/upload-pages-artifact from 3 to 4 #873

Workflow file for this run

name: Security CI
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
permissions:
contents: read
jobs:
security:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python 3.12
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.3.0
with:
python-version: "3.12"
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libzbar0 libgl1 libglib2.0-0 \
build-essential pkg-config libssl-dev \
libpcsclite-dev libudev-dev
- name: Install Python deps
# Editable install (-e .) for local source - can't hash-pin
run: |
pip install --require-hashes -r requirements-pip.lock
pip install --require-hashes -r requirements.lock
pip install --require-hashes -r requirements-dev.lock
pip install --no-deps -e .
pip install --require-hashes -r requirements-ci.lock
- uses: dtolnay/rust-toolchain@d0592fe69e35bc8f12e3dbaf9ad2694d976cb8e3 # stable
with:
toolchain: stable
- name: Build + install Rust crypto backend (maturin)
# Local wheel install - can't hash-pin freshly-built artifacts
run: |
cd rust_crypto
maturin build --release --out dist
python -m pip install --no-deps dist/*.whl
cd ..
- name: Verify Rust backend import
run: |
python - << 'EOF'
try:
import meow_crypto_rs
print("✅ Rust backend import OK")
except Exception as e:
print("❌ Rust backend import failed:", e)
raise
EOF
- name: Bandit security lint (Python static analysis)
run: |
bandit -r meow_decoder -f json -o bandit-report.json || {
echo "⚠️ Bandit found potential security issues - review bandit-report.json"
# Do not fail build yet - treat as warning during initial tuning
}
- name: Security-focused tests (required)
run: |
pytest tests/ -v -m "security or adversarial" || {
echo "Security tests failed!"
exit 1
}
env:
MEOW_TEST_MODE: "1"
MEOW_PRODUCTION_MODE: "0" # Required alongside MEOW_TEST_MODE to allow export_key() in tests
MEOW_CRYPTO_BACKEND: "rust"
# ===========================================================================
# CRIT-01: Verify PQ crypto is NOT in default features
# ===========================================================================
pq-feature-gate:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python 3.12
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.3.0
with:
python-version: "3.12"
- name: Install toml parser
run: pip install --require-hashes -r requirements-ci.lock
- name: Verify pq-crypto NOT in default features
run: |
python << 'EOF'
import toml
import sys
cargo = toml.load("crypto_core/Cargo.toml")
features = cargo.get("features", {})
default = features.get("default", [])
if "pq-crypto" in default:
print("❌ SECURITY VIOLATION: pq-crypto is in default features!")
sys.exit(1)
def get_transitive_features(feature_name, seen=None):
if seen is None:
seen = set()
if feature_name in seen:
return set()
seen.add(feature_name)
result = {feature_name}
for dep in features.get(feature_name, []):
if not dep.startswith("dep:"):
result.update(get_transitive_features(dep, seen))
return result
all_default = set()
for f in default:
all_default.update(get_transitive_features(f))
if "pq-crypto" in all_default:
print("❌ SECURITY VIOLATION: pq-crypto transitively enabled by default!")
sys.exit(1)
print("✅ PQ feature gate check passed")
EOF
# ===========================================================================
# Dependency Security Audit
# ===========================================================================
dependency-audit:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python 3.12
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.3.0
with:
python-version: "3.12"
- uses: dtolnay/rust-toolchain@d0592fe69e35bc8f12e3dbaf9ad2694d976cb8e3 # stable
with:
toolchain: stable
- name: Install audit tools
run: |
pip install --require-hashes -r requirements-ci.lock
cargo install cargo-audit cargo-deny
- name: Python dependency audit (pip-audit)
run: |
pip-audit -r requirements.txt --strict || {
echo "⚠️ pip-audit found vulnerabilities. Review and update dependencies."
exit 1
}
# RUSTSEC-2023-0071: rsa marvin-attack (transitive via yubikey)
# Mitigation: yubikey use is ECDH-only in this repo; no RSA encrypt/decrypt paths.
# Tracking: create issue + re-evaluate once yubikey updates its rsa dependency.
# Review: 2026-05-01
#
# RUSTSEC-2024-0436: unknown pending audit details
# Tracking: create issue + re-evaluate after upstream advisory details resolve.
# Review: 2026-05-01
#
# RUSTSEC-2026-0009: time 0.3.46 (transitive from x509-parser)
# Tracking: create issue + re-evaluate when x509-parser updates time.
# Review: 2026-05-01
- name: Rust dependency audit (cargo-audit)
run: |
# Cargo.lock lives at workspace root; run audit from there so it
# covers both crypto_core and rust_crypto workspace members.
cargo audit --ignore RUSTSEC-2023-0071 --ignore RUSTSEC-2024-0436 --ignore RUSTSEC-2026-0009 || {
echo "⚠️ cargo-audit found vulnerabilities not in exception list."
exit 1
}
# ===========================================================================
# SBOM Generation
# ===========================================================================
sbom:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Python 3.12
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.3.0
with:
python-version: "3.12"
- name: Generate Python SBOM
run: |
pip install --require-hashes -r requirements-ci.lock
cyclonedx-py --format json --output sbom-python.json || \
pip-licenses --format=json > sbom-python-fallback.json
echo "✅ Python SBOM generated"
- uses: dtolnay/rust-toolchain@d0592fe69e35bc8f12e3dbaf9ad2694d976cb8e3 # stable
with:
toolchain: stable
- name: Generate Rust SBOM
run: |
cargo install cargo-cyclonedx || true
cd crypto_core
cargo cyclonedx --format json > ../sbom-rust.json || \
cargo tree --format "{p} {l}" > ../sbom-rust-fallback.txt
cd ..
echo "✅ Rust SBOM generated"
- name: Upload SBOMs
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.0
with:
name: sbom-artifacts
path: |
sbom-*.json
sbom-*.txt
retention-days: 90
# ===========================================================================
# Cargo Deny - Supply Chain Security
# ===========================================================================
cargo-deny:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: dtolnay/rust-toolchain@d0592fe69e35bc8f12e3dbaf9ad2694d976cb8e3 # stable
with:
toolchain: stable
- name: Install cargo-deny
run: cargo install cargo-deny
- name: Run cargo-deny on crypto_core
run: |
cd crypto_core
cargo deny check || {
echo "⚠️ cargo-deny found issues. Review deny.toml and dependencies."
exit 1 # Changed: now fails build (make non-blocking again if tuning)
}
cd ..
- name: Run cargo-deny on rust_crypto
run: |
cd rust_crypto
cargo deny check || {
echo "⚠️ cargo-deny found issues in rust_crypto."
exit 1
}