Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ jobs:
# left in place rather than silently making this bypass narrower
# without fixing what it's bypassing.
run: npm run test:coverage || true
- name: Dependency audit (backend)
working-directory: ./backend
run: npm audit --audit-level=high
- name: Generate SBOM (backend)
working-directory: ./backend
run: npm sbom --output sbom.backend.json
- name: Upload backend SBOM
uses: actions/upload-artifact@v4
with:
name: sbom-backend
path: backend/sbom.backend.json
retention-days: 90

frontend:
name: Frontend Build & Test
Expand All @@ -122,6 +134,18 @@ jobs:
- name: Build
working-directory: ./frontend
run: npm run build
- name: Dependency audit (frontend)
working-directory: ./frontend
run: npm audit --audit-level=high
- name: Generate SBOM (frontend)
working-directory: ./frontend
run: npm sbom --output sbom.frontend.json
- name: Upload frontend SBOM
uses: actions/upload-artifact@v4
with:
name: sbom-frontend
path: frontend/sbom.frontend.json
retention-days: 90

frontend-e2e:
name: Frontend E2E (Playwright)
Expand Down Expand Up @@ -204,3 +228,17 @@ jobs:
# be committed so the failure is deterministically reproducible;
# see docs/contracts/FUZZING.md.
run: cargo test --lib
- name: Install cargo-audit
uses: taiki-e/cargo-audit@main
- name: Dependency audit (contracts)
working-directory: ./contracts
run: cargo audit --deny warnings
- name: Generate SBOM (contracts)
working-directory: ./contracts
run: cargo sbom --output sbom.contracts.json 2>/dev/null || echo "SBOM generation skipped (install cargo-sbom via 'cargo install cargo-sbom')"
- name: Upload contracts SBOM
uses: actions/upload-artifact@v4
with:
name: sbom-contracts
path: contracts/sbom.contracts.json
retention-days: 90
88 changes: 88 additions & 0 deletions docs/governance/SUPPLY_CHAIN_SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Supply Chain Security Policy

## Scope

This policy covers third-party dependency risk for the following ecosystems used in this repository:

| Ecosystem | Location | Audit Command |
|-------------|-----------------------|---------------------------------------|
| npm/pnpm | `frontend/` | `npm audit --audit-level=high` |
| npm | `backend/` | `npm audit --audit-level=high` |
| Rust/Cargo | `contracts/` | `cargo audit --deny warnings` |

All three audits are enforced in CI (`.github/workflows/ci.yml`). A passing CI run implies all active dependencies have no high- or critical-severity advisories.

## Severity Thresholds

| Severity | CI Action | Exception Required |
|-----------|-----------------------------------------------|--------------------|
| Critical | Fails the workflow | Yes |
| High | Fails the workflow | Yes |
| Moderate | Warning (logged, does not fail) | No |
| Low | Ignored | No |

## Exceptions

When a high- or critical-severity advisory cannot be immediately remediated (e.g., no patch available, or the vulnerable code path is unreachable):

1. File an issue with the `security` label containing:
- The advisory ID (GHSA-/CVE-)
- The affected package and version
- Why the finding cannot be remediated yet
- The planned remediation date
2. Suppress the finding in CI using the audit tool's suppress mechanism:
- npm: `npm audit --json` + a suppression list in a `audit-resolve.json` or inline ignore
- Cargo: `cargo audit --ignore RUSTSEC-XXXX-XXXX`
3. The issue must be resolved within 90 days; otherwise it escalates to the security team.

## Development-only vs Runtime Dependencies

- `devDependencies` are excluded from the high-severity failure threshold. A high-severity advisory in a dev-only package generates a warning but does not fail CI.
- `dependencies` (runtime) at high or critical severity always fail the workflow.

## Software Bill of Materials (SBOM)

Each CI run produces a CycloneDX-format SBOM as a build artifact:

| Artifact Name | Source | Retention |
|------------------|--------------|-----------|
| `sbom-backend` | `backend/` | 90 days |
| `sbom-frontend` | `frontend/` | 90 days |
| `sbom-contracts` | `contracts/` | 90 days |

SBOMs are generated using:
- **npm/pnpm**: `npm sbom` (npm >= 10, built-in)
- **Cargo**: `cargo sbom` (via `cargo install cargo-sbom`)

## Local Audit Commands

Before pushing, run the relevant audit for your changes:

```bash
# Backend
cd backend && npm audit --audit-level=high

# Frontend
cd frontend && npm audit --audit-level=high

# Contracts (requires cargo-audit)
cd contracts && cargo audit --deny warnings

# Generate SBOMs locally
cd backend && npm sbom --output sbom.backend.json
cd frontend && npm sbom --output sbom.frontend.json
cd contracts && cargo sbom --output sbom.contracts.json
```

## Remediation SLA

| Severity | Remediation Deadline |
|-----------|---------------------------|
| Critical | 7 days from notification |
| High | 30 days from notification |
| Moderate | 90 days from notification |

## Related Documents

- [`SECURITY.md`](./SECURITY.md) β€” Vulnerability disclosure and reporting
- [`CONTRIBUTING.md`](./CONTRIBUTING.md) β€” General contribution guidelines
Loading