Skip to content

feat(runner): support OpenClaw plugins across the ClawHub profile#15

Merged
Patrick-Erichsen merged 5 commits into
openclaw:mainfrom
VACInc:plugin-targets
Jul 18, 2026
Merged

feat(runner): support OpenClaw plugins across the ClawHub profile#15
Patrick-Erichsen merged 5 commits into
openclaw:mainfrom
VACInc:plugin-targets

Conversation

@VACInc

@VACInc VACInc commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add explicit OpenClaw plugin directory and manifest targets with stable identity, ambiguity handling, symlink-hardened reads, and OpenClaw-compatible JSON5 parsing.
  • Run the current built-in clawhub scanners, SkillSpector and ClawScan Static, for plugins and provide packageRelease context to the bundled judge.
  • Keep Socket and VirusTotal available for explicit selection and custom profiles, while skill-only scanners return an explicit skipped result for plugin targets.
  • Scan complete plugin directories, preserve explicit skill or plugin selection in dual-layout packages, and build deterministic plugin.zip artifacts for VirusTotal.

Root Cause

Before this PR, target resolution recognized only skills and URLs. Scanner capability checks and artifact metadata had no plugin target kind, so OpenClaw plugin manifests were routed through skill assumptions.

The original PR head also decoded openclaw.plugin.json with strict encoding/json. ClawSweeper reproduced that comments, trailing commas, and unquoted keys accepted by OpenClaw failed before scanner dispatch. Inspection of OpenClaw's manifest loader confirmed a strict-JSON first pass with JSON5 fallback.

During review, dual-layout packages exposed two related classification gaps: explicit SKILL.md narrowed the scan to one file, and VirusTotal independently reclassified the enclosing directory from its contents. The final implementation carries resolved target kind and ID into scanner dispatch and recognizes explicit manifests by filesystem identity.

Security / Trust Impact

Plugin contents remain untrusted. Manifest discovery does not follow symlinks; reads use O_NOFOLLOW, a same-file check, and a 256 KiB cap. The exact lowercase id key is required and validated before it enters artifacts or ZIP metadata. A directory containing both manifests fails closed until the caller selects the intended manifest.

VirusTotal can upload a deterministic archive when explicitly selected or included in a custom profile. Operators should not submit confidential packages to a public VirusTotal corpus.

Real behavior proof

Closest feasible host behavior on the final head:

go test -count=1 ./internal/runner -run 'TestReadPluginIDAcceptsOpenClawJSON5Syntax|TestVirusTotalRespectsExplicitSkillInDualLayoutPackage|TestResolveTargetExplicit(Skill|Plugin)ManifestDisambiguatesDualLayout' -v
PASS
ok github.com/openclaw/clawscan/internal/runner 0.010s

The JSON5 test passed comments, trailing commas, unquoted and escaped keys, single quotes, BOM, Unicode whitespace and keys, and extended escapes.

A real first-party plugin from an OpenClaw checkout was then scanned with the final binary. The checkout prefix is redacted:

go run ./cmd/clawscan "$OPENCLAW_REPO/extensions/synology-chat/openclaw.plugin.json" --scanner clawscan-static --json

Observed result:

{
  "target": {"kind":"plugin","id":"synology-chat"},
  "status": "completed",
  "scanned": 25,
  "omitted": 0
}

Current profile behavior was also checked with go run ./cmd/clawscan profiles -v; clawhub lists exactly skillspector and clawscan-static.

Verification

  • go test -count=1 ./...
  • go test -race -count=1 ./...
  • go vet ./...
  • make docs-site, built 6 pages
  • CGO-disabled builds: Darwin amd64/arm64, Linux amd64/arm64, Windows amd64
  • git diff --check
  • go mod tidy -diff
  • Focused JSON5, dual-layout, symlink discovery, filesystem identity, and VirusTotal target-kind regressions
  • GPT-5.6-SOL xhigh repo autoreview and independent closeout review; all reproduced code findings fixed and rerun
  • Remaining repeated VirusTotal profile finding rejected against the live profile file, CLI output, and resolver regression test

What was not tested

  • A live network-backed VirusTotal upload was not rerun after the final JSON5 and target-kind fixes; request, hashing, upload, and response behavior remains fixture-backed.
  • A live full SkillSpector plus Codex judge run was not repeated after the final parser-only and dispatch-context fixes; the real plugin static scan and complete unit/race suites were rerun.
  • Case-insensitive filesystem behavior was not exercised on a native Windows or macOS volume; filesystem-identity regression coverage and all target cross-builds passed.

Scope boundary

Plugins remain explicit targets and are not added to zero-target skill discovery. Benchmark behavior, release automation, and unrelated scanner behavior are unchanged.

@VACInc
VACInc requested a review from Patrick-Erichsen as a code owner July 12, 2026 15:36
@VACInc VACInc changed the title feat(runner): support OpenClaw plugins feat(runner): support OpenClaw plugins across the ClawHub profile Jul 13, 2026
@VACInc

VACInc commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main and expanded plugin support to full built-in clawhub parity at 16b20e8: static + SkillSpector + VirusTotal, plus plugin-aware packageRelease judge context. Full Go tests/race/vet/build/docs, owned-plugin SkillSpector Docker E2E, and xhigh autoreview are green; VirusTotal network behavior remains integration-tested with a mocked API rather than a live submission.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. 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. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Jul 13, 2026
@clawsweeper

clawsweeper Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed July 17, 2026, 8:50 PM ET / July 18, 2026, 00:50 UTC.

Summary
This branch adds explicit OpenClaw plugin target resolution, plugin-aware scanner dispatch and artifacts, deterministic VirusTotal plugin archives, JSON5 manifest parsing, documentation, and regression coverage.

Reproducibility: not applicable. as a bug reproduction. The PR supplies final-head terminal evidence that an explicit real OpenClaw plugin manifest resolves as plugin and completes a static scan.

Review metrics: 2 noteworthy metrics.

  • Patch surface: 18 files affected; 1,310 additions and 81 deletions. The feature spans CLI help, runner dispatch, scanner registry, archive construction, tests, and docs, so its public contract deserves code-owner review.
  • New dependency: 1 direct Go module added. JSON5 compatibility adds github.com/alchemy/json5, which becomes part of parsing untrusted plugin manifests.

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:

  • Obtain code-owner sponsorship for the public plugin target and JSON5 compatibility contract.

Risk before merge

  • [P1] Merging establishes plugin as a public artifact and adapter-capability contract; future scanner adapters and callers will need to preserve its target-kind semantics.
  • [P1] The final proof directly demonstrates the static-scanner path, while final-head external SkillSpector and VirusTotal network behavior remains supported primarily by fixture-backed coverage and earlier reported runs.

Maintainer options:

  1. Sponsor the public contract (recommended)
    Approve the new plugin target and adapter capability semantics as supported public behavior, then merge with the documented compatibility boundary.
  2. Pause for a narrower contract
    Defer merge until maintainers decide whether plugin scanning should be limited to a smaller profile or remain outside the public CLI.

Next step before merge

  • [P2] The remaining blocker is a code-owner product and compatibility decision, not a narrow mechanical repair.

Maintainer decision needed

  • Question: Should ClawScan's public CLI support OpenClaw plugins as a first-class plugin target, including JSON5 manifest compatibility and per-scanner target-kind capability declarations?
  • Rationale: This is a new user-visible target kind and adapter contract rather than a repair to an established ClawScan behavior; technical tests cannot determine whether that public scope belongs in the general-purpose CLI.
  • Likely owner: Patrick-Erichsen — Patrick-Erichsen is the PR's requested code owner for the affected runner and CLI surface.
  • Options:
    • Sponsor the plugin target contract (recommended): Accept plugin targets as a supported ClawScan surface and merge after normal code-owner review of the compatibility and dependency boundary.
    • Narrow the feature: Keep plugin scanning out of the public runner until maintainers define a smaller supported scanner/profile scope and manifest compatibility policy.

Security
Cleared: The diff adds a pinned JSON5 parsing dependency and hardened local manifest reads, but no concrete credential, sandbox, execution, or supply-chain regression is evident in the proposed changes.

Review details

Best possible solution:

Sponsor the explicit plugin-target contract, retain target-aware skips for scanners that do not support plugins, and land only after the code owner accepts the JSON5 parser dependency and compatibility commitment.

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

Not applicable as a bug reproduction. The PR supplies final-head terminal evidence that an explicit real OpenClaw plugin manifest resolves as plugin and completes a static scan.

Is this the best way to solve the issue?

Unclear until a maintainer accepts the public product boundary. Given that decision, the target-aware resolver and explicit scanner capability declaration are a focused, maintainable implementation path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 1d3ca1a27e69.

Label changes

Label changes:

  • 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 includes final-head terminal output from a real OpenClaw plugin static scan with the expected plugin identity and completed result; redact private paths and credentials in any future proof additions.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: This is a bounded new runner capability with meaningful but non-urgent user and compatibility impact.
  • merge-risk: 🚨 compatibility: The PR adds a public target kind and scanner-adapter capability contract that downstream callers and future adapters must preserve.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • feature: ✨ showcase: ClawSweeper spotlight: unusually compelling feature idea for maintainer attention. This creates a practical local security-review loop for OpenClaw plugin authors while preserving explicit targeting and avoiding unsafe auto-discovery.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes final-head terminal output from a real OpenClaw plugin static scan with the expected plugin identity and completed result; redact private paths and credentials in any future proof additions.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes final-head terminal output from a real OpenClaw plugin static scan with the expected plugin identity and completed result; redact private paths and credentials in any future proof additions.
Evidence reviewed

What I checked:

  • Plugin target implementation: The branch introduces internal/runner/target.go for explicit plugin classification and identity, and threads target kind and ID through runner dispatch rather than treating plugin directories as skills. (internal/runner/target.go:1, 3e7689c68e4a)
  • Prior review blocker addressed: The previous ClawSweeper review identified JSON5 manifest support as its remaining P2 finding; the final head adds the JSON5 parser dependency and tests for OpenClaw-compatible manifest syntax. (go.mod:4, 3e7689c68e4a)
  • Compatibility surface: The scanner registry gains a per-adapter target-kind capability contract, while runner gating excludes unsupported plugin scanners from credential and sandbox requirement validation. (internal/runner/scanner_registry.go:11, 3e7689c68e4a)
  • After-fix behavior proof: The PR body provides final-head terminal output from scanning an OpenClaw plugin manifest with clawscan-static, reporting target.kind as plugin, the stable ID, and completed scan counts; it also reports focused regression coverage for JSON5 and dual-layout resolution. (3e7689c68e4a)
  • Current-main status: Current main is release v0.1.6 at 1d3ca1a27e69b55fc4c3f929035ecceb864bd395; the feature head is separate and remains unmerged, so this work is not implemented on main. (1d3ca1a27e69)

Likely related people:

  • Patrick-Erichsen: The PR explicitly requests Patrick-Erichsen as a code owner for this runner and CLI surface, making them the strongest available routing candidate for the public contract decision. (role: requested reviewer and code owner; confidence: high; files: internal/runner/runner.go, internal/runner/scanner_registry.go, cmd/clawscan/main.go)
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 (4 earlier review cycles)
  • reviewed 2026-07-13T20:52:33.197Z sha 16b20e8 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-15T22:45:14.323Z sha 166dbdc :: needs maintainer review before merge. :: none
  • reviewed 2026-07-15T23:28:36.604Z sha 166dbdc :: found issues before merge. :: [P2] Accept OpenClaw's JSON5 manifest format
  • reviewed 2026-07-17T01:18:51.513Z sha 166dbdc :: found issues before merge. :: [P2] Accept OpenClaw's JSON5 manifest format

@VACInc

VACInc commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto bf6f4f1; new head 166dbdc.

Post-rebase review fixes: dual-layout explicit manifest handling, stable and timezone-independent plugin ZIP identity, and Socket plugin compatibility.

Revalidated: go test -count=1 ./..., race tests, vet, docs, five release builds, first-party dual-layout plugin E2E, and owned full clawhub E2E. Final GPT-5.6-SOL xhigh review found no actionable issues.

@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. feature: ✨ showcase ClawSweeper spotlight: unusually compelling feature idea for maintainer attention. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 16, 2026
VACInc added 5 commits July 17, 2026 19:29
Add a small target abstraction so explicit OpenClaw plugin directories are
recognized, validated, scanned, and reported without being forced through
SKILL.md assumptions, while preserving existing skill behavior and zero-target
skill discovery.

- resolveTarget/classifyLocalTarget classify a directory (or manifest file)
  holding openclaw.plugin.json as kind=plugin and record the stable manifest
  id; skills, single files, and missing paths keep the historical skill kind.
  A directory carrying both manifests is rejected as ambiguous, and an invalid
  plugin id fails the run before any scanner work. A manifest-file target is
  scanned as its surrounding plugin directory so scanners see the plugin code.
- Plugin ids follow OpenClaw's install grammar, including @scope/name ids, and
  the manifest size cap matches the host runtime's 256 KiB limit.
- Scanner adapters declare SupportsTargetKind; the built-in clawscan-static
  scanner analyzes plugin targets while skill-only scanners return an explicit
  skipped result. Requirement validation and Docker gating are target-aware,
  so scanners that can only skip never demand credentials or a sandbox.
- Manifest reads never follow symlinks: classification lstats manifests and
  readPluginID opens O_NOFOLLOW with a same-file identity re-check, so a
  hostile target cannot point its manifest at a host file outside the target.
- Plugins are never auto-discovered; zero-target discovery still scans only
  ./skills. Documented in CLI help, README, and docs/scanners.md.

Adds registry, runner, and end-to-end CLI tests covering plugin classification,
scoped ids, manifest-file targets, symlinked-manifest rejection, static-scanner
completion over plugin code, credential-free skips, ambiguity, and no
auto-discovery.

VACInc commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto 1d3ca1a; new head 3e7689c.

Addressed the JSON5 blocker plus closeout findings for exact lowercase IDs, complete dual-layout scans, symlink-safe discovery, filesystem-identity manifest selection, and VirusTotal target-kind consistency. Updated the body and docs for the current two-scanner built-in clawhub profile.

Revalidated: full tests, race tests, vet, docs, five target builds, focused real-plugin/static and JSON5 behavior, repo autoreview, and independent closeout review.

@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown

🦞🧹
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.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 18, 2026
@clawsweeper clawsweeper Bot added the status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. label Jul 18, 2026
@Patrick-Erichsen
Patrick-Erichsen merged commit a37f49f into openclaw:main Jul 18, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature: ✨ showcase ClawSweeper spotlight: unusually compelling feature idea for maintainer attention. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants