Repository navigation
fix(producer): isPathInside accepts children whose names start with two dots - #5834
Conversation
jrusso1020
left a comment
There was a problem hiding this comment.
Reviewed at d6b2a26c. Approving. This doesn't loosen containment. Both inputs go through resolve() first, so relative() only emits .. as whole leading segments. It can't produce ..foo as a parent reference. The new check rejects .. followed by a separator or the end of the string, which is exactly that set, and the absolute-path check still rejects a different drive. Matching either separator keeps win32 correct. On POSIX it only gets stricter, for a name that contains a literal backslash. The tests keep ../secret.txt, /, the sibling-prefix case and win32 ..\, and the new ..assets cases fail on main.
One small thing inline: the new constant sits between the JSDoc and isPathInside in assetPaths.ts, so the doc comment now documents the constant.
Not for this PR, but worth knowing: about 18 other sites repeat the same rel.startsWith("..") check, for example cli/src/utils/pathArgs.ts, core/src/projects.ts, engine/src/services/audioMixer.ts and studio-server/src/helpers/projectSignature.ts. They all have the same ..name false negative, and a follow-up could point them at this helper.
Need: yes, the bug is still on main · Size: ok · Reuse: fixes the two existing helpers instead of adding a third · Simpler: already minimal; the shared cleanup belongs in a follow-up
— Rames
| * Cross-platform containment check: is `childPath` inside `parentPath`? | ||
| * Equality counts as "inside". | ||
| */ | ||
| const LEADING_PARENT_SEGMENT_RE = /^\.\.(?:[\\/]|$)/; |
There was a problem hiding this comment.
With the constant here, the JSDoc above now attaches to LEADING_PARENT_SEGMENT_RE instead of isPathInside. Moving the constant above the comment block keeps the doc on the function. The producer copy already puts it in a spot that doesn't split them.
|
Thanks, @kevin9327. This one is approved, and it'll go into the merge queue once these are sorted:
Once it's green and signed, we'll queue it at your new head. If you push code changes beyond a rebase, we'll take another look first. — Rames |
miguel-heygen
left a comment
There was a problem hiding this comment.
+1 to Rames' approval at this head. I also walked the callers, including the producer file server: files under a folder like ..assets inside the project now count as inside (which is the fix), and real .. traversal is still rejected because both paths are resolved before the relative check. CI is green apart from a cancelled studio capture check this change doesn't touch.
The two things already on the thread still stand: moving the constant above the JSDoc in assetPaths.ts, and signing the two commits so the merge queue can take it.
Verdict: APPROVE
Reasoning: Correct, minimal containment fix with tests that fail on main; checks green; only the existing nit and commit signing remain.
Head branch was pushed to by a user without write access
d6b2a26 to
922eeaf
Compare
|
Thanks for the reviews. I squashed the branch into one signed commit ( |
|
Thanks for re-signing. It conflicts with main again, so could you rebase and push once more? We'll re-approve at the new head. |
922eeaf to
64c7bbf
Compare
|
Rebased onto current |
What
isPathInside(both the shared@hyperframes/parsers/asset-pathshelper andproducer/src/utils/paths.ts) now treats only a whole..segment as "outside the parent". A child whose own name starts with two dots, such as..assets/logo.pngor..intro.mp4, counts as inside again.Why
Both helpers reject any relative path where
rel.startsWith(".."), which matches ordinary names as well as parent-dir segments:Callers then treat in-project files as outside the project:
collectExternalAssets/ publish copy them ashf-ext/...external assets, the font-face embedder skips local fonts under such a folder, andhyperframes media-treatment --file ..draft.htmlfails with "--file must be an HTML file inside the project". Other containment checks in the repo (cli/src/capture/captureFile.ts,cli/src/registry/publication.ts) already compare against the whole segment.Related work
Tiny self-contained correction. I searched issues/PRs for
isPathInsideand found no overlapping work.How
Replaced
!rel.startsWith("..")with aLEADING_PARENT_SEGMENT_RE(/^\.\.(?:[\\/]|$)/) check in both helpers. Matching either separator keeps the producer helper's injectedpathModule(e.g.win32in tests) working without widening itsPathModuleLiketype. Equal paths, paths above the parent, and different-drive absolute results are still rejected.Test plan
packages/parsers/src/assetPaths.test.ts, plus new cases inpackages/producer/src/utils/paths.test.ts(POSIX andwin32..fontschildren, and awin32path above the parent). The new dot-dot-name cases fail onmainand pass with the fix.packages/parsers:vitest rungives 46 files, 1288 tests passing.packages/producer:bun run test:unithas the same failing set with and without this change. Those failures are environment-only here (missing browser/ffmpeg/bun:testdeps), and the change adds 2 passing tests.oxfmt --check,oxlintandscripts/comment-ratchet.mjsare clean on the changed files.