← Back to PRs

#20424: Fix plugin extension path traversal in discovery/install

by markmusson open 2026-02-18 22:15 View on GitHub →
size: S
## 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