Skip to content

fix(build): refuse a --build-dir that would delete the project - #9328

Open
bnusunny wants to merge 1 commit into
aws:developfrom
bnusunny:fix/build-dir-ancestor-guard
Open

bnusunny wants to merge 1 commit into
aws:developfrom
bnusunny:fix/build-dir-ancestor-guard

Conversation

@bnusunny

@bnusunny bnusunny commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Which issue(s) does this change fix?

Fixes #9327

Why is this change necessary?

sam build deletes --build-dir before it builds. The only guard (#1403) refuses the working directory itself. So sam build --build-dir .. deletes the whole project and everything beside it, and sam build -t proj/template.yaml --build-dir proj deletes the template and its source. --build-dir .aws-sam builds, but deletes SAM CLI's own build cache, dependencies and pipeline config on every run.

How does it address the issue?

--build-dir Before After
., .., any parent of the working directory . refused, parents deleted all refused, nothing deleted
a dir that is or contains the template's directory or --base-dir, e.g. -t proj/template.yaml -b proj project deleted, then "Template file not found" refused, nothing deleted
.aws-sam, .aws-sam/cache, .aws-sam/deps, or a dir containing --cache-dir state deleted silently same build, plus a warning that this will not be supported in a future release
.aws-sam/build (default), .aws-sam/auto-dependency-layer, any other dir builds unchanged

_setup_build_dir in samcli/commands/build/build_context.py compares paths with a new is_same_or_ancestor helper in samcli/lib/utils/path_utils.py. The helper uses os.path.commonpath and normcase, so it ignores case on Windows. The .aws-sam case warns rather than fails, because some users pass it today. There is no warning when clean is false, since nothing is removed then. DEFAULT_SAM_DIR is a new constant in samcli/commands/_utils/constants.py.

What side effects does this change have?

  • A --build-dir that is or contains the working directory, the template's directory or the base dir now fails instead of deleting it.
  • --build-dir .aws-sam and similar now print a warning; the build itself is unchanged.
  • The .aws-sam entry overlaps with the deps-dir entry, which already sits inside .aws-sam. It is kept so the rule still holds if the deps dir ever moves.

Mandatory Checklist

PRs will only be reviewed after checklist is complete

Notes on the unchecked items:

  • Tests:
    • Unit: the tests in tests/unit/commands/buildcmd/test_build_context.py and tests/unit/lib/utils/test_path_utils.py cover every row of the table on a real temporary filesystem. The helper also has Windows-path cases. Reverting either guard turns them red.

    • Integration: TestBuildCommand_BuildDirGuard in tests/integration/buildcmd/test_build_cmd.py runs a real sam build for four cases:

      • .. and ../.. are refused, and the project and a file next to it survive;
      • -t proj/template.yaml --build-dir proj is refused, and the template and source survive;
      • .aws-sam and .aws-sam/cache warn and still build;
      • the default build dir builds without a warning.

      Against released 1.166.2, the five guarded cases fail and the default case passes.

  • make pr: ruff, black, mypy and the build/sync/_utils unit tests pass locally; the full suite is left to CI.
  • No dependency changes. The --build-dir help text already says the directory is removed first.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@bnusunny
bnusunny requested a review from a team as a code owner October 12, 2026 22:36
@github-actions github-actions Bot added area/build sam build command pr/internal labels Oct 12, 2026
@licjun

licjun commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

The change LGTM, I just think of a strange case, sam build -t proj/template.yaml --build-dir proj, i think this build will fail since the template.yaml will be deteled, is this something we should worry about?

@bnusunny
bnusunny force-pushed the fix/build-dir-ancestor-guard branch from 19bf673 to 56a66da Compare October 13, 2026 16:36
@bnusunny bnusunny changed the title fix(build): refuse a --build-dir that is a parent of the working directory fix(build): refuse a --build-dir that would delete the project Oct 13, 2026
@bnusunny

Copy link
Copy Markdown
Contributor Author

Good catch, and it's worse than a failed build: run from proj's parent, sam build -t proj/template.yaml --build-dir proj deletes proj (template and source), then fails with "Template file not found". The guard only looked at the working directory and its parents.

Fixed in 56a66da: the build dir now must not be or contain the working directory, the template's directory, or --base-dir. That case is refused with nothing deleted, and TestBuildCommand_BuildDirGuard.test_build_dir_containing_template_dir_is_refused covers it (it fails on 1.166.2).

@aws-sam-tooling-bot aws-sam-tooling-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Results

Reviewed: b73a020..56a66da
Files: 6
Comments: 1

Comment thread tests/integration/buildcmd/test_build_cmd.py
sam build removes the build dir before building. aws#1403 refused a build dir
equal to the current working directory, but other cases slipped through:

- A build dir that contains the project: `sam build --build-dir ..`, or
  `sam build -t proj/template.yaml --build-dir proj` run from proj's
  parent, deletes the template and source (and, for `..`, everything beside
  the project). These are now refused: the build dir must not be or contain
  the working directory, the template's directory or the base dir. The
  comparison is case-insensitive on Windows.
- .aws-sam itself, or the cache or deps dir: `--build-dir .aws-sam` deletes
  SAM CLI's own state on every build -- the build cache and dependencies (so
  --cached never hits) and the committed pipeline config written by
  `sam pipeline bootstrap` -- and writes build.toml into the project root.
  Some users may pass this today, so it now logs a warning that it will not
  be supported in a future release, and still builds. No warning is logged
  for a non-clean build, which removes nothing.

.aws-sam/build (the default), .aws-sam/auto-dependency-layer (used by
sam sync) and directories outside the project are unaffected.
@bnusunny
bnusunny force-pushed the fix/build-dir-ancestor-guard branch from 56a66da to 140a76e Compare October 13, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/build sam build command pr/internal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: sam build --build-dir deletes the project when given a parent directory, and SAM CLI's own state when given .aws-sam

3 participants