Repository navigation
fix(amazonq): keep transform checkpoint changes inside the solution folder - #2969
hezelin-work wants to merge 1 commit into
Conversation
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
37e7c88 to
e33ce30
Compare
ashishrp-aws
left a comment
There was a problem hiding this comment.
🤖 AI-assisted review at e33ce30 (reviewer agent plus a chair re-check).
Requesting changes. The lexical check is right as far as it goes. Every add, remove, update and both sides of a move go through checkpointEntryPath/solutionEntryPath, so .., a/../../x, ..\x, drive and UNC paths and the job-data folder (including case and trailing dot/space variants) are all rejected. But the check only compares paths as text, while the writes follow symlinks.
Blocking
-
A symlink inside the solution folder escapes the check (
atxTransformHandler.ts:4616-4642check, thencopyFileSync/unlinkSyncat:4731/4763/4803/4859-4861). Reproduced on a real filesystem withsln/src/link -> ../../outside:- updated
src/link/victim→copyFileSyncoverwroteoutside/victim - removed
src/link/del→unlinkSyncdeleted the outside file - a file symlink
sln/filelink -> outside/victim→ the write went through to the outside file - a move with
before = src/link/key→ outside content was copied into the tree
Fix: canonicalise the nearest existing ancestor of each destination, delete target and move source (
resolveSymlinkAwarePathintoolSharedalready does this) and check it againstrealpath(solutionRoot). Alsolstatthe destination and refuse to write through a symlink. Add a real-fs test with a symlinked directory. - updated
Should fix
2. The checkpoint download path has the same class. step.StepId / stepId come from the server unchecked and are joined into the extraction directory (:2884, :3633-3639). With StepId = "../../../../x", the extraction root itself escapes, and the zip-slip guard only checks against that already-escaped root. Validate step IDs against a strict pattern (e.g. ^[A-Za-z0-9_-]+$) or apply the same containment check to pathToDownload.
3. Skipped entries are silent. They're only logged: success stays true, the counts omit them (:4870), and callers then mark the step applied (:2907, :3660), so it's never retried. Return a skippedEntries list and surface it in the transform status, so the user isn't handed a partial transform without notice.
4. The job-data exclusion compares names, not the folder on disk. UNVERIFIED, since I had no Windows host: the 8.3 short name ARTIFA~1\… and artifactWorkspace::$INDEX_ALLOCATION\… pass the check. The impact stays inside the solution, but such an entry could overwrite the manifest or applied-steps record that the user-edit protection relies on. Compare the canonical destination against realpath(<sln>/artifactWorkspace) instead.
Non-blocking: reject : in path segments on win32 (alternate data streams).
e33ce30 to
68c6a18
Compare
3dbf9b1 to
bcaf6a1
Compare
…older - Skip checkpoint entries that are not inside the solution folder once symlinks are resolved, that are symlinks, or that are in the folder that holds the transform job data, and entries that would write to a file with more than one hard link. List the skipped entries in the transform info response. - Allow an entry outside the solution folder only when the job's source files include it, write the source files list for every job, and back up such a file inside the job's backup folder. - Download and apply a checkpoint only when its job and step IDs are folder names.
bcaf6a1 to
ace6e22
Compare
Problem
Applying a transform checkpoint did not limit changes to the solution folder.
Solution
SkippedCheckpointEntries.Behavior change: a checkpoint no longer adds files outside the solution folder, or changes files there that are not among the job's source files. Jobs that are not interactive now also keep a source files list, so their checkpoint applies preserve files the customer edited since the last apply, as interactive jobs already do.
Testing: added unit tests.
License
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.