fix(openclaw): parse nested SKILL.md frontmatter + hoist metadata.openclaw.web3#19
Merged
Merged
Conversation
…nclaw.web3
The hand-rolled YAML parser in `packages/openclaw/src/manifest.ts` only
handled a single level of nesting, so any SKILL.md whose frontmatter
declared `metadata.openclaw.web3.policy.allowedContracts` (the shape the
Web3 Annex recommendations doc tells skills to use, and the shape adopted
upstream in odos-xyz/odos-skills) was silently flattened — leaving the
parsed manifest with a malformed `metadata` block and no `web3` field at
all. The W04M-003 / W04M-004 rules then fired as false positives, and
the downstream AST-W rules that read `manifest.web3.*` were skipped
entirely (silently masking real findings, e.g. AST-W12 audit sink /
kill-switch / runbook gaps).
This change:
- Replaces the custom `parseYaml` with the standard `yaml` package so
deeply-nested frontmatter parses correctly (no more single-level
limitation, plus correct handling of block scalars and quoted keys).
- Hoists `metadata.openclaw.web3` to top-level `manifest.web3` during
normalization when no top-level `web3` block is declared. Both shapes
are now supported; top-level wins when both are present.
- Normalizes `policy.allowedContracts` (and `allowedSelectors`) from
chain-keyed maps (`{ 1: ["0x..."], 8453: ["0x..."] }`) into deduped
flat string arrays, so every downstream rule can read them as
`string[]` without crashing on `.map`/`.includes`. This fixes a
scanner regression in `web3-permit-capture` that surfaced once the
hoist was in place.
- Adds parser and normalizer tests covering: deeply-nested frontmatter
parsing, hoisting from `metadata.openclaw.web3`, top-level wins over
nested, metadata preservation for AST04, and the chain-keyed-map
flatten case.
Verified against odos-xyz/odos-skills@93b3db6: W04M-003 and W04M-004
findings clear (Odos correctly credited for the fixes shipped in their
PRs #2-#4), and the previously-masked AST-W12 findings now correctly
fire so they can be addressed upstream.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
Markeljan
added a commit
that referenced
this pull request
May 21, 2026
Honest grades: fixes the MetricsAnalyzer wiring bug that made every audit fall through to hardcoded defaults, calibrates four web3 severities (W12-001/002/003, W04M-002) to LOW so governance-hygiene gaps stop masquerading as exploitable findings, and makes maintenance + documentation scoring skill-type-aware so markdown-only skill packs aren't penalized for missing source-code signals. Also rolls up the openclaw frontmatter parser fix (nested SKILL.md parsing + metadata.openclaw.web3 hoisting) shipped in #19. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The hand-rolled YAML parser in
packages/openclaw/src/manifest.tsonly handled one level of nesting, so any SKILL.md whose frontmatter declaredmetadata.openclaw.web3.policy.allowedContracts(the shape recommended in docs/odos-skill-recommendations.md and adopted upstream by odos-xyz/odos-skills) was silently flattened — the parsed manifest ended up with a malformedmetadatablock and noweb3field. Consequences:W04M-003(nometadata.openclaw) andW04M-004(noallowedContracts) fired as false positives, even when both fields were correctly declared.manifest.web3.*(AST-W01, AST-W06, AST-W10, AST-W12, etc.) was silently skipped becausemanifest.web3was undefined — masking real findings.What changed
parseYamlwith the standardyamlpackage. Correct handling of arbitrary nesting, block scalars, anchors, and quoted keys — replacing the ~60 LoC single-level scanner that was the root cause.metadata.openclaw.web3→ top-levelmanifest.web3during normalization, only when no top-levelweb3is declared (top-level wins on conflict). Lets skills follow either canonical layout; every rule keeps reading the same single path.policy.allowedContracts/allowedSelectorsfrom chain-keyed maps ({ 1: ["0x..."], 8453: ["0x..."] }) into deduped flatstring[]. Fixes a scanner regression inweb3-permit-capturethat surfaced once the hoist was wired up (it crashed withallowlistArray.map is not a functionon the chain-keyed shape).metadata.openclaw.web3, top-level wins, metadata preservation for AST04, chain-keyed-map flattening.Verification
Re-audited odos-xyz/odos-skills@93b3db6 with
--profile web3:Score moved from a falsely-flattering 65 (C) to an accurate 47 (D) for the latest Odos commit. The two false-positives Odos was being penalized for now clear; the previously-masked AST-W12 findings (rec #8 in the Odos recommendations doc — not yet shipped upstream) now correctly fire. Re-running the audit against the pre-recommendation commit
f88b7c89is byte-identical to the v0.3.0 baseline (53, same 5 findings), confirming no regression on manifests that don't use the nested shape.Test plan
bun run build— 9/9 packagesbun run test— 17/17 tasks, 95 openclaw tests pass (5 new), 0 failuresbun run check— typecheck cleanbun run lint— only pre-existing complexity warnings (unrelated, on other files)f88b7c89(pre-recommendation baseline) — no regressione2e/fixtures/good-skill)🤖 Generated with Claude Code