@asymmetric-effort/nogginlessdom's Path Traversal in matchFileSnapshot allows arbitrary file write
## Summary The `matchFileSnapshot` function in `src/assertions/snapshots.ts` accepted a `filePath` parameter with zero validation. When snapshot update mode was active (`UPDATE_SNAPSHOTS=1` or `setUpdateMode('all')`), an attacker who controls test input could write arbitrary content to any filesystem path the process has write access to, including creating intermediate directories. ## Affected Code **File:** `src/assertions/snapshots.ts`, lines 732-769 ```typescript export function matchFileSnapshot(actual: unknown, filePath: string): void { const serialized = serialize(actual); const mode = resolveUpdateMode(); const fileExists = fs.existsSync(filePath); if (!fileExists) { if (mode === 'all' || mode === 'new') { const dir = path.dirname(filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(filePath, serialized, 'utf-8'); ``` The `filePath` flows from `expect(value).toMatchFileSnapshot(filePath)` at `index.ts:1033-1035` with no sanitization, no check that the path is within an expected directory, and no symlink resolution. ## Proof of Concept ```typescript import { expect, setUpdateMode } from '@asymmetric-effort/nogginlessdom'; setUpdateMode('all'); // Writes arbitrary content to any writable path expect('malicious content').toMatchFileSnapshot('/tmp/exploit/payload.txt'); // Path traversal via relative components expect('data').toMatchFileSnapshot('../../../tmp/evil.txt'); // In CI environments, could overwrite CI config expect('injected step').toMatchFileSnapshot('/home/runner/.github/workflows/backdoor.yml'); ``` ## Impact In CI/CD environments where test files may come from untrusted pull requests, this allows writing to any writable filesystem location with directory creation. An attacker could overwrite configuration files, inject code into build artifacts, or modify CI pipeline definitions. ## Fix Fixed in commit https://github.com/asymmetric-effort/NogginLessDom/commit/785e6ac6e124d1a89b3ccf40bbd75fc8e4cb215d on `main`. The `matchFileSnapshot` function now validates that the resolved file path is within the project root directory (defaults to `process.cwd()`, configurable via optional `projectRoot` parameter). Paths that resolve outside the project directory are rejected with a descriptive error. ```typescript export function matchFileSnapshot( actual: unknown, filePath: string, projectRoot?: string, ): void { const root = projectRoot ?? process.cwd(); const resolved = path.resolve(root, filePath); if (!resolved.startsWith(root + path.sep) && resolved !== root) { throw new Error( `File snapshot path must be within the project directory: ${filePath}`, ); } // ... all subsequent file I/O uses `resolved` instead of `filePath` } ```
AI Analysis
Technical Summary
The matchFileSnapshot function in @asymmetric-effort/nogginlessdom (src/assertions/snapshots.ts) accepted an unsanitized filePath parameter. When snapshot update mode is active, this allowed arbitrary file writes to any writable path, including directory creation, due to lack of path validation or symlink resolution. The vulnerability affects versions before 0.0.22. The fix, committed on main, enforces that resolved file paths must reside within the project root directory, rejecting paths outside it with an error.
Potential Impact
An attacker who can control test inputs in environments using vulnerable versions with snapshot update mode enabled can write arbitrary files anywhere writable by the process. This can lead to overwriting or injecting malicious content into configuration files, build artifacts, or CI/CD pipeline definitions, potentially compromising build integrity and execution.
Mitigation Recommendations
A fix is available in version 0.0.22 and later, which validates that file paths are within the project root directory before writing. Users should upgrade to version 0.0.22 or later to mitigate this vulnerability. Until then, avoid enabling snapshot update mode with untrusted inputs. Patch status is confirmed fixed in commit https://github.com/asymmetric-effort/NogginLessDom/commit/785e6ac6e124d1a89b3ccf40bbd75fc8e4cb215d.
@asymmetric-effort/nogginlessdom's Path Traversal in matchFileSnapshot allows arbitrary file write
Description
## Summary The `matchFileSnapshot` function in `src/assertions/snapshots.ts` accepted a `filePath` parameter with zero validation. When snapshot update mode was active (`UPDATE_SNAPSHOTS=1` or `setUpdateMode('all')`), an attacker who controls test input could write arbitrary content to any filesystem path the process has write access to, including creating intermediate directories. ## Affected Code **File:** `src/assertions/snapshots.ts`, lines 732-769 ```typescript export function matchFileSnapshot(actual: unknown, filePath: string): void { const serialized = serialize(actual); const mode = resolveUpdateMode(); const fileExists = fs.existsSync(filePath); if (!fileExists) { if (mode === 'all' || mode === 'new') { const dir = path.dirname(filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(filePath, serialized, 'utf-8'); ``` The `filePath` flows from `expect(value).toMatchFileSnapshot(filePath)` at `index.ts:1033-1035` with no sanitization, no check that the path is within an expected directory, and no symlink resolution. ## Proof of Concept ```typescript import { expect, setUpdateMode } from '@asymmetric-effort/nogginlessdom'; setUpdateMode('all'); // Writes arbitrary content to any writable path expect('malicious content').toMatchFileSnapshot('/tmp/exploit/payload.txt'); // Path traversal via relative components expect('data').toMatchFileSnapshot('../../../tmp/evil.txt'); // In CI environments, could overwrite CI config expect('injected step').toMatchFileSnapshot('/home/runner/.github/workflows/backdoor.yml'); ``` ## Impact In CI/CD environments where test files may come from untrusted pull requests, this allows writing to any writable filesystem location with directory creation. An attacker could overwrite configuration files, inject code into build artifacts, or modify CI pipeline definitions. ## Fix Fixed in commit https://github.com/asymmetric-effort/NogginLessDom/commit/785e6ac6e124d1a89b3ccf40bbd75fc8e4cb215d on `main`. The `matchFileSnapshot` function now validates that the resolved file path is within the project root directory (defaults to `process.cwd()`, configurable via optional `projectRoot` parameter). Paths that resolve outside the project directory are rejected with a descriptive error. ```typescript export function matchFileSnapshot( actual: unknown, filePath: string, projectRoot?: string, ): void { const root = projectRoot ?? process.cwd(); const resolved = path.resolve(root, filePath); if (!resolved.startsWith(root + path.sep) && resolved !== root) { throw new Error( `File snapshot path must be within the project directory: ${filePath}`, ); } // ... all subsequent file I/O uses `resolved` instead of `filePath` } ```
CVSS v4.0
Affected software
Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.
Weaknesses
AI-Powered Analysis
Machine-generated threat intelligence
Technical Analysis
The matchFileSnapshot function in @asymmetric-effort/nogginlessdom (src/assertions/snapshots.ts) accepted an unsanitized filePath parameter. When snapshot update mode is active, this allowed arbitrary file writes to any writable path, including directory creation, due to lack of path validation or symlink resolution. The vulnerability affects versions before 0.0.22. The fix, committed on main, enforces that resolved file paths must reside within the project root directory, rejecting paths outside it with an error.
Potential Impact
An attacker who can control test inputs in environments using vulnerable versions with snapshot update mode enabled can write arbitrary files anywhere writable by the process. This can lead to overwriting or injecting malicious content into configuration files, build artifacts, or CI/CD pipeline definitions, potentially compromising build integrity and execution.
Mitigation Recommendations
A fix is available in version 0.0.22 and later, which validates that file paths are within the project root directory before writing. Users should upgrade to version 0.0.22 or later to mitigate this vulnerability. Until then, avoid enabling snapshot update mode with untrusted inputs. Patch status is confirmed fixed in commit https://github.com/asymmetric-effort/NogginLessDom/commit/785e6ac6e124d1a89b3ccf40bbd75fc8e4cb215d.
Technical Details
- Gcve Source
- db.gcve.eu
- Osv Id
- GHSA-322x-v876-g883
- Osv Schema Version
- 1.4.0
- Aliases
- []
- Ecosystems
- ["npm"]
- Database Specific Severity
- HIGH
- Cvss Version
- 4.0
Threat ID: 6a46ecb327e9c7971943c63b
Added to database: 07/02/2026, 22:56:51 UTC
Last enriched: 07/02/2026, 23:09:13 UTC
Last updated: 07/31/2026, 12:27:30 UTC
Views: 42
Community Reviews
0 reviewsCrowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.
Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.
Actions
Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.
External Links
Need more coverage?
Upgrade to Pro Console for AI refresh and higher limits.
For incident response and remediation, OffSeq services can help resolve threats faster.
Latest Threats
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.