Skip to content

fix(sync): keep all writes inside --dest - #13

Merged
sameehj merged 1 commit into
masterfrom
fix/wolfglass-sync-path-guard
Oct 2, 2026
Merged

sameehj merged 1 commit into
masterfrom
fix/wolfglass-sync-path-guard

Conversation

@MarkAtwood

@MarkAtwood MarkAtwood commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

wolfglass-sync joins --subdir onto --dest and copies files there with shutil.copy2. An absolute --subdir replaces --dest entirely, a --subdir containing .. walks out of it, and a symlink already under the vendored path redirects a copy to wherever it points.

This requires --subdir to be relative and to resolve inside --dest, and resolves every write target (share files, VERSION, .wolfglass-rev) before copying. If any lands outside the vendored path it exits non-zero without writing anything. Containment uses os.path.commonpath, so --dest / works.

tests/test_wolfglass_sync.py covers absolute and .. subdirs, file and directory symlinks pointing outside, a --subdir that is itself a symlink out of --dest, --dest /, and a normal relative copy. Wired into selftest.yml.

Copilot AI review requested due to automatic review settings July 24, 2026 00:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens tools/wolfglass-sync against path traversal/escape via --subdir so syncing cannot overwrite files outside the intended --dest tree, and adds CI-backed regression tests for the new guard.

Changes:

  • Add --subdir validation to require a relative path that resolves within --dest.
  • Add unit tests covering absolute and ..-based escape attempts, plus a valid relative subdir case.
  • Wire the new test into selftest.yml (compile + unittest execution).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tools/wolfglass-sync Adds --subdir containment checks to prevent writing outside --dest.
tests/test_wolfglass_sync.py New tests validating the containment guard (absolute and .. rejected; relative allowed).
.github/workflows/selftest.yml Runs the new unit test in CI and includes it in the syntax-compile step.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/wolfglass-sync
Comment on lines +61 to +66
dest_abs = os.path.realpath(args.dest)
dest_root_abs = os.path.realpath(dest_root)
if dest_root_abs != dest_abs and \
not dest_root_abs.startswith(dest_abs + os.sep):
sys.exit(f"ERROR: --subdir {args.subdir!r} escapes --dest; it must "
f"resolve to a path inside {args.dest!r}.")
@sameehj
sameehj force-pushed the master branch 4 times, most recently from 3ab77f9 to 9bdf5b7 Compare July 24, 2026 14:09
@MarkAtwood
MarkAtwood force-pushed the fix/wolfglass-sync-path-guard branch from a6770c6 to 481f19f Compare August 13, 2026 01:15
@MarkAtwood
MarkAtwood force-pushed the fix/wolfglass-sync-path-guard branch from 481f19f to d1d67d3 Compare September 29, 2026 00:57
wolfglass-sync joins --subdir onto --dest and copies files there with
shutil.copy2. An absolute --subdir replaces --dest entirely, a --subdir
containing .. walks out of it, and a symlink already under the vendored
path redirects a copy to wherever it points.

Require --subdir to be relative and to resolve inside --dest, and
resolve every write target (share files, VERSION, .wolfglass-rev)
before copying. If any lands outside the vendored path, exit non-zero
without writing. Containment uses os.path.commonpath, so --dest /
works.

Adds tests/test_wolfglass_sync.py, wired into selftest.yml.
@MarkAtwood
MarkAtwood force-pushed the fix/wolfglass-sync-path-guard branch from 157fa0a to 4f22eb4 Compare October 1, 2026 20:54
@MarkAtwood MarkAtwood changed the title fix(sync): reject --subdir that escapes --dest fix(sync): keep all writes inside --dest Oct 1, 2026
@sameehj
sameehj merged commit 017ddeb into master Oct 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants