Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
138 lines
7.9 KiB
Markdown
138 lines
7.9 KiB
Markdown
---
|
|
summary: Machine-checked security models for OpenClaw's highest-risk paths.
|
|
title: Formal verification (security models)
|
|
read_when:
|
|
- Reviewing formal security model guarantees or limits
|
|
- Reproducing or updating TLA+/TLC security model checks
|
|
permalink: /security/formal-verification/
|
|
---
|
|
|
|
OpenClaw's formal security models (TLA+/TLC today) give a machine-checked argument that specific highest-risk paths — authorization, session isolation, tool gating, and misconfiguration safety — enforce their intended policy, under explicit stated assumptions.
|
|
|
|
> Note: some older links may refer to the previous project name.
|
|
|
|
## What this is
|
|
|
|
An executable, attacker-driven security regression suite:
|
|
|
|
- Each claim has a runnable model-check over a finite state space.
|
|
- Many claims have a paired negative model that produces a counterexample trace for a realistic bug class.
|
|
|
|
This is **not** a proof that OpenClaw is secure in all respects, and it does not verify the full TypeScript implementation.
|
|
|
|
## Where the models live
|
|
|
|
Models are maintained in a separate repo: [vignesh07/openclaw-formal-models](https://github.com/vignesh07/openclaw-formal-models).
|
|
|
|
<Note>
|
|
That repository is currently unreachable (GitHub returns "Repository not found" as of this writing). If it is still broken for you, ask in the OpenClaw maintainer channels for the current location before assuming the models were removed.
|
|
</Note>
|
|
|
|
## Caveats
|
|
|
|
- These are models, not the full TypeScript implementation — drift between model and code is possible.
|
|
- Results are bounded by the state space TLC explores. Green does not imply security beyond the modeled assumptions and bounds.
|
|
- Some claims rely on explicit environment assumptions (for example, correct deployment and correct configuration inputs).
|
|
|
|
## Reproducing results
|
|
|
|
Clone the models repo and run TLC:
|
|
|
|
```bash
|
|
git clone https://github.com/vignesh07/openclaw-formal-models
|
|
cd openclaw-formal-models
|
|
|
|
# Java 11+ required (TLC runs on the JVM).
|
|
# The repo vendors a pinned tla2tools.jar and provides bin/tlc plus Make targets.
|
|
|
|
make <target>
|
|
```
|
|
|
|
There is no CI integration back into this repo yet; a future iteration could add CI-run models with public artifacts (counterexample traces, run logs) or a hosted "run this model" workflow for small bounded checks.
|
|
|
|
## Claims and targets
|
|
|
|
### Gateway exposure and open gateway misconfiguration
|
|
|
|
**Claim:** binding beyond loopback without auth can make remote compromise possible and increases exposure; a token/password blocks unauthenticated attackers, per the model's assumptions.
|
|
|
|
| Result | Targets |
|
|
| -------------- | ---------------------------------------------------------------- |
|
|
| Green | `make gateway-exposure-v2`, `make gateway-exposure-v2-protected` |
|
|
| Red (expected) | `make gateway-exposure-v2-negative` |
|
|
|
|
See also `docs/gateway-exposure-matrix.md` in the models repo.
|
|
|
|
### Node exec pipeline (highest-risk capability)
|
|
|
|
**Claim:** `exec host=node` requires (a) a node command allowlist plus declared commands and (b) live approval when configured; approvals are tokenized to prevent replay, in the model.
|
|
|
|
| Result | Targets |
|
|
| -------------- | --------------------------------------------------------------- |
|
|
| Green | `make nodes-pipeline`, `make approvals-token` |
|
|
| Red (expected) | `make nodes-pipeline-negative`, `make approvals-token-negative` |
|
|
|
|
### Pairing store (DM gating)
|
|
|
|
**Claim:** pairing requests respect TTL and pending-request caps.
|
|
|
|
| Result | Targets |
|
|
| -------------- | ---------------------------------------------------- |
|
|
| Green | `make pairing`, `make pairing-cap` |
|
|
| Red (expected) | `make pairing-negative`, `make pairing-cap-negative` |
|
|
|
|
### Ingress gating (mentions and control-command bypass)
|
|
|
|
**Claim:** in group contexts requiring mention, an unauthorized control command cannot bypass mention gating.
|
|
|
|
| Result | Targets |
|
|
| -------------- | ------------------------------ |
|
|
| Green | `make ingress-gating` |
|
|
| Red (expected) | `make ingress-gating-negative` |
|
|
|
|
### Routing and session-key isolation
|
|
|
|
**Claim:** DMs from distinct peers do not collapse into the same session unless explicitly linked or configured.
|
|
|
|
| Result | Targets |
|
|
| -------------- | --------------------------------- |
|
|
| Green | `make routing-isolation` |
|
|
| Red (expected) | `make routing-isolation-negative` |
|
|
|
|
## v1++ models: concurrency, retries, trace correctness
|
|
|
|
Follow-on models that tighten fidelity around real-world failure modes: non-atomic updates, retries, and message fan-out.
|
|
|
|
### Pairing store concurrency and idempotency
|
|
|
|
**Claim:** the pairing store enforces `MaxPending` and idempotency even under interleavings — check-then-write must be atomic/locked, and refresh must not create duplicates. Concretely: concurrent requests cannot exceed `MaxPending` for a channel, and repeated requests/refreshes for the same `(channel, sender)` do not create duplicate live pending rows.
|
|
|
|
| Result | Targets |
|
|
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| Green | `make pairing-race` (atomic/locked cap check), `make pairing-idempotency`, `make pairing-refresh`, `make pairing-refresh-race` |
|
|
| Red (expected) | `make pairing-race-negative` (non-atomic begin/commit cap race), `make pairing-idempotency-negative`, `make pairing-refresh-negative`, `make pairing-refresh-race-negative` |
|
|
|
|
### Ingress trace correlation and idempotency
|
|
|
|
**Claim:** ingestion preserves trace correlation across fan-out and is idempotent under provider retries. When one external event becomes multiple internal messages, every part keeps the same trace/event identity; retries do not double-process; if provider event IDs are missing, dedupe falls back to a safe key (for example trace ID) to avoid dropping distinct events.
|
|
|
|
| Result | Targets |
|
|
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| Green | `make ingress-trace`, `make ingress-trace2`, `make ingress-idempotency`, `make ingress-dedupe-fallback` |
|
|
| Red (expected) | `make ingress-trace-negative`, `make ingress-trace2-negative`, `make ingress-idempotency-negative`, `make ingress-dedupe-fallback-negative` |
|
|
|
|
### Routing dmScope precedence and identityLinks
|
|
|
|
**Claim:** routing keeps DM sessions isolated by default and only collapses sessions when explicitly configured, via channel precedence and identity links. Channel-specific `dmScope` overrides win over global defaults; `identityLinks` collapse sessions only within explicit linked groups, not across unrelated peers.
|
|
|
|
| Result | Targets |
|
|
| -------------- | ------------------------------------------------------------------------- |
|
|
| Green | `make routing-precedence`, `make routing-identitylinks` |
|
|
| Red (expected) | `make routing-precedence-negative`, `make routing-identitylinks-negative` |
|
|
|
|
## Related
|
|
|
|
- [Threat model](/security/THREAT-MODEL-ATLAS)
|
|
- [Contributing to the threat model](/security/CONTRIBUTING-THREAT-MODEL)
|
|
- [Incident response](/security/incident-response)
|