mustflow 2.116.0 → 2.116.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/source-anchors.js +11 -0
- package/package.json +1 -1
- package/templates/default/i18n.toml +72 -6
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +37 -11
- package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/SKILL.md +477 -0
- package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/compiler-diagnostics-abi-linker-checklist.md +778 -0
- package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/compiler-generators-properties-checklist.md +501 -0
- package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/compiler-test-strategy-differential-checklist.md +498 -0
- package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/debug-symbol-symbolication-checklist.md +412 -0
- package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/ir-design-ssa-pass-pipeline-checklist.md +759 -0
- package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/miscompile-reduction-ir-checklist.md +434 -0
- package/templates/default/locales/en/.mustflow/skills/cross-platform-filesystem-safety/SKILL.md +55 -36
- package/templates/default/locales/en/.mustflow/skills/cross-platform-filesystem-safety/references/path-containment-handle-checklist.md +251 -0
- package/templates/default/locales/en/.mustflow/skills/file-upload-security-review/SKILL.md +133 -32
- package/templates/default/locales/en/.mustflow/skills/file-upload-security-review/references/file-upload-parser-ssrf-resource-checklist.md +306 -0
- package/templates/default/locales/en/.mustflow/skills/formal-verification-review/SKILL.md +310 -0
- package/templates/default/locales/en/.mustflow/skills/formal-verification-review/references/formal-concurrency-model-checking-smt-checklist.md +457 -0
- package/templates/default/locales/en/.mustflow/skills/formal-verification-review/references/formal-contracts-modeling-checklist.md +434 -0
- package/templates/default/locales/en/.mustflow/skills/formal-verification-review/references/formal-memory-bounds-ci-checklist.md +509 -0
- package/templates/default/locales/en/.mustflow/skills/fuzz-harness-review/SKILL.md +439 -0
- package/templates/default/locales/en/.mustflow/skills/fuzz-harness-review/references/fuzz-harness-campaign-checklist.md +379 -0
- package/templates/default/locales/en/.mustflow/skills/fuzz-harness-review/references/fuzz-oracle-triage-ci-checklist.md +307 -0
- package/templates/default/locales/en/.mustflow/skills/idempotency-integrity-review/SKILL.md +48 -28
- package/templates/default/locales/en/.mustflow/skills/idempotency-integrity-review/references/operation-ordering-stale-write-checklist.md +259 -0
- package/templates/default/locales/en/.mustflow/skills/input-boundary-validation-review/SKILL.md +329 -0
- package/templates/default/locales/en/.mustflow/skills/input-boundary-validation-review/references/input-boundary-security-checklist.md +319 -0
- package/templates/default/locales/en/.mustflow/skills/input-event-synchronization-review/SKILL.md +306 -0
- package/templates/default/locales/en/.mustflow/skills/input-event-synchronization-review/references/input-session-state-checklist.md +298 -0
- package/templates/default/locales/en/.mustflow/skills/input-event-synchronization-review/references/remote-input-transport-interaction-checklist.md +328 -0
- package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/SKILL.md +353 -0
- package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-diagnostics-recovery-checklist.md +267 -0
- package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-execution-closure-performance-checklist.md +428 -0
- package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-gc-verification-checklist.md +457 -0
- package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-semantics-runtime-checklist.md +391 -0
- package/templates/default/locales/en/.mustflow/skills/modal-loop-reentrancy-review/SKILL.md +294 -0
- package/templates/default/locales/en/.mustflow/skills/modal-loop-reentrancy-review/references/modal-loop-reentrancy-checklist.md +290 -0
- package/templates/default/locales/en/.mustflow/skills/modal-loop-reentrancy-review/references/nested-modal-state-lifetime-checklist.md +297 -0
- package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/SKILL.md +252 -0
- package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/references/dns-network-resolution-checklist.md +394 -0
- package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/references/language-symbol-resolution-checklist.md +282 -0
- package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/references/module-package-loader-resolution-checklist.md +352 -0
- package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/SKILL.md +103 -17
- package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/cst-ast-lowering-checklist.md +260 -0
- package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/lexer-tokenization-checklist.md +397 -0
- package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/tree-serialization-compatibility-checklist.md +164 -0
- package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/tree-traversal-rewrite-checklist.md +209 -0
- package/templates/default/locales/en/.mustflow/skills/race-condition-review/SKILL.md +68 -11
- package/templates/default/locales/en/.mustflow/skills/race-condition-review/references/race-reproduction-memory-model-checklist.md +268 -0
- package/templates/default/locales/en/.mustflow/skills/routes.toml +151 -0
- package/templates/default/locales/en/.mustflow/skills/session-handoff-integrity-review/SKILL.md +343 -0
- package/templates/default/locales/en/.mustflow/skills/session-handoff-integrity-review/references/session-auth-stream-resume-checklist.md +413 -0
- package/templates/default/locales/en/.mustflow/skills/session-handoff-integrity-review/references/session-handoff-protocol-checklist.md +485 -0
- package/templates/default/locales/en/.mustflow/skills/two-phase-transition-integrity-review/SKILL.md +267 -0
- package/templates/default/locales/en/.mustflow/skills/two-phase-transition-integrity-review/references/admission-decision-recovery-checklist.md +308 -0
- package/templates/default/locales/en/.mustflow/skills/two-phase-transition-integrity-review/references/two-phase-transition-checklist.md +229 -0
- package/templates/default/locales/en/.mustflow/skills/ui-dispatch-lifecycle-review/SKILL.md +300 -0
- package/templates/default/locales/en/.mustflow/skills/ui-dispatch-lifecycle-review/references/ui-affinity-event-loop-checklist.md +277 -0
- package/templates/default/locales/en/.mustflow/skills/ui-dispatch-lifecycle-review/references/ui-dispatch-lifecycle-checklist.md +292 -0
- package/templates/default/manifest.toml +115 -1
package/templates/default/locales/en/.mustflow/skills/cross-platform-filesystem-safety/SKILL.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
mustflow_doc: skill.cross-platform-filesystem-safety
|
|
3
3
|
locale: en
|
|
4
4
|
canonical: true
|
|
5
|
-
revision:
|
|
5
|
+
revision: 9
|
|
6
6
|
lifecycle: mustflow-owned
|
|
7
7
|
authority: procedure
|
|
8
8
|
name: cross-platform-filesystem-safety
|
|
9
|
-
description: Apply this skill when file paths, directories, symlinks, reparse points, real paths, path traversal, reserved names, null bytes, NTFS alternate data streams, Windows 8.3 short names, Windows namespace prefixes, atomic file writes, temporary files, file copies, generated outputs, clone or checkout materialization, Windows/POSIX path behavior, line endings, file permissions, durable writes, failure classification, or filesystem cleanup are created, changed, reviewed, or reported.
|
|
9
|
+
description: Apply this skill when file paths, URI path components, directories, file descriptors or handles, symlinks, hard links, reparse points, junctions, mount points, real paths, path traversal, reserved names, null bytes, NTFS alternate data streams, Windows 8.3 short names, Windows namespace prefixes, atomic file writes, temporary files, file copies, archive extraction, generated outputs, clone or checkout materialization, Windows/POSIX path behavior, TOCTOU safety, line endings, file permissions, durable writes, failure classification, or filesystem cleanup are created, changed, reviewed, or reported.
|
|
10
10
|
metadata:
|
|
11
11
|
mustflow_schema: "1"
|
|
12
12
|
mustflow_kind: procedure
|
|
@@ -26,7 +26,7 @@ metadata:
|
|
|
26
26
|
<!-- mustflow-section: purpose -->
|
|
27
27
|
## Purpose
|
|
28
28
|
|
|
29
|
-
Keep filesystem behavior safe across Windows and POSIX while preventing path traversal, symlink escapes, unsafe overwrites, stale generated output, and platform-only assumptions.
|
|
29
|
+
Keep filesystem behavior safe across Windows and POSIX while preventing path traversal, symlink escapes, hard-link aliases, reparse or mount escapes, check-use races, unsafe overwrites, stale generated output, and platform-only assumptions. Treat an opened object capability and its verified identity as the security boundary; lexical normalization or path-prefix agreement is only an early rejection signal.
|
|
30
30
|
|
|
31
31
|
<!-- mustflow-section: use-when -->
|
|
32
32
|
## Use When
|
|
@@ -37,6 +37,7 @@ Keep filesystem behavior safe across Windows and POSIX while preventing path tra
|
|
|
37
37
|
- Behavior must work on Windows and POSIX path separators, drive roots, case differences, reserved names, maximum path lengths, executable extensions, line endings, permissions, or rename semantics.
|
|
38
38
|
- Code or config serves files to a browser, preview server, dev server, test UI, static asset server, attachment endpoint, snapshot endpoint, or package artifact where a denied path, filename alias, or platform-specific path form could expose private files.
|
|
39
39
|
- A test or final report claims a path is inside the project, symlink-safe, traversal-safe, race-safe, atomic, idempotent, cleanup-safe, or cross-platform.
|
|
40
|
+
- A URL or protocol path is decoded into a filesystem path, or a queue, scanner, converter, archive extractor, or later worker reopens a path after validation.
|
|
40
41
|
|
|
41
42
|
<!-- mustflow-section: do-not-use-when -->
|
|
42
43
|
## Do Not Use When
|
|
@@ -52,9 +53,14 @@ Keep filesystem behavior safe across Windows and POSIX while preventing path tra
|
|
|
52
53
|
- Current filesystem helpers, path validation rules, symlink policy, case-sensitivity policy, write strategy, cleanup strategy, temporary-file strategy, permission strategy, and platform expectations.
|
|
53
54
|
- Expected behavior for missing paths, existing files, directories, symlinks, dangling symlinks, reparse points or junctions, path traversal, null bytes, Windows namespace prefixes, Windows reserved names, NTFS alternate data streams, Windows 8.3 short names, trailing spaces or dots, collisions, long paths, large files, and permissions errors.
|
|
54
55
|
- Path-length, filename-length, collision, staging, promotion, and cleanup expectations for clone, checkout, scaffold, install, archive, and generated-tree flows, including the deepest known entry path when available.
|
|
56
|
+
- A representation ledger from raw bytes or URI component through decoder ownership and count, Unicode and separator policy, validated segments, platform path construction, and the final filesystem sink. Record every transform after validation.
|
|
57
|
+
- A root-capability ledger: trusted root directory descriptor or handle, root owner and permissions, device and inode or volume and file identity where available, mount policy, symlink policy, hard-link policy, reparse-point policy, and the credential or namespace performing lookup.
|
|
58
|
+
- A runtime-capability ledger: operating system, filesystem, runtime and provider version, descriptor-relative or handle-relative API actually returned, supported operations, link and mount guarantees, and any platform where the helper falls back to lexical or check-then-open behavior.
|
|
59
|
+
- An operation ledger for open, create, read, write, scan, transform, rename, publish, delete, cleanup, and queued work. Record atomic flags, same-descriptor or same-handle continuity, path-only reopen points, and object identity carried between stages.
|
|
55
60
|
- Failure classification expectations for filesystem and platform errors such as Windows path length, POSIX `ENAMETOOLONG`, reserved names, case collisions, Unicode aliases, file locks, permissions, quota, cross-device moves, missing executable bits, line endings, watcher limits, and descriptor limits.
|
|
56
61
|
- Whether atomicity requires best-effort rename, same-directory temporary files on the same volume, file fsync, parent directory fsync, Windows replacement behavior, or reader-safe latest pointers.
|
|
57
62
|
- Relevant command-intent entries for tests, docs, release, and mustflow validation.
|
|
63
|
+
- Read `references/path-containment-handle-checklist.md` when untrusted paths, traversal claims, URL decoding, symlinks, hard links, junctions, mounts, TOCTOU, archive extraction, or operating-system-specific open semantics are in scope.
|
|
58
64
|
|
|
59
65
|
<!-- mustflow-section: preconditions -->
|
|
60
66
|
## Preconditions
|
|
@@ -69,6 +75,7 @@ Keep filesystem behavior safe across Windows and POSIX while preventing path tra
|
|
|
69
75
|
- Update path validation, file helpers, tests, templates, docs, and call sites needed for safe filesystem behavior.
|
|
70
76
|
- Prefer repository-local safe helpers over ad hoc path string checks.
|
|
71
77
|
- Do not rely on string prefix checks alone when symlinks, drive roots, or real paths matter.
|
|
78
|
+
- Do not treat `normalize`, `resolve`, `absolute`, `realpath`, `GetFullPathName`, or a separator-aware prefix check as proof that the object eventually opened remains below the trusted root.
|
|
72
79
|
- Do not lowercase paths as a universal containment strategy. Case-insensitive comparison may be appropriate for a specific platform boundary, but it must not collapse distinct POSIX paths or replace real containment checks.
|
|
73
80
|
- Do not accept null bytes, Windows device names, namespace bypass prefixes, alternate data streams, 8.3 short-name aliases, or platform-invalid path segments as ordinary filenames.
|
|
74
81
|
- Do not recursively delete, overwrite, or copy broad directories unless the target is resolved, bounded, and intentionally owned by the task.
|
|
@@ -78,43 +85,53 @@ Keep filesystem behavior safe across Windows and POSIX while preventing path tra
|
|
|
78
85
|
<!-- mustflow-section: procedure -->
|
|
79
86
|
## Procedure
|
|
80
87
|
|
|
81
|
-
1. Classify each path as trusted repository path,
|
|
82
|
-
2.
|
|
83
|
-
3.
|
|
84
|
-
4. Use Unicode normalization for validation only when detecting platform aliases such as superscript Windows device-name variants. Do not rewrite or persist normalized filenames unless the repository policy explicitly says so.
|
|
85
|
-
5.
|
|
86
|
-
6.
|
|
87
|
-
7.
|
|
88
|
-
8.
|
|
89
|
-
9.
|
|
90
|
-
10.
|
|
91
|
-
11.
|
|
92
|
-
12.
|
|
93
|
-
13.
|
|
94
|
-
14.
|
|
95
|
-
15.
|
|
96
|
-
16.
|
|
97
|
-
17.
|
|
98
|
-
18. For
|
|
99
|
-
19.
|
|
100
|
-
20.
|
|
101
|
-
21. For
|
|
102
|
-
22. For
|
|
103
|
-
23.
|
|
104
|
-
24.
|
|
105
|
-
25.
|
|
106
|
-
26. For
|
|
107
|
-
27.
|
|
108
|
-
28.
|
|
88
|
+
1. Classify each path as trusted repository path, untrusted protocol input, generated state, template source, package artifact, temporary file, external path, or unknown. Prefer an opaque object identifier or server-generated single filename over accepting a path hierarchy.
|
|
89
|
+
2. Build the representation ledger before changing validation. For URL-like input, parse the protocol and select the path component first, decode that component exactly once under one named owner, apply the declared Unicode and separator policy, split into segments, validate the segments, freeze the validated representation, and only then construct the platform path. Reject a second decoder or any post-validation transform that can create a separator, dot segment, NUL, device name, namespace, or alternate stream.
|
|
90
|
+
3. Reject impossible or dangerous path text early. When a pure relative path is required, reject empty, `.` and `..` segments instead of normalizing them away. Check null bytes after decoding, absolute and root-relative forms, drive-relative forms such as `C:tmp`, UNC and device namespaces, Windows device names such as `CON` or `NUL`, namespace prefixes such as `\\?\` and `\\.\`, alternate data streams using colon segments, trailing dots or spaces, and platform-invalid characters.
|
|
91
|
+
4. Use Unicode normalization for validation only when detecting platform aliases such as superscript Windows device-name variants. Do not rewrite or persist normalized filenames unless the repository policy explicitly says so. Validate for the filesystem that will consume the path, not only the upstream host.
|
|
92
|
+
5. Establish the trusted root as an already opened directory descriptor or handle when the risk requires strong containment. Record its owner, permissions, namespace, device or volume identity, and whether attackers can rename or add children below it. Do not make current working directory part of the security decision.
|
|
93
|
+
6. Use lexical normalization, separator-aware relative checks, prefix checks, and `realpath` only for early rejection, diagnostics, and low-risk trusted paths. Keep separator boundaries so partial path traversal cannot make a sibling name look like a child, but do not mistake that lexical check for proof across a later lookup, symlink, junction, reparse point, mount, hard link, or attacker-controlled parent.
|
|
94
|
+
7. On Linux where the runtime exposes it, resolve untrusted paths relative to the trusted root descriptor with `openat2`. Choose `RESOLVE_BENEATH` or `RESOLVE_IN_ROOT` deliberately, add `RESOLVE_NO_MAGICLINKS` explicitly when magic links are forbidden, add `RESOLVE_NO_XDEV` when mount crossings are forbidden, and add `RESOLVE_NO_SYMLINKS` only when all symlinks are forbidden. Do not present `O_NOFOLLOW` as an all-component defense; it affects only the final component.
|
|
95
|
+
8. Prefer an audited runtime root-capability API when it preserves the needed operation on the actual platform. Go `os.Root` or `os.OpenInRoot` can provide root-relative operations, but its guarantees vary by target: it does not block Unix mount traversal, and targets without descriptor-relative support may retain check-use limitations. Java `SecureDirectoryStream` is useful only when the installed filesystem provider and operating system actually return that interface. Otherwise use an audited helper that walks one segment at a time relative to directory descriptors, opens intermediate directories with directory and no-follow constraints, and never reconstructs an absolute path mid-walk. Record the runtime, provider, filesystem, supported operation, and fallback limitation instead of claiming equivalence to `openat2`.
|
|
96
|
+
9. On Windows, prefer an opaque single filename below an application-owned directory. Reject drive-relative, root-relative, UNC, device-namespace, alternate-stream, reserved-device, trailing-dot, trailing-space, and mixed-separator aliases before opening. Open a HANDLE with the intended reparse behavior, inspect the opened object's reparse tag, final path, volume identity, and file identity where the API and runtime expose them, and use that same HANDLE for the operation. Do not claim that `GetFullPathName`, a final path string, or ordinary `CreateFile` behavior is a Windows equivalent of `openat2`.
|
|
97
|
+
10. Reject reparse points and junctions by default in attacker-writable trees unless the product has an explicit allow policy and can verify the opened target. For privileged Windows services, check whether process-level reparse traversal mitigations belong at startup; if the code cannot enable and verify them, report the remaining risk.
|
|
98
|
+
11. Open first under the path-resolution policy, inspect the opened object with `fstat` or the corresponding handle metadata, then read, write, scan, transform, or publish through that same descriptor or handle. `exists`, `access`, `lstat`, `realpath`, or metadata-check followed by an unrelated `open` is a time-of-check to time-of-use gap.
|
|
99
|
+
12. Treat hard links separately from symlinks. No-follow flags do not stop a hard link from naming an existing file. Where the policy forbids shared identities, verify device and inode or volume and file identity, consider link count as one signal, and ensure attackers cannot create links in the storage directory. Do not claim link-count checks alone prove ownership.
|
|
100
|
+
13. Treat mount boundaries separately from path boundaries. Use `RESOLVE_NO_XDEV`, mount identity, volume identity, or an equivalent owned-storage invariant when mount or bind-mount crossings are forbidden. State explicit compatibility exceptions for legitimate mount layouts.
|
|
101
|
+
14. Create new objects through the trusted parent descriptor or handle with one validated final segment and an atomic exclusive-create primitive such as `O_CREAT|O_EXCL` or `CREATE_NEW`. Do not precheck existence and then create.
|
|
102
|
+
15. For scanners, converters, antivirus, image processors, and other path-only tools, materialize an immutable application-owned staging object first. Bind the result to an object identifier, digest, size, and generation, and reject any stage that silently reopens an attacker-controlled path.
|
|
103
|
+
16. For queued work, store an immutable object identity, digest, and generation rather than a previously validated path. Reauthorize and revalidate the current object version at execution time; a queue delay turns a path string into stale authority.
|
|
104
|
+
17. For archive extraction, parse and validate the complete entry set before the first write when the format and bounded input permit it. Build one destination graph that rejects duplicate and platform-alias names, file-versus-directory prefix conflicts such as `a` and `a/b`, separator and Unicode collisions, and order-dependent link traversal. Carry the validated entry object into extraction instead of reparsing the raw name. Accept only regular files and directories by default; reject symlink, hard-link, device, FIFO, socket, reparse, and other special entries unless an explicit product contract proves them safe. Ignore archive-supplied owner, group, mode, setuid, setgid, sticky, ACL, xattr, capability, and timestamp metadata unless each field is allowlisted, and create files with service-owned permissions. Count actual emitted bytes, logical file size, allocated temporary storage, sparse extents, entry count, directories, depth, name length, compression work, nested archives, and elapsed time under one shared budget. Create every entry through the trusted root capability and use `file-upload-security-review` for the surrounding upload, parser, storage, serving, and cleanup lifecycle.
|
|
105
|
+
18. For externally sourced trees, use a `preflight -> dangerous operation -> classifier -> safe cleanup` pipeline. Estimate the materialized path budget before writing, including destination root, project directory, generated subdirectories, deepest known repository or archive entry, Windows path-length behavior, POSIX path and component limits, byte limits, case collisions, reserved names, and safety headroom.
|
|
106
|
+
19. For Git clone and checkout materialization, prefer an app-owned staging directory and no-checkout or metadata-first flow when feasible. Inspect repository entries before checkout, check them against the final destination, then promote the result only after success. Do not delete a user-selected final destination when checkout fails.
|
|
107
|
+
20. For Windows Git checkout or clone materialization, prefer a per-invocation `core.longpaths=true` setting when product code invokes Git. Do not mutate global Git config from application code unless the user explicitly chose that setup action. Long-path support still depends on operating-system, Git, filesystem, and downstream tool behavior, so checkout failures must remain classifiable.
|
|
108
|
+
21. For symlink-heavy repositories on Windows, detect whether checkout produced real links or plain-text symlink stubs before running build logic. Report missing Developer Mode, `core.symlinks`, or native symlink support as an environment prerequisite; do not silently replace file symlinks with junctions or copies unless the repository contract explicitly supports that compatibility mode.
|
|
109
|
+
22. For POSIX, do not assume that forward slashes make paths safe. Check `ENAMETOOLONG`, byte-based per-component name limits, mount permissions, executable bits, case-sensitive import paths, symlink loops, file descriptor limits, watcher limits, quota, and cross-device rename behavior.
|
|
110
|
+
23. Check case behavior explicitly. Windows and many macOS volumes preserve case but compare case-insensitively by default; POSIX commonly compares case-sensitively. State whether the code preserves spelling, rejects conflicting names, or relies on the host filesystem.
|
|
111
|
+
24. Check collisions before materializing Git trees, archives, generated files, uploaded names, or dependency trees. Include case-only collisions, Unicode normalization aliases, reserved Windows names with extensions, trailing dot or space aliases, duplicate archive entries, and byte-limit collisions from multibyte names.
|
|
112
|
+
25. Classify filesystem failures before generic network, auth, or unknown failures. Use stable categories such as `path_too_long`, `filename_too_long`, `byte_limit_exceeded`, `invalid_path`, `reserved_name`, `case_collision`, `unicode_collision`, `symlink_escape`, `mount_escape`, `identity_mismatch`, `permission_denied`, `file_locked`, `cross_device_move`, `disk_full_or_quota`, `executable_bit_missing`, `line_ending_mismatch`, `watcher_limit`, and `descriptor_limit`.
|
|
113
|
+
26. For writes, prefer same-directory temporary-file then rename or replace behavior when readers may observe the file. Keep the temporary file on the same volume, use unpredictable names, least-privilege creation permissions, and safe no-follow writes when the project already has that helper. For hostile tree materialization, use a new attacker-nonwritable staging directory with private Unix permissions or a dedicated Windows ACL, then publish only the verified tree.
|
|
114
|
+
27. Treat atomic writes as platform-specific. POSIX rename semantics, Windows replacement behavior, cross-filesystem moves, network filesystems, FUSE or overlay filesystems, fsync availability, and directory fsync support differ; report best-effort guarantees honestly.
|
|
115
|
+
28. When durable writes matter, include the full durability sequence where the platform supports it: write the temporary file, flush the file data, close it, rename or replace it, then flush the parent directory entry. If parent directory fsync is unavailable, downgrade the durability claim.
|
|
116
|
+
29. For copies and updates, keep the source and destination descriptors open through the operation where feasible. Do not report symlink safety if the final write or later consumer can still follow a changed link or reopen a mutable path.
|
|
117
|
+
30. Treat rename and delete as name-to-parent operations with their own races. Strong claims require an attacker-nonwritable parent or a platform primitive that binds the operation to the intended parent and object identity. Prefer atomic quarantine into application-owned storage before destructive cleanup; do not claim that a prior opened-handle check alone makes a later path-based delete safe.
|
|
118
|
+
31. For host environment limitations such as long-path registry flags, Developer Mode, WSL metadata mounts, Linux inotify/sysctl limits, Docker Desktop volume backend, network filesystems, or antivirus locks, classify and report the environment prerequisite. Do not perform privileged host repair from ordinary file logic.
|
|
119
|
+
32. Distinguish disk and quota errors from watch or descriptor exhaustion. In a watcher or scanner path, `ENOSPC` may mean an inotify watch limit rather than a full disk, and `EMFILE` or similar failures may indicate a per-process or per-user file-descriptor limit.
|
|
120
|
+
33. For deletes and cleanup, narrow the target to app-owned staging or generated state. Preserve bounded diagnostic evidence first, then revalidate the operation at the destructive boundary. Never remove the user-selected destination that the operation was supposed to populate.
|
|
121
|
+
34. For scans, bound recursion, generated/vendor exclusions, file size, symlink, hard-link, reparse-point and mount traversal, loop detection, maximum path length, depth, entry count, and total bytes.
|
|
122
|
+
35. Keep path output stable for users and automation. Report repository-relative display paths separately from security identities; never reuse a display path as authorization.
|
|
123
|
+
36. Add focused tests for decode order and double decoding, NUL after decode, dot segments, mixed separators, drive-relative and namespace forms, alias collisions, middle and final symlink swaps, hard links, bind mounts, junctions and reparse points, exclusive-create collisions, same-handle identity, queued stale paths, destructive-operation races, archive order attacks, file-directory prefix conflicts, metadata restoration attempts, sparse logical-size exhaustion, runtime-provider fallback, and unsupported-filesystem behavior.
|
|
109
124
|
|
|
110
125
|
<!-- mustflow-section: postconditions -->
|
|
111
126
|
## Postconditions
|
|
112
127
|
|
|
113
|
-
-
|
|
114
|
-
-
|
|
128
|
+
- The chain from raw representation through one decoder, immutable validated segments, trusted root capability, opened object identity, and same-descriptor or same-handle operation is explicit.
|
|
129
|
+
- Runtime and provider capability claims identify the actual platform implementation and do not silently promote lexical or check-then-open fallbacks to race-resistant guarantees.
|
|
130
|
+
- Path boundaries, invalid-name policy, case policy, symlink, hard-link, reparse-point, junction, and mount policy, write strategy, cleanup strategy, durability expectations, and platform assumptions are explicit.
|
|
131
|
+
- Clone, checkout, scaffold, install, extraction, and generated-tree flows have preflight, whole-entry collision mapping, metadata policy, staging, promotion, path-length, logical and emitted-byte limits, symlink-stub, collision, diagnostic-preservation, cleanup, and failure-taxonomy policies.
|
|
115
132
|
- Host setting prerequisites are reported without unapproved registry, global config, WSL, sysctl, Docker Desktop, antivirus, or shell-profile mutation.
|
|
116
133
|
- Dangerous file operations are bounded to known repository-owned or generated locations.
|
|
117
|
-
- Atomicity and race-safety claims are scoped to what the current helpers and
|
|
134
|
+
- Atomicity, containment, identity, and race-safety claims are scoped to what the current helpers, kernel, runtime, and filesystem can actually guarantee.
|
|
118
135
|
- Any untested platform behavior is reported as remaining risk instead of claimed safe.
|
|
119
136
|
|
|
120
137
|
<!-- mustflow-section: verification -->
|
|
@@ -135,6 +152,7 @@ Use release checks when template files, package artifacts, or installed workflow
|
|
|
135
152
|
## Failure Handling
|
|
136
153
|
|
|
137
154
|
- If root containment is unclear, stop before writing or deleting and report the ambiguous path owner.
|
|
155
|
+
- If validation and use cannot share an opened descriptor, handle, or immutable object identity, fail closed for hostile paths or report the exact reopen race.
|
|
138
156
|
- If the platform cannot prove symlink-safe behavior, fail closed or document the exact remaining gap.
|
|
139
157
|
- If atomic replace, file fsync, parent directory fsync, no-follow open, or final-target verification is not available on the platform, downgrade the claim to best-effort and keep the write boundary narrow.
|
|
140
158
|
- If Unicode normalization, Windows namespace prefixes, alternate data streams, 8.3 short names, or reparse points could change the effective target, fail closed or report the exact unhandled path class.
|
|
@@ -148,8 +166,9 @@ Use release checks when template files, package artifacts, or installed workflow
|
|
|
148
166
|
|
|
149
167
|
- Filesystem surface reviewed
|
|
150
168
|
- Path trust classes, invalid-name handling, case policy, and root boundary
|
|
151
|
-
-
|
|
152
|
-
-
|
|
169
|
+
- Decode and representation ledger; trusted root capability; opened-object identity; same-descriptor or same-handle continuity
|
|
170
|
+
- Null byte, reserved-name, Unicode normalization, namespace prefix, alternate data stream, 8.3 short-name, symlink, hard-link, mount, reparse-point, traversal, race, atomic write, durability, permission, copy, queue, delete, scan, and cleanup decisions
|
|
171
|
+
- Clone, checkout, scaffold, install, extraction, whole-entry collision graph, archive metadata, sparse-file budget, runtime capability, preflight, staging, promotion, path-length, collision, failure-taxonomy, and diagnostic-preservation decisions
|
|
153
172
|
- Host-setting prerequisites reported or deferred
|
|
154
173
|
- Windows/POSIX assumptions and skipped platform checks
|
|
155
174
|
- Tests or fixtures added or reused
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Path Containment and Opened-Object Checklist
|
|
2
|
+
|
|
3
|
+
Use this reference when a filesystem boundary accepts untrusted names, decodes URL components, crosses process or queue stages, extracts archives, or claims resistance to traversal, links, mounts, or check-use races.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
1. Security pipeline
|
|
8
|
+
2. Representation and decode ledger
|
|
9
|
+
3. Pure-relative segment policy
|
|
10
|
+
4. Windows lexical hazards
|
|
11
|
+
5. Root capability and object identity
|
|
12
|
+
6. Linux resolution policy
|
|
13
|
+
7. POSIX fallback boundaries
|
|
14
|
+
8. Windows HANDLE and reparse policy
|
|
15
|
+
9. Hard-link and mount identity
|
|
16
|
+
10. TOCTOU operation matrix
|
|
17
|
+
11. Creation, staging, publication, deletion, and queues
|
|
18
|
+
12. Archive extraction
|
|
19
|
+
13. Test matrix
|
|
20
|
+
14. Primary anchors
|
|
21
|
+
|
|
22
|
+
## 1. Security Pipeline
|
|
23
|
+
|
|
24
|
+
Use this order for hostile input:
|
|
25
|
+
|
|
26
|
+
`raw bytes -> protocol parse -> select one path component -> strict decode once -> Unicode and separator policy -> segment validation -> immutable relative representation -> lookup below trusted root -> validate opened object -> operate through the same descriptor or handle`
|
|
27
|
+
|
|
28
|
+
Every arrow needs one owner. A second decoder, normalizer, separator conversion, case fold, Unicode rewrite, environment expansion, archive library, shell, or downstream tool after validation can create a new path language and invalidate the earlier decision.
|
|
29
|
+
|
|
30
|
+
Prefer an opaque object identifier and server-generated storage name. Accept a hierarchy only when the product actually needs user-selected hierarchy.
|
|
31
|
+
|
|
32
|
+
## 2. Representation and Decode Ledger
|
|
33
|
+
|
|
34
|
+
Record:
|
|
35
|
+
|
|
36
|
+
| Stage | Questions |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| Transport | Are inputs bytes, a URL, a URL path component, form data, JSON, a header, or an archive entry? |
|
|
39
|
+
| Parser | Which parser owns component boundaries? Is a whole URL ever decoded before parsing? |
|
|
40
|
+
| Decoder | Which component is decoded, how many times, and how are malformed sequences handled? |
|
|
41
|
+
| Unicode | Is normalization used only for alias detection, or does it rewrite the stored name? |
|
|
42
|
+
| Separators | Which characters become separators on the final sink platform? Can a later layer reinterpret `/`, `\\`, `%2f`, `%5c`, or lookalikes? |
|
|
43
|
+
| Segments | Are empty, `.`, `..`, NUL, absolute, rooted, namespace, stream, and reserved segments rejected? |
|
|
44
|
+
| Construction | Is the validated immutable segment list combined only with a trusted root capability? |
|
|
45
|
+
| Sink | Which kernel, filesystem, container namespace, network share, archive library, or Windows API performs the final lookup? |
|
|
46
|
+
|
|
47
|
+
Do not decode the entire URI before locating its components. Do not validate encoded text and then decode it. Do not decode repeatedly until the text stops changing.
|
|
48
|
+
|
|
49
|
+
## 3. Pure-Relative Segment Policy
|
|
50
|
+
|
|
51
|
+
For an untrusted path below a fixed root:
|
|
52
|
+
|
|
53
|
+
- require a non-empty relative segment sequence;
|
|
54
|
+
- reject empty segments when duplicate separators are not part of the contract;
|
|
55
|
+
- reject `.` and `..` rather than repairing them with normalization;
|
|
56
|
+
- reject NUL after decoding;
|
|
57
|
+
- reject absolute, root-relative, drive-relative, UNC, and device-namespace forms;
|
|
58
|
+
- reject a segment that the final filesystem aliases to a reserved or different name;
|
|
59
|
+
- freeze the accepted segment sequence so downstream layers cannot reinterpret raw input;
|
|
60
|
+
- keep display spelling separate from the object identity used for authorization.
|
|
61
|
+
|
|
62
|
+
Lexical rejection reduces attack surface. It does not replace kernel-constrained lookup.
|
|
63
|
+
|
|
64
|
+
## 4. Windows Lexical Hazards
|
|
65
|
+
|
|
66
|
+
Check the final Windows sink for:
|
|
67
|
+
|
|
68
|
+
- both slash directions as potential separators;
|
|
69
|
+
- drive-absolute paths such as `C:\\x` and drive-relative paths such as `C:x`;
|
|
70
|
+
- root-relative paths such as `\\x`;
|
|
71
|
+
- UNC shares and device or extended namespaces such as `\\\\server\\share`, `\\\\?\\`, and `\\\\.\\`;
|
|
72
|
+
- NTFS alternate data streams introduced by colon syntax;
|
|
73
|
+
- reserved device names, including device names followed by extensions and documented superscript-digit aliases;
|
|
74
|
+
- trailing spaces and periods that Win32 or shell layers may trim or alias;
|
|
75
|
+
- short 8.3 aliases when the volume generates them;
|
|
76
|
+
- case and Unicode aliases under the actual volume policy;
|
|
77
|
+
- reparse points, junctions, mount folders, and volume changes;
|
|
78
|
+
- final consumer APIs that may apply different normalization or namespace rules.
|
|
79
|
+
|
|
80
|
+
`GetFullPathName` computes a path string. It does not freeze the directory tree or prove what a later open reaches.
|
|
81
|
+
|
|
82
|
+
## 5. Root Capability and Object Identity
|
|
83
|
+
|
|
84
|
+
Treat the trusted root as a capability, not a string:
|
|
85
|
+
|
|
86
|
+
- open the root directory before processing hostile names;
|
|
87
|
+
- keep the root descriptor or HANDLE alive for the operation;
|
|
88
|
+
- record which principal and mount or volume namespace opened it;
|
|
89
|
+
- ensure attackers cannot replace the root or mutate its parent;
|
|
90
|
+
- resolve children relative to that root where the platform supports it;
|
|
91
|
+
- inspect the opened target rather than trusting the requested spelling;
|
|
92
|
+
- carry the opened descriptor, HANDLE, or immutable object identity into later stages.
|
|
93
|
+
|
|
94
|
+
Useful identity signals include POSIX device and inode, mount identity, Windows volume serial or volume identity, file ID, object type, reparse tag, and final path from an already opened HANDLE. No one signal is universally sufficient; select the set that proves the repository's policy.
|
|
95
|
+
|
|
96
|
+
## 6. Linux Resolution Policy
|
|
97
|
+
|
|
98
|
+
When Linux `openat2` is available through the runtime or an audited native helper, choose resolution flags by policy:
|
|
99
|
+
|
|
100
|
+
| Policy | Resolution decision |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| A relative path must not escape the root | Resolve relative to the root `dirfd` with `RESOLVE_BENEATH`. |
|
|
103
|
+
| Absolute-looking input and absolute symlinks should be scoped as if the root were `/` | Consider `RESOLVE_IN_ROOT`; do not combine its different semantics with a `BENEATH` claim. |
|
|
104
|
+
| Magic links are forbidden | Add `RESOLVE_NO_MAGICLINKS` explicitly. Do not rely on another flag's current incidental behavior. |
|
|
105
|
+
| All symlinks are forbidden | Add `RESOLVE_NO_SYMLINKS`; note that this also forbids legitimate symlink layouts. |
|
|
106
|
+
| Mount and bind-mount crossings are forbidden | Add `RESOLVE_NO_XDEV`; document legitimate mount compatibility exceptions. |
|
|
107
|
+
| Only the final component must not be a symlink | `O_NOFOLLOW` can enforce that narrower rule, but not all-component safety. |
|
|
108
|
+
|
|
109
|
+
Handle `EAGAIN`, `EXDEV`, `ELOOP`, unsupported-kernel behavior, and runtime wrapper gaps explicitly. Bound retries for race-related `EAGAIN`; never fall back silently to an unconstrained absolute open.
|
|
110
|
+
|
|
111
|
+
## 7. POSIX Fallback Boundaries
|
|
112
|
+
|
|
113
|
+
If `openat2` is unavailable:
|
|
114
|
+
|
|
115
|
+
1. Start from an opened trusted root directory descriptor.
|
|
116
|
+
2. Walk one validated segment at a time with descriptor-relative operations.
|
|
117
|
+
3. Open intermediate components as directories and reject symlink following.
|
|
118
|
+
4. Keep the current directory descriptor alive until the next descriptor is secured.
|
|
119
|
+
5. Apply the final operation relative to the verified parent descriptor.
|
|
120
|
+
6. Inspect the opened object and operate through that same descriptor.
|
|
121
|
+
|
|
122
|
+
An audited fallback still needs tests for renames, mount changes, network filesystems, FUSE, overlay filesystems, and runtime flag support. A language runtime that only exposes `realpath` plus path-based `open` cannot honestly claim the same boundary.
|
|
123
|
+
|
|
124
|
+
### Runtime root-capability APIs
|
|
125
|
+
|
|
126
|
+
Use runtime helpers only after proving what the deployed platform returns:
|
|
127
|
+
|
|
128
|
+
| Runtime API | Useful boundary | Required caveat |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| Go `os.Root` or `os.OpenInRoot` | Root-relative file operations with traversal-resistant behavior on supported targets. | Record the Go version and target. Unix mount and bind-mount traversal is not blocked; GOOS targets without descriptor-relative primitives can retain TOCTOU limits; WASI inherits implementation quality. |
|
|
131
|
+
| Java `SecureDirectoryStream` | Relative open, attribute, move, and delete operations through an open directory stream, with `NOFOLLOW_LINKS` where specified. | Support depends on the operating system and filesystem provider. Check that `Files.newDirectoryStream` actually returns `SecureDirectoryStream`; do not cast or claim support blindly. |
|
|
132
|
+
| High-level path helper only | Lexical rejection and diagnostics. | `normalize`, `realpath`, `abspath`, or prefix comparison does not become a root capability merely because the runtime documents it as safe for ordinary paths. |
|
|
133
|
+
|
|
134
|
+
For every wrapper, inventory open, exclusive create, mkdir, rename, delete, stat, and link behavior separately. A wrapper that safely opens files may still lack a parent-bound rename or delete primitive.
|
|
135
|
+
|
|
136
|
+
## 8. Windows HANDLE and Reparse Policy
|
|
137
|
+
|
|
138
|
+
Windows does not have a drop-in `openat2` equivalent. Keep the claim narrow:
|
|
139
|
+
|
|
140
|
+
1. Prefer an application-owned directory whose parents are not attacker-writable.
|
|
141
|
+
2. Prefer one server-generated child name rather than a user hierarchy.
|
|
142
|
+
3. Reject lexical namespaces, streams, rooted forms, separators, reserved aliases, and trailing-dot or trailing-space forms before opening.
|
|
143
|
+
4. Open a HANDLE with the access, sharing, creation disposition, and reparse behavior intended by the policy.
|
|
144
|
+
5. Inspect metadata from that opened HANDLE: object type, attributes and reparse tag, final path, volume identity, and file identity where available.
|
|
145
|
+
6. Reject reparse points by default in an untrusted tree unless the product explicitly follows and verifies them.
|
|
146
|
+
7. Use the same HANDLE for I/O. Do not validate the HANDLE and then reopen the original path.
|
|
147
|
+
8. For creation, use an atomic exclusive disposition such as `CREATE_NEW`; do not call an existence check first.
|
|
148
|
+
|
|
149
|
+
Opening a reparse point itself and opening its target are different operations. The implementation must state which object it inspects and which object it later uses.
|
|
150
|
+
|
|
151
|
+
## 9. Hard-Link and Mount Identity
|
|
152
|
+
|
|
153
|
+
No-follow policies address path redirection through symbolic links or reparse points. They do not stop a hard link from naming the same underlying file.
|
|
154
|
+
|
|
155
|
+
For storage that must not share identities with outside objects:
|
|
156
|
+
|
|
157
|
+
- keep the storage directory non-writable by attackers;
|
|
158
|
+
- compare device and inode or volume and file identity where a known expected object exists;
|
|
159
|
+
- use link count only as a warning or policy signal, not a universal proof;
|
|
160
|
+
- control who can create links and where;
|
|
161
|
+
- use a private staging filesystem or object store when ownership cannot be established.
|
|
162
|
+
|
|
163
|
+
Mounts and bind mounts can redirect a lexically contained path into a different filesystem. Use a no-cross-device resolution policy or verify mount or volume identity when that crossing is forbidden. Be explicit when container, Kubernetes, WSL, network-share, or application layouts require legitimate crossings.
|
|
164
|
+
|
|
165
|
+
## 10. TOCTOU Operation Matrix
|
|
166
|
+
|
|
167
|
+
| Weak sequence | Safer contract |
|
|
168
|
+
| --- | --- |
|
|
169
|
+
| `exists -> open` | Attempt the intended open directly and classify the result. |
|
|
170
|
+
| `lstat -> open` | Open under the resolution policy, inspect the opened object, use the same descriptor. |
|
|
171
|
+
| `realpath -> startsWith -> open` | Resolve below the trusted root capability and keep the returned descriptor or HANDLE. |
|
|
172
|
+
| `scan(path) -> publish(path)` | Scan an immutable staging object and publish that exact object or verified digest and generation. |
|
|
173
|
+
| `validate(path) -> enqueue(path)` | Enqueue immutable object ID, digest, size, and generation; reauthorize on execution. |
|
|
174
|
+
| `validate -> create` | Exclusive create through the trusted parent descriptor or HANDLE. |
|
|
175
|
+
| `open -> close -> delete(path)` | Quarantine atomically into attacker-nonwritable storage, or use a parent-and-identity-bound delete primitive where available. |
|
|
176
|
+
|
|
177
|
+
Shortening the time window is not a proof. The design should remove the second name lookup or bind it to the same trusted parent and object identity.
|
|
178
|
+
|
|
179
|
+
## 11. Creation, Staging, Publication, Deletion, and Queues
|
|
180
|
+
|
|
181
|
+
- Create below a trusted parent with exactly one validated final segment and atomic exclusivity.
|
|
182
|
+
- Use private, least-privilege, unpredictable staging names on the same filesystem when same-filesystem atomic promotion is required.
|
|
183
|
+
- Feed scanners and converters an opened descriptor or immutable staging object. If a tool accepts only paths, make that path application-owned and non-replaceable by the attacker.
|
|
184
|
+
- Bind scan and transform results to a digest, size, object ID, and generation.
|
|
185
|
+
- Publish by atomic same-filesystem rename or replacement only when the target platform and filesystem contract supports the claimed reader behavior.
|
|
186
|
+
- Do not claim cross-filesystem copy-and-delete is atomic.
|
|
187
|
+
- Treat deletion and rename as separate security-sensitive operations. A verified read handle does not automatically authorize a later path-based delete.
|
|
188
|
+
- Put immutable object identity in queues and receipts. A pathname is a mutable locator, not durable authority.
|
|
189
|
+
|
|
190
|
+
## 12. Archive Extraction
|
|
191
|
+
|
|
192
|
+
Before the first write, parse the complete bounded entry set when feasible and build one immutable extraction plan. Reject:
|
|
193
|
+
|
|
194
|
+
- duplicate raw or normalized destinations;
|
|
195
|
+
- case, Unicode, separator, reserved-name, trailing-dot, trailing-space, and 8.3 aliases under the final consumer platform;
|
|
196
|
+
- file-versus-directory prefix conflicts such as a regular file `a` plus `a/b`;
|
|
197
|
+
- an entry whose type or link target changes the meaning of a later entry;
|
|
198
|
+
- undecodable or ambiguous names instead of repairing them;
|
|
199
|
+
- a plan whose own entry count, name bytes, or graph size exceeds budget.
|
|
200
|
+
|
|
201
|
+
Carry the validated entry object into extraction. Do not validate one parsed name and ask another library layer to parse the raw name again.
|
|
202
|
+
|
|
203
|
+
For every planned entry:
|
|
204
|
+
|
|
205
|
+
- parse the archive format once and inspect the declared entry type;
|
|
206
|
+
- reject absolute, rooted, drive-relative, namespace, stream, empty, `.` and `..` segment forms;
|
|
207
|
+
- apply final-platform separator and alias rules;
|
|
208
|
+
- reject duplicate names plus case, Unicode, reserved-name, trailing-dot, trailing-space, and 8.3 collisions;
|
|
209
|
+
- reject symlink, hard-link, device, FIFO, socket, reparse, and other special entries unless the product has an explicit safe policy;
|
|
210
|
+
- create directories and files through the trusted extraction root capability;
|
|
211
|
+
- use atomic exclusive creation and reject a destination that already exists;
|
|
212
|
+
- never extract first and inspect later in an attacker-visible destination;
|
|
213
|
+
- ignore archive-supplied uid, gid, owner names, mode, setuid, setgid, sticky bits, ACLs, xattrs, capabilities, and timestamps unless each field is explicitly required and safely allowlisted;
|
|
214
|
+
- create with service-owned permissions inside a fresh attacker-nonwritable staging directory;
|
|
215
|
+
- enforce entry count, directory count, name length, depth, actual total emitted bytes, per-entry bytes, logical file size, allocated temporary storage, sparse extents, compression work, CPU or time, and nested-archive budgets;
|
|
216
|
+
- publish only a fully verified app-owned staging tree.
|
|
217
|
+
|
|
218
|
+
Treat library filters and non-local-path warnings as versioned defense in depth. Pin the runtime and archive API behavior, set security options explicitly where available, and keep the application entry-type, collision, root-capability, metadata, and resource policies independent of library defaults.
|
|
219
|
+
|
|
220
|
+
## 13. Test Matrix
|
|
221
|
+
|
|
222
|
+
Cover the strongest claim with deterministic tests and platform-specific integration tests where possible:
|
|
223
|
+
|
|
224
|
+
- percent-encoded separators, dot segments, malformed encoding, double decoding, and NUL after decoding;
|
|
225
|
+
- mixed separators, `C:relative`, root-relative, UNC, device namespaces, alternate streams, reserved names, trailing spaces or dots, short aliases, case and Unicode collisions;
|
|
226
|
+
- a symlink in a middle component, final-component symlink, dangling link, loop, magic link, junction, reparse point, bind mount, and volume crossing;
|
|
227
|
+
- hard-link identity and link-count policy;
|
|
228
|
+
- archive entry-order swaps, file-directory prefix conflicts, duplicate parser views, metadata restoration attempts, and sparse logical-size exhaustion;
|
|
229
|
+
- attacker swaps a component between validation and open;
|
|
230
|
+
- attacker swaps a path after enqueue, scan, or transform;
|
|
231
|
+
- exclusive-create collision and attacker-controlled parent;
|
|
232
|
+
- opened-object identity remains constant through read, scan, transform, and publish;
|
|
233
|
+
- delete or rename races and quarantine behavior;
|
|
234
|
+
- network filesystem, FUSE, overlay, WSL, or unsupported-runtime behavior is rejected or reported rather than silently downgraded.
|
|
235
|
+
- Go or Java runtime/provider fallback is detected and the claim is narrowed instead of silently using path-only operations.
|
|
236
|
+
|
|
237
|
+
Do not invent success-rate, timing, or race-frequency thresholds. A single permitted counterexample falsifies a universal containment or race-free claim.
|
|
238
|
+
|
|
239
|
+
## 14. Primary Anchors
|
|
240
|
+
|
|
241
|
+
- [RFC 3986: URI generic syntax](https://www.rfc-editor.org/rfc/rfc3986.html) for component boundaries, percent encoding, and dot-segment semantics.
|
|
242
|
+
- [Linux `openat2(2)`](https://man7.org/linux/man-pages/man2/openat2.2.html) for descriptor-relative resolution and `RESOLVE_*` behavior.
|
|
243
|
+
- [Microsoft: Naming Files, Paths, and Namespaces](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file) for Windows naming, namespaces, reserved names, separators, and 8.3 aliases.
|
|
244
|
+
- [Microsoft: `CreateFileW`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew) for HANDLE creation, creation dispositions, and reparse behavior.
|
|
245
|
+
- [Microsoft: `GetFinalPathNameByHandleW`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew) for inspecting the final path of an opened HANDLE.
|
|
246
|
+
- [Microsoft: `GetFileInformationByHandleEx`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandleex) for opened-object metadata classes available to the implementation.
|
|
247
|
+
- [CWE-367](https://cwe.mitre.org/data/definitions/367.html) for the check-use race class and why shortening a race window is not elimination.
|
|
248
|
+
- [Go: traversal-resistant file APIs](https://go.dev/blog/osroot) and [`os.Root`](https://pkg.go.dev/os#Root) for runtime root-relative operations and documented target-specific caveats.
|
|
249
|
+
- [Java `SecureDirectoryStream`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/nio/file/SecureDirectoryStream.html) for provider-dependent relative operations through an open directory stream.
|
|
250
|
+
- [Python `tarfile`](https://docs.python.org/3/library/tarfile.html) and [`zipfile`](https://docs.python.org/3/library/zipfile.html) for archive entry types, metadata, sparse members, extraction-filter version changes, and caller-owned `zipfile.Path` validation.
|
|
251
|
+
- [Go `archive/zip`](https://pkg.go.dev/archive/zip) for the current opt-in `zipinsecurepath` non-local-name behavior; do not treat a possible future default as current policy.
|