[CFX-6228][CFX-6229] sec: validate server-controlled paths in sync engine#526
Open
wojtekwdr wants to merge 1 commit into
Open
Conversation
b7a07bd to
cf558da
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Adds defense-in-depth validation for server-controlled sync paths before local filesystem write/delete operations.
Changes:
- Validates download paths in
downloadOne. - Validates server-side delete paths in
removeLocalDeletedFiles. - Adds path safety regression tests for unsafe path classes and delete behavior.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
internal/workload/sync/download.go |
Adds SafeRelPath validation before creating downloaded files. |
internal/workload/sync/phase5_execute.go |
Adds SafeRelPath validation before removing remote-deleted local files. |
internal/workload/sync/path_safety_test.go |
Adds tests for unsafe server paths and delete containment behavior. |
go.sum |
Updates module checksum metadata. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cf558da to
64dfb99
Compare
64dfb99 to
af3e6a5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RATIONALE
Two linked
[SEC] P1findings from the sync-engine security review (CFX-6228, CFX-6229):internal/workload/sync/download.go::downloadOnepassesFileAction.Path(server-controlled, sourced from theAllFilesresponse) directly intofilepath.Join(e.projectDir, filepath.FromSlash(fa.Path))and thenos.Create. A compromised server returning../../../etc/cron.d/evilwrites outside the project directory.internal/workload/sync/phase5_execute.go::removeLocalDeletedFilesdoes the same withos.Remove. A path of../../../home/user/.ssh/id_rsadeletes that file.filesapi.AllFilesalready validates manifest entries at the HTTP boundary, but paths flow throughSyncPlanbefore reaching disk, so a per-call-site guard is required as defense in depth.P2-4 (Rollback.Backup)provides a third layer at the rollback path and is tracked separately.CHANGES
internal/workload/sync/download.go- callfileops.SafeRelPath(fa.Path)at the top ofdownloadOne, beforefilepath.Join; return a wrapped"server returned unsafe download path %q: %w"error on rejection.internal/workload/sync/phase5_execute.go- callfileops.SafeRelPath(fa.Path)inside theremoveLocalDeletedFilesloop, after theActDownloadDeletefilter and beforefilepath.Join; return a wrapped"server returned unsafe delete path %q: %w"error on rejection.internal/workload/sync/path_safety_test.go(new) - sharedunsafeServerPathsslice covering five bypass classes (../escape,../../etc/passwd,/etc/passwd,..\windows, empty), table-driven tests for both call sites, a sentinel-file test that pins the no-escape-from-project-dir contract by writing a sentinel int.TempDir()'s parent and asserting it survives, and a negative test confirming non-ActDownloadDeleteentries are skipped without validation (uploads carry locally-scanned paths that would over-reject).The wrapping style and identifier choice (
fileops.SafeRelPath) match existing guards atcmd/workload/code/checkout/checkout.go:290andinternal/drapi/filesapi/allfiles.go:43,73.TESTING
task lint- 0 issues.task test- new tests pass under-race, each under 10ms; full sync package passes. (Full-repotask testreports one unrelated pre-existing failure incmd.TestWorkloadCommandNotPresentByDefaultdriven by the local.env'sDATAROBOT_CLI_FEATURE_WORKLOAD=true; with that env var unset the entire suite passes.)../path does not result inos.Removereaching outside the project directory.Note
Low Risk
Tightens path handling at two filesystem call sites with existing SafeRelPath helper; behavior change is rejecting malicious paths that should never have been applied.
Overview
Adds defense-in-depth validation so server-controlled
FileAction.Pathvalues cannot escape the project directory during sync.Before writing or removing files,
downloadOneandremoveLocalDeletedFilesnow callfileops.SafeRelPathand fail with clear errors (server returned unsafe download/delete path). Validation runs only forActDownloadDeletedeletes so upload-side delete entries (locally scanned paths) are not over-rejected.New
path_safety_test.gotable-tests traversal/absolute/empty/backslash paths at both sites, uses a parent-dir sentinel to prove deletes never run outside the project dir, and asserts non-download-delete plan entries are skipped.Reviewed by Cursor Bugbot for commit b7a07bd. Configure here.