Skip to content

Security Assurance

ForgeOS security is not only a set of rules. It is a set of invariants, tests, CI gates, and evidence artifacts that should prove the rules continue to hold.

What This Covers

The public invariants live in:

security/SECURITY_INVARIANTS.md

The public standards mapping lives in:

security/STANDARDS_CROSSWALK.md

They cover:

  • production auth must not accept dev headers;
  • tenant data must not cross tenant boundaries;
  • Postgres RLS must block handler bugs;
  • commands must stay deterministic and side-effect free except for ctx.emit;
  • queries and liveQueries must be read-only;
  • agent tools must inherit Forge auth, tenant, policy, telemetry, and approval boundaries;
  • secret values must not appear in generated artifacts, telemetry, logs, or reports;
  • webhooks must reject invalid signatures, stale timestamps, tampered bodies, and replayed event ids;
  • releases must be traceable to CI and package evidence.

Security Assurance Workflow

The CI workflow is:

.github/workflows/security-assurance.yml

It runs:

forge generate --check
forge check --json
forge auth check --json
forge secrets check --json
forge auth prove --json
forge secrets prove --json
forge rls test --db postgres --json
forge rls mutate-test --json
forge security prove --db postgres --full --json
npm run security:evidence -- security/evidence/latest/security-proof.json security/evidence/latest
npm run release:evidence -- security/evidence/latest
npm run security:deps -- security/evidence/latest/dependency-audit.json
forge verify --strict --script-timeout-ms 120000
bun test tests/security

The current implementation covers adversarial fixtures for runtime boundaries, runtime and HTTP tenant isolation, JWT/OIDC negative auth paths, value-aware secret redaction, webhook signature/replay checks, agent tool metadata, structural agent checks, deterministic model-level agent probes, standards crosswalks, release evidence, SBOM generation, dependency vulnerability evidence, Postgres RLS tenant isolation, and RLS mutation checks.

forge security prove --json reports an assurance level:

  • structural-only: local checks passed, but the RLS proof did not run against Postgres.
  • postgres-proved: the proof included the Postgres RLS adversarial probes.

By default, forge security prove aggregates structural proofs and invariant metadata. Pass --full or --run-tests to execute the invariant security tests inside the proof command and include the resulting test status in proofs.securityTests.

Alpha Surface Review

Recent alpha surfaces add useful agent and migration workflows, but they also expand the assurance perimeter. Treat these as explicit surfaces in release review:

Surface Primary risk Required control
DeltaDB and agent memory local history can imply stronger provenance than was observed commands must label current-contract fallbacks, redact agent payloads, and mark low-confidence observation sessions as needs-review
CAIR query/action protocol compact mutation plans can hide impact mutation actions must plan before apply, write journals, and stay behind generated guard checks
Studio bridge browser tooling can accidentally cross from inspect to mutate bridge commands must keep explicit subcommands, local binding, and no secret echoing
Brownfield import external manifests can overstate runtime capabilities imports must preserve source metadata, validation diagnostics, and generated contract drift checks
Nuxt template and frontend bindings generated client wiring can drift from runtime entries CI must install the template, run Forge check, run Nuxt typecheck, and probe forge dev --once

For release candidates, include the relevant field report or focused test output alongside normal security evidence when one of these surfaces changed.

Local Security Gate

Run the focused gate locally:

node ./bin/forge.mjs generate --check
node ./bin/forge.mjs check --json
node ./bin/forge.mjs auth check --json
node ./bin/forge.mjs secrets check --json
node ./bin/forge.mjs auth prove --json
node ./bin/forge.mjs secrets prove --json
node ./bin/forge.mjs ai redteam --json
node ./bin/forge.mjs ai redteam --model-level --json
node ./bin/forge.mjs rls test --db postgres --json
node ./bin/forge.mjs rls mutate-test --json
node ./bin/forge.mjs security prove --db postgres --full --json

Run the broader gate before release:

node ./bin/forge.mjs verify --strict --script-timeout-ms 120000
npm run field:test -- --package-managers npm --templates minimal-web,nuxt-web --forge-spec "npm:forgeos@alpha" --install --runtime-probes --json
npm run field:test -- --package-managers npm --templates nuxt-web --forge-spec "npm:forgeos@alpha" --install --runtime-probes --json

Evidence

Security evidence should be generated into:

security/evidence/latest/

Examples:

forge-check.json
auth-check.json
secrets-check.json
rls-test.json
rls-mutation.json
security-proof.json
auth-negative.json
tenant-isolation.json
runtime-boundaries.json
secret-redaction.json
agent-tools.json
webhooks.json
release-supply-chain.json
sbom.cyclonedx.json
dependency-audit.json

Evidence files must not include:

  • secret values;
  • .env contents;
  • database row data from real users;
  • raw prompts when retention is disabled;
  • large telemetry payloads.

Current Gaps

The current assurance layer is intentionally not the final security story. The next layers are:

  1. More runtime tenant isolation scenarios for generated agent auto-tools and liveQuery HTTP/SSE probes.
  2. External review of auth claim mapping, telemetry sinks, webhook recipes, and RLS policy generation.
  3. Broader production field reports on real Postgres deployments and longer-lived apps.

Dependency Vulnerability Evidence

Run:

npm run security:deps

This writes:

security/evidence/latest/dependency-audit.json

The auditor recreates temporary npm installs from the framework package, the create-app wrapper, and both template root/web manifests. Template placeholders are resolved the same way generated apps are resolved, so the evidence reflects a real npm create forgeos-app@alpha consumer path instead of raw template files.

The default threshold is high. Unwaived high or critical issues fail the command. Waivers are explicit and versioned in:

security/dependency-audit-waivers.json

Keep waivers narrow, include a reason, and set an expiration date.