fix(plugin-sdk): remove relative extension boundary escapes#51939
fix(plugin-sdk): remove relative extension boundary escapes#51939Takhoffman merged 5 commits intomainfrom
Conversation
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
4 similar comments
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
89973a6 to
a3e9bb0
Compare
a3e9bb0 to
181db5b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 181db5b147
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50c0130e01
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| "peerDependenciesMeta": { | ||
| "openclaw": { | ||
| "optional": true |
There was a problem hiding this comment.
Make the new OpenClaw peer dependency mandatory
In the plugin install path we unpack the plugin and run npm install --omit=dev inside that isolated directory (src/infra/install-package-dir.ts:188-199). Because the new openclaw peer is marked optional here, npm accepts the install without checking/materializing the host package, so users on older OpenClaw releases can still install or update these plugins and only discover the break later when the new openclaw/plugin-sdk/* imports from their runtime barrels cannot be resolved. The same peerDependenciesMeta.openclaw.optional stanza was added to the other updated public plugin manifests in this commit, so the compatibility gate is still ineffective.
Useful? React with 👍 / 👎.
| // Keep this barrel thin and aligned with the local extension surface. | ||
|
|
||
| export * from "../../src/plugin-sdk/twitch.js"; | ||
| export * from "openclaw/plugin-sdk/twitch"; |
There was a problem hiding this comment.
Add a minimum host-version gate for Twitch
extensions/twitch/runtime-api.ts now depends on the brand-new openclaw/plugin-sdk/twitch export, but extensions/twitch/package.json still has no peerDependencies.openclaw floor. Twitch is installable from npm today — the docs explicitly tell users to run openclaw plugins install @openclaw/twitch (docs/channels/twitch.md:16-20), and catalog resolution falls back to the package name when openclaw.install.npmSpec is absent (src/channels/plugins/catalog.ts:187-195) — so hosts older than this commit can accept the package and then fail at load time because their loader never aliases that new subpath.
Useful? React with 👍 / 👎.
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🔵 Symlink-following write enables arbitrary file overwrite when sanitizing bundled extension package.json
Description
Because the code writes the manifest using
Vulnerable code: function writeJson(filePath, value) {
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
}
...
if (changed) {
writeJson(manifestPath, packageJson);
}This is a classic symlink attack risk in build/staging scripts when operating on potentially untrusted directories/artifacts. RecommendationHarden writes to At minimum, fail closed if the manifest is not a regular file: import fs from "node:fs";
import path from "node:path";
function safeWriteJson(manifestPath, value, pluginDir) {
// Ensure the resolved path stays within the plugin directory
const realPluginDir = fs.realpathSync(pluginDir);
const realManifestDir = fs.realpathSync(path.dirname(manifestPath));
if (realManifestDir !== realPluginDir) {
throw new Error(`Refusing to write manifest outside pluginDir: ${manifestPath}`);
}
const st = fs.lstatSync(manifestPath);
if (st.isSymbolicLink() || !st.isFile()) {
throw new Error(`Refusing to write non-regular manifest file: ${manifestPath}`);
}
fs.writeFileSync(manifestPath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
}For stronger protection on platforms that support it, open the file with Analyzed PR: #51939 at commit Last updated on: 2026-03-22T01:47:09Z |
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]>
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]>
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]>
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]>
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]>
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]> (cherry picked from commit 2b4c3c2) # Conflicts: # scripts/stage-bundled-plugin-runtime-deps.mjs
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]>
…#51939) * fix(plugin-sdk): remove relative extension boundary escapes * Gate new plugin-sdk subpaths on host version * Add changelog entry for openclaw#51939 * Fix local staging for plugin-sdk host version gate * Raise host floor for line and googlechat plugins --------- Co-authored-by: Tak Hoffman <[email protected]>
Summary
runtime-api.tsbarrels and one BlueBubbles helper import still used relative paths that escaped their own package roots, and therelative-outside-packageboundary check tolerated the existing violations via a checked-in baseline.openclaw/plugin-sdk/*subpaths, rewired the violating extension imports to those public seams, and changedrelative-outside-packageto hard-fail on any violation.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
Bundled extensions now consume plugin SDK seams through public
openclaw/plugin-sdk/*subpaths instead of relative escapes. Therelative-outside-packagerule now fails immediately on any future violation.Security Impact (required)
No)No)No)No)No)Yes, explain risk + mitigation:Repro + Verification
Environment
Steps
pnpm lint:extensions:no-relative-outside-packageonmainand inspect the non-empty inventory.openclaw/plugin-sdk/*import and export the missing subpaths.pnpm build.Expected
relative-outside-packagereports no violations and fails if any reappear.Actual
Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
pnpm lint:extensions:no-relative-outside-package,pnpm lint:plugins:plugin-sdk-subpaths-exported,pnpm test -- test/extension-plugin-sdk-boundary.test.ts src/plugin-sdk/runtime-api-guardrails.test.ts src/plugin-sdk/subpaths.test.ts, andpnpm build.openclaw/plugin-sdk/imessage-core; confirmed the boundary script no longer accepts a non-empty relative-outside-package baseline.Review Conversations
If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.
Compatibility / Migration
Yes)No)No)Failure Recovery (if this breaks)
ad5d80862a.package.json,scripts/lib/plugin-sdk-entrypoints.json, and the touched extensionruntime-api.ts/targets.tsfiles.Risks and Mitigations
plugin-sdk:check-exports,subpaths.test.ts, and the targeted boundary/runtime-api tests.AI-assisted: Yes. Tested locally.