Trust & security

Threat model

STRIDE walk against every shipped primitive · Last updated: 2026-05-08

fastpace — STRIDE threat model

Public artifact answering "what could go wrong with fastpace itself." Walks each STRIDE category against each shipped primitive. Updated per-release; cross-linked from /trust. Last updated: 2026-05-08 · current version 0.34.0

Scope

This is a threat model of fastpace as a system the customer installs and operates — not of the AI runtimes fastpace mediates. The runtime threat model (Bedrock, Azure OpenAI, Vertex, Anthropic direct) is the customer's responsibility, governed by their direct contract with that provider. We explicitly do not assume responsibility for those data paths and the /trust page documents that boundary.

In scope:

Out of scope:


Trust boundaries

Three trust boundaries delineate the system:

  1. Developer machine ↔ AI runtime. Crossed every time an agent calls the runtime API. fastpace's prompt-redactor (F0.5) sanitizes outbound data; runtime guard (F1.11) enforces approved-runtime policy.
  2. Repo ↔ org dashboard. Crossed when the org dashboard ingests a repo's signed summary. Each summary is signed with the install's F0.1 identity; the dashboard verifies before persisting.
  3. Org ↔ external policy/identity authority. Crossed when (a) the org admin publishes a signed policy bundle (F2.11) for repos to pull, and (b) the SAML IdP issues an envelope (F1.14) for fastpace to verify. Each direction is signed with the appropriate authority's private key; fastpace verifies against a configured public key.

STRIDE walkthrough

S — Spoofing identity

What could go wrong: An attacker passes off non-authentic content as having come from a legitimate party — a fake audit entry, a fake AI-BOM, a fake policy bundle, a fake SAML profile.

PrimitiveMitigation
F0.1 cryptographic identityEvery install has an Ed25519 keypair generated locally. The private key never leaves the machine. The fingerprint is stable; identity rotation produces a clean break with the prior key archived.
F0.2 hash-chained signed audit logEvery entry is signed with the install's F0.1 private key. Verifying a chain requires the matching public key; rotated/archived keys are tried in order.
F2.4 AI-BOMEach BOM is signed by F0.1 and identifies the install_id + fingerprint of the signer.
F1.12 sanctioned-install attestation + Sigstore bundleCo-signed by F0.1 (proves the install agreed) and the org private key (proves the org issued the license). Sigstore bundle wraps the signature in a verifier-friendly envelope.
F2.11 policy bundleSigned by the org admin's F0.1 key; verifyBundle rejects any bundle whose signature does not match the configured trusted issuer.
F1.14 SAML envelope verifierVerifies the IdP signature over the canonical JSON profile. Issuer + audience checks reject envelopes signed by an authentic-but-wrong-tenant IdP.
F2.6 trusted data tapsEach tap is signed by the install identity at registration; listTaps drops invalid signatures from the active set.

Residual risk. If the developer's machine is compromised at a level that exposes the F0.1 private key, the attacker can sign anything. The key file is stored at ~/.fastpace/identity/ with 0o600 permissions and is never transmitted; this is a host-security problem.

T — Tampering with data

What could go wrong: An attacker (or a careless edit) modifies an artifact after the fact and presents the modified version as authentic.

PrimitiveMitigation
F0.2 hash chainEach entry's entry_hash is sha256(canonical_json(body)); the next entry binds via prev_hash. Editing any entry breaks every later entry's chain. fastpace verify walks and reports the first break.
F1.1 run manifestsEach manifest is signed; verifyManifest recomputes entry_hash and rejects mismatches.
F2.4 AI-BOMSame: signed body.
F2.3 provenance trailersCommit messages carry Fp-Run-Manifest: etc. Tampering with the commit message breaks the trailer-to-manifest binding; verify-provenance reports it.
F2.2 explanation bundlesSixth proof layer in the verify-provenance chain: explanation digest links back to the manifest.
F2.6 trusted data tapsTampered entries fail signature verification and are dropped from listTaps.
F2.5 control monitorEach drift report is signed; controlMonitor.listReports surfaces signature presence.
F2.9 audit gateEach gate report is signed.
F2.11 policy bundleTampering anywhere in the bundle invalidates the signature; the local pre-bundle backup at fastpace/policy/local-pre-bundle.json lets apply be reverted cleanly.
F0.4 agent identity manifestsFrontmatter is part of the manifest; the agent-scope-guard hook re-reads on every call so swapping a manifest at rest immediately changes the operational scope.

Residual risk. A physically-present attacker with write access to the repo can rewrite both the chain and the matching signatures (the key is on the same machine). Defense-in-depth: replication of the audit log to immutable storage (F3.11 Tier-3 backlog) closes this.

R — Repudiation

What could go wrong: A user denies having performed an action that fastpace recorded — "I never granted that exception."

PrimitiveMitigation
F0.1 identityEvery signed artifact is bound to a specific install_id + fingerprint. The signing machine is identified.
F0.2 audit chainAppend-only with hash linkage. Repudiating a recorded action requires breaking the chain (which is detectable).
F1.8 exception workflowEvery exception request and revoke is signed into the chain. Exceptions are themselves audit records.
F2.3 provenance trailersEvery AI-authored commit carries trailers binding the commit to a specific run manifest, agent, and prompt hash.
F1.14 RBAC + SAMLEvery privileged action goes through the role-permission check; the action's actor is captured in the audit entry.
F2.14 coach feedback loopEvery rating is signed and timestamped; rating-token includes the original block_id so feedback cannot be re-attributed to a different block.

Residual risk. Same as Tampering: if the F0.1 key is compromised, attribution is unreliable. This is the host-security problem.

I — Information disclosure

What could go wrong: A secret, PII, or sensitive code snippet leaks out of the developer machine through a fastpace-mediated channel.

PrimitiveMitigation
F0.5 prompt redactorUserPromptSubmit hook strips secrets (regex patterns: AWS keys, GitHub PATs, JWTs, generic API tokens) and PII (email, phone) before the prompt reaches the runtime. Custom patterns extend the built-in set.
F1.10 sensitivity-tagged contextFrontmatter on context files declares sensitivity (public, internal, confidential, restricted). Hooks can refuse to include restricted content in prompts that target a runtime not on the approved list.
F2.6 trusted data tapsAllow-list of source patterns permitted to feed prompts. A source matching no active tap is blocked + logged.
F1.11 approved-runtime registryCalls to non-approved runtimes are blocked at the runtime-guard hook. Limits the blast radius of an exfil attempt to the approved runtime's data path.
F1.7 MCP scope mediationMCP server calls are filtered by allowed_servers + allowed_actions. A compromised agent cannot call mcpgithubmerge_pull_request if the policy says [read, comment] only.
F1.10 sensitivity tagging in auditsaudit.log entries record the sensitivity tag of any context passed in; auditors can enumerate every cross-tier flow.
F0.5 redaction logsWhat was redacted (kind + count) is logged, but the redacted content itself is NEVER persisted.
Identity key storageF0.1 private key is stored at ~/.fastpace/identity/private.pem with 0o600 permissions. Never committed, never transmitted. The .gitignore ships a hard-block on .fastpace/identity/.

Residual risk. Redaction is regex-based and can miss novel secret formats. The prompt-redactor.js hook accepts custom patterns and the F2.13 SAST hook covers a different layer (post-write code). Future work: a learned redactor that also flags potentially-sensitive prose.

D — Denial of service

What could go wrong: A hook or guard fires on every AI call and slows the developer to a crawl, or a misconfigured policy blocks every action.

PrimitiveMitigation
Hook timeout conventionEvery shipped hook reads stdin, performs at most one synchronous file system check, and exits in <50ms on the happy path. The audit-logger, agent-scope-guard, prompt-redactor, and runtime-guard hooks specifically exit on first matching deny rule.
F1.3 circuit breakerRefuses to fire below 3 sample sessions to avoid false positives during onboarding. The fleet-wide baseline (Sprint 15) lets a brand-new install borrow fleet baselines instead of failing open until it has its own samples.
F1.8 exception workflow + F1.9 coachEvery block surfaces the exact fastpace exception request command. Developers always have a path forward — they don't have to disable a hook to unblock themselves.
F2.13 SAST/lint requiredblock_on is configurable per repo (default high); require_all_tools defaults to false so a missing tool doesn't fail the push. The hook only fires on git push (or explicit opt-in patterns), not on every Bash call.
F2.9 audit gate --soft modeOperators can roll out the gate in soft mode that records reports without blocking; only flip to hard mode after the report is consistently green.
F2.11 policy bundle apply backupApply writes a local-pre-bundle.json snapshot of the prior config; one command reverts.
Worst-case bypassSetting FASTPACE_NO_HOOKS=1 is documented as the developer-side bypass. The bypass itself is logged to the audit chain (next-sprint hardening).

Residual risk. A hook with a real bug could fail closed. Mitigation: each hook ships try/catch around its main path with allow() as the default failure mode (fail-open is the right choice when the alternative is the developer being unable to work; the audit chain still reflects the failure for post-hoc review). High-risk hooks (runtime-guard, agent-scope-guard) fail closed by design.

E — Elevation of privilege

What could go wrong: A non-privileged actor performs an action that should require a privileged role.

PrimitiveMitigation
F0.4 agent identity + scopeEvery agent declares allowed_tools, allowed_paths, max_files, etc., in frontmatter. The agent-scope-guard hook enforces on every tool call.
F1.11 approved runtimesCalls to a non-approved runtime are blocked even if the agent's scope would otherwise allow them.
F1.7 MCP scope mediationPer-server allowed_actions blocks privileged MCP actions (merge_pull_request, delete_repo) even when the server itself is allow-listed.
F1.6 least-privilege bootstrapfastpace grant is the only path to expand an agent's scope. Each grant is signed into the audit chain with reason + reviewer + TTL.
F1.8 risk-tier exceptionsCritical / irreversible / exfil_eligible tiers require a named reviewer, not self-approval. The exception module enforces this at the API layer.
F1.14 RBAC rolesFour roles (dev / team_lead / security / admin); each permission is checked at the org-dashboard endpoint level.
F1.14 SAML envelope verifierReal signature + window + audience check. An attacker cannot forge a SAML envelope without the IdP private key.
F1.12 sanctioned-install attestationDistinguishes sanctioned (org-licensed) installs from personal npm i -g installs. The org-dashboard can refuse to ingest summaries from non-sanctioned installs (gate is policy-defined).

Residual risk. A user with admin role plus repo write access can do anything. Mitigation: every admin action is in the audit chain, and the F2.7 red-team harness includes scenarios for admin-account abuse.


Cross-cutting design choices

These come up repeatedly in the per-category analysis above.


Wave-4 (v0.36.0) — security-relevant additions

Three commands shipped in v0.36.0 touch the security perimeter and are worth calling out explicitly.

Four gateway-dependent Wave-4 commands (model-route, key-vault, local-model, token-budget) ship their config surfaces only. Real call-time enforcement requires the model gateway, which remains parked. Until then, these commands are advisory and a host-compromised attacker can edit the config files freely — the policies serve as documentation and warning surfaces, not enforcement. Be explicit with customers that buying Platform today does not buy gateway-level enforcement.

The platform_metrics rollup added to the install→org-dashboard shipper carries: bus-factor scores, AI-share %, vendor-HHI, coverage-gap counts, token-budget %, redteam findings counts, drift configured-yes/no. No prompt text, no manifest payloads, no developer-identifying data — only counts and percentages. Same posture as the existing roi, maturity, and audit_coverage payloads on the same shipper.


v0.40.0 (Wave 5c.A) — ship-layer additions

The audit chain now carries a new event type deploy.recorded written by fastpace deploy record. Schema-extends the chain; fastpace verify walks the new event type identically to existing hook.* entries. No new trust boundary introduced — the deploy event lives entirely on the customer machine until the existing audit-replication shipper sends it onward. Same posture as roi, maturity, platform_metrics payloads on the same shipper.

Provenance trailers can now optionally carry X-fastpace-Deploy: <tag>. Threat-model implication: the trailer is set by the customer's own commit-author tooling (post-tag hook), not by fastpace; an attacker with commit-author access can spoof it. Mitigation: trailers are verifiable against the corresponding signed deploy attestation in fastpace/deploys/<id>.json and the audit-chain deploy.recorded entry. If the trailer claims a deploy that no attestation backs, the claim fails verification — soft-fail with a clear "no matching attestation" signal in fastpace verify.


v0.41.0 (Wave 5c.B) — metrics-source connector trust boundary (forecast)

When the metrics-source connector ships in v0.41.0, a new trust boundary opens: fastpace → external observability vendor (Datadog / Prometheus / Sentry / CloudWatch / New Relic / Splunk). Per the original threat model's design rule — every new trust boundary gets a STRIDE walkthrough — here it is.

STRIDE — fastpace ↔ external metrics source

ThreatRiskMitigation
Spoofing. The connector is tricked into hitting a fake vendor endpoint (DNS poisoning, MITM, vendor-look-alike domain).Attacker harvests the customer's metrics-API token + receives queries that reveal which services/metrics the customer monitors.TLS verification required on all vendor calls (no --insecure flag, no certificate pinning bypass). Per-provider hostname allowlist baked into the adapter (e.g. Datadog adapter only talks to api.datadoghq.{com,eu}).
Tampering. Vendor (or someone on-path between fastpace and the vendor) returns falsified metrics.A canary deploy looks healthy when it actually isn't, or vice-versa — leading to bad rollback decisions.(a) Metrics are advisory inputs to a human decision (fastpace rollback assess is a recommendation engine, not an actuator — never auto-rolls-back). (b) Caching writes results to fastpace/metrics-cache/<provider>/<hash>.json with the query hash; cache poisoning requires file-system write access on the dev's machine, which means the threat is already past the trust boundary. (c) Multi-source cross-check: customers can declare two providers (e.g. Datadog + Sentry) and the verify step warns when they disagree.
Repudiation. Vendor denies sending data, or fastpace denies sending a query.Customer can't trace "why did fastpace recommend rollback at 14:23?"Every query + response gets logged to fastpace/audit.log as a new event type metrics-source.queried (signed, chained). The query hash + response hash + provider name + timestamp are all in the log; vendor logs are out-of-scope but the customer-side record is forensic-grade.
Information disclosure. Fastpace sends customer's prompt text or commit content to the vendor.Customer's source-code intent leaks into the metrics provider's logs.fastpace never sends prompt text or source code in metrics queries. Queries are pre-canonicalised against the vendor's query DSL (e.g. PromQL, Datadog metrics-query) and verified to contain only: service names, metric names, time ranges, threshold values. The connector enforces this at the adapter layer — any query string containing identifiers outside an allowlist of metric/service/env names is rejected before transmission.
Denial of service. Vendor is rate-limiting or down.fastpace deploy verify blocks indefinitely waiting on response; CI gate times out.Configurable per-query timeout (default 30s) + async-with-polling fallback for long windows + cached results with TTL (default 5 min). If all three fail, verification reports metrics-source: unavailable rather than hanging — and the rollback-assess step downgrades to "human judgment required, no metrics signal."
Elevation of privilege. Compromised metrics-API token grants attacker access beyond just reading metrics.Customer's metrics-API token is exposed via fastpace; attacker uses it to write metrics, modify alerts, or pivot inside the vendor account.(a) Tokens are stored env-var-only via fastpace key-vault (never on disk in fastpace's tree). (b) The connector's request library rejects all non-GET HTTP methods (read-only by construction) so a token that has write-scope can't be used to write through fastpace. (c) Customer must mint a read-only API token in the vendor dashboard and grant only the metric scopes the connector needs — documented in the per-adapter setup guide.

Threats out of scope (deliberately)

Audit-trail additions


What changes in the next-sprint horizon

These are documented in future-work.md and will update this threat model as they ship:


Reporting

To report a security issue or a missing item in this threat model: security@fastpace.dev. Acknowledgement within 48 hours; initial triage within 5 business days.