Skip to content

feat: add hosted feed envelope verifier#98299

Merged
giodl73-repo merged 8 commits into
openclaw:mainfrom
giodl73-repo:feeds-trust-envelope-verifier
Jul 9, 2026
Merged

feat: add hosted feed envelope verifier#98299
giodl73-repo merged 8 commits into
openclaw:mainfrom
giodl73-repo:feeds-trust-envelope-verifier

Conversation

@giodl73-repo

@giodl73-repo giodl73-repo commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Related: openclaw/rfcs#25

What Problem This Solves

Starts the hosted feed trust-verification implementation series by adding the signed envelope verifier primitives that later feed refresh and source-profile PRs can consume.

Why This Change Was Made

This adds a small, isolated verifier for OpenClaw-hosted external plugin catalog envelopes. It verifies Ed25519 signatures over DSSE PAE using the decoded serialized payload bytes, accepts PEM or raw base64url public keys, validates the payload type, and only parses the feed after a trusted signature verifies.

This PR intentionally does not wire signed envelopes into marketplace refresh, config, snapshot persistence, CLI output, or install eligibility. Those stay in follow-up PRs from the RFC trust series.

The Ed25519 PEM/raw-key verification helpers are shared with device identity code so the new feed verifier does not fork a second signature implementation.

User Impact

No user-visible behavior changes yet. This is a draft implementation foundation for future signed hosted feed verification.

Real behavior proof

Behavior or issue addressed:
Signed hosted feed envelopes can be verified against an explicit trusted Ed25519 key using DSSE PAE over decoded serialized payload bytes. Equivalent URL-safe and standard base64 encodings of the same payload bytes verify against the same signature input; payload bytes changed after signing are rejected before the feed is trusted; malformed raw signature arrays are capped before filtering or verification.

Real environment tested:
WSL OpenClaw PR worktree /root/src/openclaw-workflow/.worktrees/pr-98299-fix at PR head 297003b252cdc57b7f3f3e53c54113ae28f4001b; source harness using node --import tsx -; generated in-memory Ed25519 proof key; no network service or persisted cache involved.

Exact steps or command run after this patch:

  1. Run a source harness that imports createOfficialExternalPluginCatalogEnvelopePayload, createOfficialExternalPluginCatalogEnvelopeSigningInput, and verifyOfficialExternalPluginCatalogSignedEnvelope from src/plugins/official-external-plugin-catalog-envelope.ts.
  2. Generate an Ed25519 keypair, encode a minimal clawhub-official feed payload as URL-safe base64, sign DSSE PAE over the decoded payload bytes, and verify the URL-safe envelope with a trusted PEM key.
  3. Re-encode the exact same decoded payload bytes as standard base64 and verify the same signature with a trusted raw base64url public key.
  4. Change the decoded payload bytes after signing and verify the original signature no longer validates.
  5. Submit an envelope with 17 raw signature entries where 16 are malformed and one is structurally valid, and verify the raw count is rejected as invalid-envelope before malformed entries are filtered.

Evidence after fix:

{
  "signingInputUtf8Prefix": "DSSEv1 49 openclaw.official-external-plugin-catalog-feed.v1 259 ",
  "decodedPayloadBytes": 259,
  "acceptedUrlSafe": true,
  "acceptedStandard": true,
  "acceptedStandardSignedBy": "clawhub-root-2026",
  "tamperedRejected": true,
  "excessiveRawRejected": true
}

Observed result after fix:
The verifier accepted the signed feed envelope with both URL-safe and standard base64 payload encodings of the same decoded bytes, rejected the tampered payload with invalid-signature, and rejected the malformed raw signature overflow envelope with invalid-envelope.

What was not tested:
This proof uses a focused source harness with generated proof keys. It does not test live ClawHub hosted envelope publication, marketplace refresh wiring, config trust-root selection, snapshot trust-state persistence, CLI output, or install eligibility because those are intentionally deferred to later PRs in the trust series.

Validation

> node scripts/run-vitest.mjs src/plugins/official-external-plugin-catalog-envelope.test.ts --reporter=dot
Test Files 1 passed (1)
Tests 12 passed (12)
[test] passed 1 Vitest shard

> npx oxfmt --check src/infra/ed25519-signature.ts src/plugins/official-external-plugin-catalog-envelope.ts src/plugins/official-external-plugin-catalog-envelope.test.ts
All matched files use the correct format.

> npx oxlint src/infra/ed25519-signature.ts src/plugins/official-external-plugin-catalog-envelope.ts src/plugins/official-external-plugin-catalog-envelope.test.ts
Found 0 warnings and 0 errors.

> git diff --check origin/main...HEAD && git diff --check
PASS

> pnpm tsgo:core
PASS

> node --import tsx -
acceptedUrlSafe=true acceptedStandard=true tamperedRejected=true excessiveRawRejected=true

@openclaw-barnacle openclaw-barnacle Bot added size: M maintainer Maintainer-authored PR labels Jun 30, 2026
@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 8, 2026, 10:19 PM ET / 02:19 UTC.

Summary
Adds shared Ed25519 helper utilities and a DSSE-backed verifier/test suite for signed hosted external plugin catalog feed envelopes, exposed through a lazy catalog-loader entry point.

PR surface: Source +266, Tests +296. Total +562 across 5 files.

Reproducibility: not applicable. as a feature PR; the changed behavior is source-reproducible through the verifier harness and focused Vitest described in the PR body and comments.

Review metrics: 1 noteworthy metric.

  • Verifier consumer state: 1 verifier added, 0 live refresh consumers wired. The PR intentionally establishes the signed-envelope primitive before marketplace refresh, config, snapshot, or install eligibility changes.

Stored data model
Persistent data-model change detected: database schema: src/plugins/official-external-plugin-catalog-envelope.test.ts, database schema: src/plugins/official-external-plugin-catalog-envelope.ts, serialized state: src/plugins/official-external-plugin-catalog-envelope.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: canonical
Canonical: #98299
Summary: This PR is the base verifier primitive for a hosted feed trust stack; the related same-repo PRs are adjacent follow-up slices rather than duplicates.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Risk before merge

  • [P1] This establishes a security-sensitive envelope verification contract that the follow-up trust stack will consume, so maintainers should keep merge tied to the accepted DSSE/RFC direction and exact-head checks.
  • [P1] Live ClawHub publication, config trust-root selection, snapshot trust-state persistence, CLI output, and install eligibility are intentionally deferred to linked follow-up PRs.

Maintainer options:

  1. Accept the reviewed verifier primitive (recommended)
    Merge after required checks if maintainers are comfortable making this DSSE envelope contract the base for the hosted-feed trust series.
  2. Hold for broader trust-stack review
    Pause this PR if maintainers want the verifier, config, refresh enforcement, and CLI trust output reviewed as one security boundary.

Next step before merge

  • No ClawSweeper repair lane is needed because the prior blockers are fixed and the remaining action is normal maintainer/check-gated merge handling.

Security
Cleared: No concrete security or supply-chain defect was found in the current verifier-only diff; the temporary shrinkwrap changes are no longer in the live PR files.

Review details

Best possible solution:

Land this narrow verifier primitive only after maintainer security-boundary approval and exact-head checks, then keep config, refresh-state, and CLI trust rendering in the stacked follow-up PRs.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a feature PR; the changed behavior is source-reproducible through the verifier harness and focused Vitest described in the PR body and comments.

Is this the best way to solve the issue?

Yes; after the prior DSSE and signature-bound fixes, sharing Ed25519 helpers and exposing a lazy verifier is a narrow foundation while keeping refresh/config wiring in follow-up PRs.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 0307deacfac7.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body and follow-up comments provide terminal/source-harness proof for accepted signed envelopes, equivalent base64 encodings, tamper rejection, and raw signature overflow rejection; no live ClawHub service path is part of this slice.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body and follow-up comments provide terminal/source-harness proof for accepted signed envelopes, equivalent base64 encodings, tamper rejection, and raw signature overflow rejection; no live ClawHub service path is part of this slice.

Label justifications:

  • P2: This is a normal-priority feature/security-hardening foundation with limited immediate runtime blast radius because it is not yet wired into marketplace refresh.
  • merge-risk: 🚨 security-boundary: The PR defines the signature verification contract for future trusted hosted feed consumption, which green CI alone cannot validate as the right trust boundary.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body and follow-up comments provide terminal/source-harness proof for accepted signed envelopes, equivalent base64 encodings, tamper rejection, and raw signature overflow rejection; no live ClawHub service path is part of this slice.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and follow-up comments provide terminal/source-harness proof for accepted signed envelopes, equivalent base64 encodings, tamper rejection, and raw signature overflow rejection; no live ClawHub service path is part of this slice.
Evidence reviewed

PR surface:

Source +266, Tests +296. Total +562 across 5 files.

View PR surface stats
Area Files Added Removed Net
Source 4 344 78 +266
Tests 1 296 0 +296
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 5 640 78 +562

What I checked:

Likely related people:

  • Patrick-Erichsen: Patrick is assigned to this PR, contributed an in-branch CI repair, and submitted the latest approval after the DSSE and signature-bound fixes. (role: reviewer and current assignee; confidence: high; commits: 9bd70cb34665; files: src/plugins/official-external-plugin-catalog.ts, src/plugins/official-external-plugin-catalog-envelope.ts)
  • vincentkoc: Current main blame and PR metadata tie the existing catalog and device-identity files to Vincent's recent merged work on refactor(slack): localize internal declarations #102044. (role: recent area contributor; confidence: medium; commits: 5a5b4c5b105f, e085fa1a3ffd; files: src/plugins/official-external-plugin-catalog.ts, src/infra/device-identity.ts)
  • steipete: Git history shows Peter introduced and later refined the device identity helper surface that this PR extracts into shared Ed25519 helpers. (role: device identity feature history; confidence: medium; commits: 73e9e787b4df, 29453c9578d3; files: src/infra/device-identity.ts)
  • giodl73-repo: Beyond authoring this branch, Gio owns the related hosted-feed trust stack and RFC direction referenced by the PR body and linked follow-up PRs. (role: hosted feed trust series proposer; confidence: medium; commits: 1005a6f8c716, a131122093f8, 7504327b53cc; files: src/plugins/official-external-plugin-catalog-envelope.ts, src/plugins/official-external-plugin-catalog-envelope.test.ts, src/infra/ed25519-signature.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (15 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-08T01:04:19.267Z sha 39d2e57 :: needs real behavior proof before merge. :: [P1] Sign DSSE PAE over decoded payload bytes
  • reviewed 2026-07-08T01:12:42.536Z sha 39d2e57 :: needs real behavior proof before merge. :: [P2] Cap the raw signatures array before filtering
  • reviewed 2026-07-08T17:47:24.608Z sha c6525aa :: found issues before merge. :: [P1] Sign DSSE PAE over decoded payload bytes
  • reviewed 2026-07-08T17:55:38.877Z sha c6525aa :: needs real behavior proof before merge. :: [P1] Sign DSSE PAE over decoded payload bytes
  • reviewed 2026-07-08T22:18:49.247Z sha 297003b :: needs maintainer review before merge. :: none
  • reviewed 2026-07-08T22:25:04.961Z sha 297003b :: needs maintainer review before merge. :: none
  • reviewed 2026-07-08T23:20:06.053Z sha d119b8e :: needs maintainer review before merge. :: none
  • reviewed 2026-07-08T23:51:24.954Z sha 448f05f :: needs changes before merge. :: [P1] Remove the unapproved shrinkwrap refresh

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 30, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Updated at 8742cc6515 to address the Ed25519 helper reuse feedback by sharing PEM/raw verification helpers with device identity code. The PR body now includes source-harness real behavior proof showing a signed envelope accepted and a tampered payload rejected with invalid-signature.

@clawsweeper

clawsweeper Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 1, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 🔁 re-review loop A fresh ClawSweeper review was explicitly requested after the latest review. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 2, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Proof and implementation have been refreshed since the current stale verdict: head 8742cc6515 shares Ed25519 PEM/raw verification helpers with device identity and the PR body includes source-harness proof for accepted signed envelope plus tampered payload rejection.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 🔁 re-review loop A fresh ClawSweeper review was explicitly requested after the latest review. labels Jul 6, 2026
@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams channel: signal Channel integration: signal channel: slack Channel integration: slack channel: telegram Channel integration: telegram channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web channel: zalo Channel integration: zalo app: android App: android app: ios App: ios app: web-ui App: web-ui gateway Gateway runtime extensions: diagnostics-otel Extension: diagnostics-otel extensions: lobster Extension: lobster extensions: memory-core Extension: memory-core labels Jul 8, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased the verifier-primitive PR onto current main for maintainer merge verification. The code diff is still the intended five files, and the current head is d119b8e64b811c2b4a06b4c0e544f1fee065ef7c.

Carry-forward proof from the rebased head:

  • DSSE PAE verifies decoded serialized payload bytes rather than base64/base64url envelope text.
  • Standard and URL-safe payload encodings verify the same decoded bytes.
  • Tampered payloads and excessive raw signatures reject.
  • git diff --check origin/main...HEAD passed after rebase.

Please refresh the durable verdict for this exact head before merge.

@clawsweeper

clawsweeper Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Prepared head 448f05f6de7657cb72a761f52c46241c14d4d65d keeps the DSSE verifier diff and adds a generated shrinkwrap refresh because the rebased PR and current origin/main both failed the npm-shrinkwrap guard.

Fresh exact-head local proof:

  • node scripts/generate-npm-shrinkwrap.mjs --all --check
  • pnpm check
  • node scripts/run-vitest.mjs src/plugins/official-external-plugin-catalog-envelope.test.ts --reporter=dot
  • npx oxfmt --check on verifier files plus generated shrinkwrap files
  • npx oxlint on verifier files
  • git diff --check origin/main...HEAD and git diff --check

Please refresh the durable verdict for this exact head before merge.

@clawsweeper

clawsweeper Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Dependency graph guard cleared

This PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh /allow-dependencies-change comment after the guard blocks that new head SHA.

  • Current SHA: eb6fcb20afdaa67f062a3ce1679feb19ffa050f2

@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Restored #98299 to the intended verifier-only diff and rebased onto current main. Current head: eb6fcb20afdaa67f062a3ce1679feb19ffa050f2.

Notes:

  • The temporary generated shrinkwrap repair was reverted because hosted CI checks the protected base shrinkwrap state and dependency guard rejected dependency-file changes in this PR.
  • Net PR diff is back to the five verifier files only.

Fresh exact-head local proof:

  • node scripts/run-vitest.mjs src/plugins/official-external-plugin-catalog-envelope.test.ts --reporter=dot
  • npx oxfmt --check src/infra/ed25519-signature.ts src/plugins/official-external-plugin-catalog-envelope.ts src/plugins/official-external-plugin-catalog-envelope.test.ts
  • npx oxlint src/infra/ed25519-signature.ts src/plugins/official-external-plugin-catalog-envelope.ts src/plugins/official-external-plugin-catalog-envelope.test.ts
  • git diff --check origin/main...HEAD and git diff --check

Please refresh the durable verdict for this exact head.

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@giodl73-repo

Copy link
Copy Markdown
Contributor Author

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: L status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants