#20424: Fix plugin extension path traversal in discovery/install
size: S
Cluster:
Plugin Management Enhancements
## Summary
Hardens plugin package handling to prevent `openclaw.extensions` from escaping plugin package directories.
## Changes
- `src/plugins/discovery.ts`
- Add canonical path resolution + containment checks (`isPathInside`) for manifest extension entries.
- Manifest entries resolving outside the package directory are ignored and emit warnings in discovery diagnostics.
- `src/plugins/install.ts`
- Validate `openclaw.extensions` entries against package root before install.
- Reject install when any extension entry escapes the package directory (fail-closed).
- Keep existing scan behavior for valid entries and maintain install copy checks using validated paths.
- `src/plugins/discovery.test.ts`
- Added regression test for escaped manifest extension in discovery.
- `src/plugins/install.e2e.test.ts`
- Added regression test for install-time rejection of escaped extension entries.
## Security Impact
- Prevents plugin manifest path traversal / trusted-load confusion where a package could point extension loading outside its extracted directory.
- Enforces explicit integrity boundary between package artifacts and loaded extensions.
## Validation
Ran focused tests on the working dependency tree containing the same changes:
- `pnpm --dir /Users/mmusson/projects/openclaw/claw-mem/openclaw-latest exec vitest run --config vitest.unit.config.ts src/plugins/discovery.test.ts` (pass)
- `pnpm --dir /Users/mmusson/projects/openclaw/claw-mem/openclaw-latest exec vitest run --config vitest.e2e.config.ts src/plugins/install.e2e.test.ts` (pass)
## Commit
- `a75b6df7f` Harden plugin extension path handling
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR hardens plugin extension path handling to prevent `openclaw.extensions` manifest entries from escaping their package directory via path traversal (e.g., `../outside.js`).
- **`discovery.ts`**: Adds `isManifestExtensionInsidePackage` check using the existing `isPathInside` utility. Invalid entries are skipped with a diagnostic warning (warn-and-continue), which is appropriate for the read-only discovery phase.
- **`install.ts`**: Upgrades the traversal check from warn-and-skip to fail-closed — if any extension entry escapes the package directory, the entire install is rejected. The `afterCopy` callback is simplified to iterate over the already-validated `forcedScanEntries` rather than re-validating against `targetDir`.
- **Tests**: Both `discovery.test.ts` and `install.e2e.test.ts` add regression tests covering the `../outside.js` traversal vector, verifying that discovery ignores the entry and install rejects the package respectively.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it adds a well-scoped security hardening with correct logic and appropriate test coverage.
- The changes are focused and correct. The `isPathInside` utility is well-tested and handles edge cases (traversal, same-path, cross-drive). Discovery uses warn-and-skip (appropriate for read-only), install uses fail-closed (appropriate for write operations). The `afterCopy` refactor correctly maps validated entries to the target directory. Both code paths have regression tests. No issues found.
- No files require special attention
<sub>Last reviewed commit: a75b6df</sub>
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#21245: fix(plugins): harden symlinked extension discovery
by victorGPT · 2026-02-19
83.3%
#7090: fix: plugin install uses manifest ID for folder name (#2796)
by dial481 · 2026-02-02
82.2%
#21964: Security: harden gateway and plugin trust boundaries
by Elormyevu · 2026-02-20
81.8%
#2556: fix(plugin-install): handle existing plugins and filter workspace deps
by longmaba · 2026-01-27
80.2%
#23574: security: P0 critical remediation — plugin sandbox, password hashin...
by lumeleopard001 · 2026-02-22
80.0%
#14112: test(security): harden plugin install against script execution
by davidahmann · 2026-02-11
79.9%
#20499: test(plugins): add bundled+config duplicate discovery regression
by dcol91863 · 2026-02-19
79.7%
#19941: fix(nostr): move openclaw from devDependencies to peerDependencies
by AustinEral · 2026-02-18
79.6%
#11439: fix(security): warn on relative OPENCLAW_CONFIG_PATH and disable co...
by coygeek · 2026-02-07
79.3%
#21660: fix(plugins): require explicit allowlist for non-bundled plugins
by AI-Reviewer-QS · 2026-02-20
79.3%