#19542: security: sandbox dynamic import in hook transforms with symlink validation
gateway
size: XS
Cluster:
Plugin Management Enhancements
## Summary
- Add `fs.realpathSync()` validation before `import()` in `loadTransform`
- After resolving symlinks, re-validate that the real path stays within the transforms directory
- Pass `containingDir` in `HookMappingTransformResolved` for post-symlink containment checks
- Complements the existing `resolveContainedPath` pre-check with a runtime symlink guard
## Security Impact
Prevents symlink-based escapes where a symbolic link inside the transforms directory could point to arbitrary code on the filesystem, bypassing the existing path traversal checks.
## Test plan
- [x] Existing path traversal tests still pass
- [ ] Test symlink outside transforms directory is rejected
- [ ] Verify legitimate transform modules still load correctly
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
added symlink validation in `loadTransform` to prevent path traversal attacks where a symbolic link inside the transforms directory could point to arbitrary filesystem locations
**Key changes:**
- imports `fs` for `realpathSync()` calls
- added `containingDir` field to `HookMappingTransformResolved` type to track the transforms directory
- before dynamic `import()`, resolves symlinks for both module path and containing directory
- validates that the real module path stays within the real containing directory using `path.relative()`
**Issues found:**
- critical logic bug in the containment check at line 354-355 that allows symlink escape when the symlink points to the containing directory itself (empty relative path bypasses all conditions)
<h3>Confidence Score: 1/5</h3>
- This PR contains a critical security bug that undermines the symlink protection it's trying to add
- the containment validation at lines 354-355 has a logic error where an empty relative path (when symlink points to the containing directory itself) bypasses all security checks, allowing attackers to escape the transforms directory and execute arbitrary code from the filesystem. This completely defeats the purpose of the security fix.
- Pay close attention to `src/gateway/hooks-mapping.ts` lines 354-355 - the containment check logic is incorrect
<sub>Last reviewed commit: 4729df3</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#23294: fix(security): OC-201 Hook Transform RCE - Symlink-Safe Path Contai...
by aether-ai-agent · 2026-02-22
81.7%
#23473: Hooks/Plugins: enforce discovery root containment
by bmendonca3 · 2026-02-22
79.1%
#19021: fix(hooks): reject path traversal in hook pack manifest entries dur...
by moxunjinmu · 2026-02-17
73.4%
#22910: fix(browser): resolve symlinks in upload path validation
by erdinccurebal · 2026-02-21
72.4%
#16929: fix(security): block access to sensitive directories from within sa...
by CornBrother0x · 2026-02-15
72.1%
#3564: fix(plugins): follow symlinks in plugin and hook discovery
by mollywires · 2026-01-28
71.8%
#15611: fix(gateway): invalidate hook transform cache on config reload
by AI-Reviewer-QS · 2026-02-13
71.7%
#13144: harden archive extraction, auth tokens, hook transforms, and queue ...
by qxlsz · 2026-02-10
71.3%
#23308: fix(browser): accept upload paths that traverse symlinked tmp dirs
by SidQin-cyber · 2026-02-22
70.8%
#8846: fix(tools): block LLM writes to hooks directories
by yubrew · 2026-02-04
70.5%