# Dynamic path resolution bypasses normalization

Path checks that resolve or compare via mutable lookups or raw bytes, not the OS's own resolution

_Area: Memory corruption and native code. Seen in 2 disclosed reports; one confirmed bounty: $2,330; latest 2026-06-16. Updated 2026-10-24._

## How it works
A security check decides whether a path is allowed by computing a normalized form, then trusting that the form matches what the OS will actually open. The assumption that breaks: the normalization the check performs is the same one the filesystem applies. When the check resolves paths through a dynamically looked-up function, or compares raw bytes while the OS folds case and Unicode, the checked string and the opened file diverge. The check passes; the kernel opens something else.

## Where it shows up
- Permission/sandbox code calling `pathModule.resolve`, `fs.realpath` or similar via a mutable property lookup rather than a captured reference [E2](https://bugbountylibrary.com/r/h1%3A2225660.md)
- Deny/allow rules compared as raw byte strings on case-insensitive or Unicode-normalizing filesystems (APFS, NTFS) [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8xpq-cjcf-3wh9.md)
- Hand-rolled URL/query parsing (`lastIndexOf('?')` vs first `?`) feeding a path used for file access [E1](https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-21-vscode-extension-escape-vulnerability.md)
- Webview/extension configs granting `localResourceRoots` to the whole disk, so any traversal reaches everything [E1](https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-21-vscode-extension-escape-vulnerability.md)
- Any check that runs before, and separately from, the actual open call

## How to review
Identify the exact string the check validates and the exact string the OS resolves. The invariant: the checked path must be the resolved path, or the check must run on the post-resolution result. Concretely: confirm security-critical built-ins are captured in local references, not looked up on a mutable module object [E2](https://bugbountylibrary.com/r/h1%3A2225660.md); confirm path comparison uses the filesystem's equivalence rules (normalize NFC/NFD, case-fold) or compares inodes after resolution [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8xpq-cjcf-3wh9.md); confirm parsers agree with the consumer on delimiters [E1](https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-21-vscode-extension-escape-vulnerability.md). Test each equivalence class the OS supports against the rule.

## Variants seen
- Monkey-patched `path.resolve` defeats Node permission model normalization [E2](https://bugbountylibrary.com/r/h1%3A2225660.md)
- Unicode/case/ligature equivalence on APFS bypasses Deno deny rules [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8xpq-cjcf-3wh9.md)
- Parser differential in a local HTTP server plus over-broad resource roots in VSCode extensions [E1](https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-21-vscode-extension-escape-vulnerability.md)

## Why fixes fail
E2 is a regression of an earlier traversal fix (CVE-2023-30584): the patch added resolution but called it through a mutable lookup, so the fix was bypassable by reassigning the property. Fixes that add normalization without pinning the function or matching OS semantics remain bypassable.

## Impact and severity
Sandbox and permission-model escapes: reading, writing, executing or FFI-loading denied files [E2](https://bugbountylibrary.com/r/h1%3A2225660.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-8xpq-cjcf-3wh9.md); local file theft from extensions [E1](https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-21-vscode-extension-escape-vulnerability.md). Severity is high because the boundary is the OS sandbox itself. Over-broad roots [E1](https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-21-vscode-extension-escape-vulnerability.md) and mutable-lookup fixes [E2](https://bugbountylibrary.com/r/h1%3A2225660.md) widen it.

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-21-vscode-extension-escape-vulnerability.md
- E2: https://bugbountylibrary.com/r/h1%3A2225660.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-8xpq-cjcf-3wh9.md
