Releases: gl0di/clawseccheck
ClawSecCheck v1.8.2
Self-hardening + bilingual directory metadata. A property-based test for the secret
redactor uncovered (and fixed) a redaction idempotency bug, a new CI gate locks in the
zero-false-positive law, and the skill manifest now carries explicit English and Hebrew
directory metadata. No new checks, no behavior change to the audit itself.
Fixed
logsafe.redact()idempotency. A secondredact()pass over an already-masked
key= <redacted>pair collapsed the whole match to a bare<redacted>, dropping the key
name (the colon/equals secret pattern re-matched the marker). A value that is already
<redacted>is now left untouched. No secret was ever leaked β only the documented
idempotency contract was broken.
Added
- False-positive corpus CI gate (
tests/test_fp_corpus.py). Operationalizes the
zero-false-positive-FAIL law: every clean fixture home (home_safe+fixtures/clean_*)
is audited and asserted to yield zeroFAILfindings; new clean fixtures auto-enroll by
naming convention, with a guard against a vacuous (empty-corpus) pass. - Property-based tests for
logsafe.redact()(tests/test_logsafe_property.py).
Randomized secret payloads in randomized surrounding text (200 iterations/property) prove
no secret value ever survives redaction and thatredact()never raises on arbitrary input. - Bilingual directory metadata in
SKILL.md. Explicit English and Hebrewdisplay_name/
display_descriptionplustags, and alicense: MITfield, for catalog listings. A Hebrew
companion manifestSKILL_HE.mdships for the Israeli skills directory; English remains the
canonical manifest.
Changed
- Repository now publishes only product docs. Process and research notes were moved out of
the published tree; the public repo keeps README, SKILL.md/SKILL_HE.md, CHANGELOG,
SECURITY/SECURITY_MODEL, and docs/THREAT_COVERAGE.md.
ClawSecCheck v1.8.1
Hebrew evidence localization fix + a CI guard so it can't regress. Eight FAIL/WARN checks
rendered an English detail line in the --lang he report because their evidence prose had no
matching DETAIL_RULES entry β the recurring "forgot the he rule for a new check" gap (it had
previously surfaced at C5 β B45 β B47). Probing every fixture home found the gap was still open for
B9, B26, B30, B32 (WARN + FAIL variants), B38, B39, and B41.
Fixed
--lang heevidence leaks (B9, B26, B30, B32, B38, B39, B41). Added HebrewDETAIL_RULES
for every leakingdetailvariant ini18n.py. Interpolated tokens (counts, channel lists,
bind/auth values, provider lists, re-enabled control-plane tools) are preserved verbatim via
capture groups; only the prose is translated. English output is byte-identical (unchanged).
Added
tests/test_i18n_completeness.pyβ i18n-completeness CI guard. Audits every fixture home and
fails CI if any FAIL/WARN finding'sdetailrenders fully in English undertp(detail, "he").
Permanently closes the recurring localization gap at commit time. Deterministic and offline; the
whole-detail unit has no false-positive risk from Latin config identifiers. (Hebrew titles
were already guarded bytest_i18n.py.)
Notes
- No new checks, no schema changes, no scoring changes β output-localization fix only. The audit
still only checks and guides; it never applies fixes or changes your config.
ClawSecCheck v1.8.0
B48 β dangerous break-glass overrides. Mining the real openclaw config schema (2026.6.9) for
dangerously* / allowUnsafe* toggles found ~20 such flags but only 3 were checked. The new B48
closes that coverage gap with a grounded registry β every path was confirmed accepted by openclaw config validate (so they are real, not fabricated), and each is documented "keep disabled."
Added
- B48 β dangerous break-glass overrides enabled (scored). FAIL when a sandbox-escape
(agents[.defaults|.list[]].sandbox.docker.dangerouslyAllow{ContainerNamespaceJoin,ExternalBindSources, ReservedContainerTargets}) or control-plane auth-bypass (gateway.controlUi.dangerouslyDisableDeviceAuth)
flag is active; WARN for the rest βgateway.controlUi.{dangerouslyAllowHostHeaderOriginFallback, allowExternalEmbedUrls},gateway.allowRealIpFallback,gateway.nodes.allowCommands,
channels.<x>.{dangerouslyDisableSignatureValidation,dangerouslyAllowInheritedWebhookPath, network.dangerouslyAllowPrivateNetwork},hooks[.gmail|.mappings[]].allowUnsafeExternalContent,
plugins.entries.<x>.config.allowPrivateNetwork. Absent/false = clean PASS β verified zero
false positives on the real stock out-of-box config and on the fixture corpus. - Mapped to OWASP LLM01/LLM06 and the ASI sandboxing/RCE class (
docs/THREAT_COVERAGE.md).
Notes
- Grounded the new check the dogfood way: set each flag via the real
openclawbinary (the schema
validated the path) and confirmed B48 FAIL/WARN on the live config; the stock default stays PASS. - B48 deliberately does not re-cover flags owned by dedicated checks (
dangerouslyAllowNameMatchingβB30,
browser.ssrfPolicy.dangerouslyAllowPrivateNetworkβB38).
ClawSecCheck v1.7.1
Out-of-the-box dogfood fixes. Stood up a real stock openclaw@2026.6.9 and audited its default
config as a first-time user would. The audit itself was clean (grade A, zero false-positive FAILs
on the stock config; sparse-config keys correctly report UNKNOWN), but the naive-user view surfaced two
real defects, now fixed. A field-path cross-check against the live openclaw config schema confirmed
the rest of the "not in current schema" reads are intentional legacy/alt-shape fallbacks (like the
existing mcpServers), not fabrications β left as-is.
Fixed
- C4 no longer asserts an ungrounded CVE or false "outdated" warning.
check_versionused to WARN
on any recorded version and nameCVE-2026-25253β a CVE absent from the grounded_KNOWN_ADVISORIES
(B33), applied even to the current latest release. It is now a neutral PASS update-hygiene advisory;
all version-vulnerability claims are deferred to the grounded B33 gate (Β§4: don't invent CVEs; Β§5:
no spurious warning on a current install). The Hebrew rule was updated to match. - Next-action / fix hints now use
clawseccheck, notaudit.py. A first-time skill/CLI user has the
clawseccheckcommand; the guidance hints (--prompts/--monitor/--badge/β¦) and the B16 fix text
referenced a bareaudit.pythat doesn't resolve for them.
ClawSecCheck v1.7.0
Paste-ready remediation (--fix). The exact fix commands were already in each finding's prose;
now they're extracted into a copy-paste block. ClawSecCheck stays read-only β --fix only
prints remediation; it never applies anything (the name promises a check). Config fixes are given
as set <dotted-path> β <value> guidance so you edit your own openclaw.json, never a
paste-over JSON blob that could clobber neighbouring keys.
Added
--fixview β prints paste-ready remediation for current FAIL/WARN findings: exact shell
commands (allowlisted verbs only βchmod/openclaw, no destructive or network commands) and
config path+value guidance. Header states plainly that ClawSecCheck does not apply them.catalog.REMEDIATION+remediation_for(id)β single source of truth, authored only for
checks with a safe, deterministic, grounded fix (config dotted paths verified against the real
schema, Β§4). Checks needing manual review keep their prosefix.--jsonexposes"remediation": {commands, config}per finding; SARIF results carry a
fixesarray (description-only β noartifactChanges, since nothing is auto-edited).
Notes
- Additive only β no verdict, score, or check behaviour changed; grades unchanged on the fixture
corpus. A safety test enforces the command allowlist (norm/curl/sudo/pipes/etc.). - Workspace-specific paths use documented
<placeholder>forms rather than auto-substituting a
path guessed from evidence (neverchmodthe wrong thing, Β§5). - Out of scope (deliberately): an auto-apply
--apply(would need to be opt-in and
confirmation-gated, Β§2) and a paste-over JSON patch (clobber risk).
ClawSecCheck v1.6.0
OWASP framework mapping. Each check is now mapped to the OWASP Top 10 for LLM Applications
(2025) category it addresses on the agent surface, and the checks are mapped (by threat name) to the
agent-specific OWASP Agentic Security Initiative (ASI) classes. Pure additive metadata β no
verdict, score, or check behaviour changed. Grounded against genai.owasp.org (the 2025 list reordered
vs 2023, so the codes were verified, not assumed).
Added
catalog.OWASP_MAP+owasp_for(id)β single source of truth mapping each check to its
OWASP-LLM-2025 code(s);catalog.OWASP_LLM_2025holds the ten canonical codes/titles.--jsonexposes"owasp": [...]per finding (empty list for checks with no clean LLM-Top-10
analog β host-watch, logging, SSRF, backups β which are covered by the ASI classes instead).docs/THREAT_COVERAGE.mdgains a Framework mapping section: the LLM-Top-10 table (the whole
multi-agent arc B45/B46/B47 lands under LLM06 Excessive Agency) and the ASI threat-class table
(tool misuse, multi-agent identity/privilege abuse, inter-agent communication, cascading
blast-radius), with grounded source links.
Notes
- Honest non-coverage is stated, not stretched: LLM08 (vector/embedding) and LLM09
(misinformation) live in the model/RAG layer with no agent-config surface, so nothing maps to them. - Borrowed the taxonomy credibility of an OWASP-web reviewer skill without its method β ClawSecCheck
stays deterministic, local, zero-token; it maps OWASP onto the agent, the surface app-code
reviewers don't audit.
ClawSecCheck v1.5.1
Hebrew completeness for B47 evidence. A third field round confirmed the recurring pattern: a new
check's evidence bullets render in English under --lang he until they get translation rules (the
1.4.1 routing is in place; the per-check prose rules were missing). B47's evidence is now localized,
and adding an evidence rule alongside each new check that emits evidence prose is now standing practice.
Fixed
- B47 evidence bullets are localized. Added
DETAIL_RULESpatterns forreassembly chain: β¦,
reachable via walls only: β¦(prefix translated, the agent-name chain preserved verbatim) and the
threeweakest edge tier: β¦enum values (theschema/filtered/rawkey stays Latin like other
technical tokens; the gloss is Hebrew).detail/fixwere already translated.
Changed
--risk-pathstext output now shows the RISK id. Each path renders as[SEV] RISK-NN: title
(the id was previously only in--json), so a path referenced by id can be cross-referenced in the
human report.- README: noted that the first call right after a skill update can return empty (an OpenClaw
skill-reload timing artifact on the runtime side β re-run; verify with--verify-self).
ClawSecCheck v1.5.0
Cross-agent trifecta reassembly (confused deputy). B45 (1.4.0) checks whether one agent is the
trifecta. But separation is fictional if the trifecta reassembles across delegation: an
untrusted-input agent that can drive a sensitive-data agent and an outbound agent has the whole
trifecta even though no single agent holds all three. What decides exploitability is the data-handling
tier on the edge β a typed/structured return is a wall; raw passthrough carries the poison. Grounded in
docs/research/multiagent-privilege-separation.md: config has no delegation graph, so this is
attestation-driven and advisory; the runtime data-flow property stays honestly UNKNOWN.
Added
- B47 β cross-agent trifecta reassembly (delegation graph). Reads a new attestation block
delegation: [{from, to, returns}](returnsβschema/filtered/raw/unknown) and walks the
graph from each untrusted-input agent. UNKNOWN without adelegationblock; PASS when the trifecta
is unreachable across agents or when every traversable edge is aschemawall (with an explicit
not-runtime-verified caveat); WARN when an untrusted agent reassembles the trifecta via a non-wall
edge (raw/filtered/unknown).ATTESTEDconfidence, advisory (unscored). - RISK-11 β cross-agent reassembly narrative in the "Highest-risk paths" section, firing on the
same condition with the concrete chain (<entry> β <secrets> β <outbound>). - Attestation parser
attest.attested_delegation()+ thedelegationblock intemplate()/
_questions, additive underclawseccheck-attest/1(older attestations stay valid). - Shared
checks._reassembly()graph helper (reused by B47 and RISK-11); tiersschema=3 (wall) > filtered=2 > raw=1 β unknown=1.
Notes
- Zero false-positive FAILs held: without a
delegationblock B47 is UNKNOWN everywhere and RISK-11
never fires. Verified across the real-schema fixture corpus βhome_safe(A/91, 0 FAIL) and
home_vuln(8 FAILs) baselines unchanged; no B47 FAIL anywhere. - Conservative by design: a necessary-condition reachability + weakest-tier heuristic, not a precise
per-edge data-flow proof. Whether a privileged agent re-interprets returned data at runtime stays
UNKNOWN (out of static scope). RISK narratives remain English-only (a generalrender_risk_paths
limitation across all RISK rules).
ClawSecCheck v1.4.1
Hebrew report completeness. A field validation confirmed a general gap: in --lang he, finding
evidence bullets rendered in English while detail/fix translated (first seen on C5, then on
B45). Evidence now runs through the same i18n pipeline (tp) as detail/fix.
Fixed
- Evidence bullets are localized.
report._render_findingroutes each evidence line through
tp(ev, lang). The translation is graceful and data-safe: a bullet matching aPHRASESkey or a
DETAIL_RULESpattern is translated, while a dynamic data bullet (path, verb name, perm bits, agent
name) has no match and is preserved verbatim.lang="en"is unaffected (tpis a no-op there). - Added a
DETAIL_RULESpattern for the B45 trifecta-decomposition evidence (<agent>: holds all 3 legs): the prose is Hebrew, the agent name (data) is preserved.
Notes
- Pure-data / taxonomy evidence (paths, verb names, perm bits, blast-radius class tokens) stays
language-neutral by design β the same stance as the English-by-design JSONdetail/fixcontract.
No FAIL/WARN verdict changed; this is output-text only.
ClawSecCheck v1.4.0
Multi-agent privilege separation. The trifecta check (A1) flattens the whole setup into one
capability surface, so it can't tell a monolithic agent (one agent holds all three legs) from a
properly separated fleet where no single agent does β and it fails the separated fleet anyway. Two
new checks close that blind spot. Grounded against the real OpenClaw schema
(docs/research/multiagent-privilege-separation.md): config expresses the fact of multi-agent
topology but not the delegation graph, per-agent tool allowlists, or inter-agent data-handling β
so per-agent analysis is attestation-driven, and the runtime parts stay honestly out of scope.
Added
- B45 β per-agent privilege separation (trifecta decomposition). Reads the attested agent roster
(newagents: [{name, tools}]block in the--attestself-report;--asktemplate updated) and
classifies each agent's trifecta legs itself. WARN when a single agent holds all three legs
(separation absent); PASS when none does (necessary condition met β explicitly not a safety
guarantee); UNKNOWN without a roster.ATTESTEDconfidence, advisory (unscored) β like B43/B44, the
verdict rests on a self-report the static config can't corroborate, so it never moves the grade. - B46 β multi-agent trifecta exposure. Config-only, scored: spawnable subagents + the global
trifecta active + no exec approval gate β WARN. Capped at WARN so it can never introduce a new FAIL
on a real config; a deliberate light nudge layered on A1, not a duplicate. - New attestation parser
attest.attested_agents()(tolerant, mirrorsattested_paths());agents
block added totemplate()/_questions, additive under the sameclawseccheck-attest/1schema
(older attestations stay valid).
Notes
- Zero false-positive FAILs held: without
--attestB45 is UNKNOWN everywhere (no new FAIL by
construction), and B46 is capped at WARN. Verified across the real-schema fixture corpus β
home_safeunchanged (A/91, 0 FAIL),home_vulnFAIL baseline unchanged (8 FAILs), no spurious
B46 WARN. - Deferred to 1.5.0 (needs an attestation
delegationblock): cross-agent confused-deputy reassembly
(RISK-11) and the inter-agent data-handling tier (structured-return wall / text-filter sieve /
raw passthrough). The Β§4 grounding doc records why the runtime trust property stays UNKNOWN.