Skip to content

Security hardening pass + security test framework#85

Merged
ndreno merged 2 commits into
mainfrom
security/hardening-and-test-framework
Jun 29, 2026
Merged

Security hardening pass + security test framework#85
ndreno merged 2 commits into
mainfrom
security/hardening-and-test-framework

Conversation

@ndreno

@ndreno ndreno commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Hardening pass from a security review, plus a security testing harness. Everything builds; affected crate test suites and the workspace clippy gate pass locally.

Hardening

  • Control plane: admin bearer token required on all routes except /health and the data-plane WebSocket; fails closed without BARBACANE_CONTROL_ADMIN_TOKEN; CORS restricted to an allowlist (BARBACANE_CONTROL_ALLOWED_ORIGINS).
  • Artifact integrity: Ed25519 signing at compile (BARBACANE_SIGNING_KEY) and verify-on-load against a pinned key (BARBACANE_TRUSTED_PUBKEY), plus per-plugin/spec/route checksum verification before any plugin is instantiated.
  • MCP: sessions are enforced for non-initialize requests.
  • Plugin egress: the WASM host HTTP client blocks loopback/link-local/private/metadata targets and no longer follows redirects (BARBACANE_ALLOW_INTERNAL_EGRESS to override).
  • jwt-auth: real signature verification via the host verify_signature capability (inline JWK); the test-only skip flag is ignored in production builds.
  • Secrets: file:// references confined to BARBACANE_SECRETS_DIR.
  • Misc: fix a fail-open middleware short-circuit; bound Prometheus path-label cardinality on unmatched routes; stop panicking on hostile x-request-id/traceparent; correct capability map (cache/rate_limit/http_stream); non-root standalone image; correct AGPL image labels; add deny.toml license/bans/sources gates.

Security test framework

  • Adversarial integration suite under crates/barbacane-test/tests/security/.
  • cargo-fuzz targets under fuzz/ (spec parser, artifact loader, JSON-RPC, validator).
  • Runbook: docs/contributing/security-testing.md; make security-test / make fuzz-build.

Config (operators)

Var Purpose
BARBACANE_CONTROL_ADMIN_TOKEN required to start the control plane
BARBACANE_CONTROL_ALLOWED_ORIGINS CORS allowlist (comma-separated)
BARBACANE_SIGNING_KEY PKCS#8 Ed25519 key to sign artifacts at compile
BARBACANE_TRUSTED_PUBKEY hex Ed25519 pubkey; when set, signature verification is required on load
BARBACANE_SECRETS_DIR base dir for file:// secret references
BARBACANE_ALLOW_INTERNAL_EGRESS opt out of the plugin SSRF guard

Follow-ups (see ROADMAP "Security hardening")

  • Complete the per-plugin default-deny capability linker (needs the official plugin.toml capability-dialect migration + the wasm/Docker integration run).
  • Ingress timeouts/limits, per-plugin secret scoping, SDK hardening helpers, CI supply-chain gates, control-plane non-root.

Detailed findings are tracked privately.

ndreno added 2 commits June 29, 2026 23:23
Closes the critical findings from the security review and adds a
security testing harness. All changes build; affected crate test
suites and the workspace clippy gate pass.

Critical fixes:
- control-plane: require an admin bearer token on all routes except
  /health and the data-plane WebSocket; fail closed without
  BARBACANE_CONTROL_ADMIN_TOKEN; tighten CORS to an allowlist.
- artifact: Ed25519 sign-on-compile (BARBACANE_SIGNING_KEY) and
  verify-on-load against a pinned key (BARBACANE_TRUSTED_PUBKEY),
  plus per-plugin/spec/route checksum verification on load.
- mcp: reject non-initialize requests without a valid session
  (no more header-omission bypass).
- wasm http client: SSRF guard rejecting loopback/link-local/private/
  metadata targets; redirects disabled (BARBACANE_ALLOW_INTERNAL_EGRESS
  to override).
- jwt-auth: real signature verification via host verify_signature
  (inline JWK); skip flag ignored in production builds.
- wasm secrets: confine file:// references to BARBACANE_SECRETS_DIR.

Hardening / quick wins:
- wasm chain: fix fail-open middleware short-circuit downgrade.
- data plane: bound Prometheus path-label cardinality on unmatched
  routes; stop panicking on hostile x-request-id/traceparent.
- wasm capability map: add cache, rate_limit, http_stream.
- containers: non-root standalone image; correct AGPL license labels.
- deny.toml: add licenses/bans/sources gates.

Security test framework:
- adversarial integration suite (crates/barbacane-test/tests/security/)
- cargo-fuzz targets (fuzz/) for parser/loader/jsonrpc/validator
- docs/contributing/security-testing.md

Deferred (tracked in ROADMAP): full per-plugin capability-enforcement
linker (needs plugin-manifest migration + wasm integration run).
Completes capability enforcement and fixes the CI failures on the
hardening branch.

WA-1 — capability enforcement:
- Migrate all 33 official plugin.toml manifests to the canonical
  `[capabilities] host_functions = [...]` dialect, with the minimal
  capability set verified against each plugin's real wasm imports.
- Correct the capability->imports map (time aliases under clock_now,
  outbound-body fns under http_call, broker read-result under
  kafka/nats) and always-allow the core request-body ABI.
- Carry per-plugin host_functions into the .bca manifest and run
  validate_imports on load: a plugin importing a host function outside
  its declared capabilities is a hard load failure (default-deny).
- Gate enforcement on a new `capabilities_enforced` manifest flag, set
  true only when capabilities are authoritative (compiled from
  plugin.toml). Control-plane-compiled artifacts (registry does not yet
  persist capabilities) load without enforcement; tracked as follow-up.
- Add validate.rs unit tests proving undeclared imports are rejected and
  declared/core imports are allowed.

CI fixes:
- Reformat (cargo fmt) the hardening changes.
- Bump anyhow 1.0.102 -> 1.0.103 (RUSTSEC-2026-0190; new advisory, not
  introduced by this branch).
- Revert deny.toml to advisories-only (the license/bans/sources gates
  move to the public CI-hardening issue; they tripped the audit job).
- Fix 4 stream_raw tests that regressed under the SSRF guard, and make
  the SSRF allow-flag per-client config (HttpClientConfig.
  allow_internal_egress) instead of a global, removing the test race.

Docs:
- docs/reference/configuration.md: env vars + breaking-by-default notes.
- CHANGELOG Unreleased entry; ROADMAP updates.
@ndreno ndreno merged commit 68736e0 into main Jun 29, 2026
12 checks passed
@ndreno ndreno deleted the security/hardening-and-test-framework branch June 29, 2026 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant