Skip to content

Bug: sam build --use-container fails with LinkOutsideDestinationError on 1.155.2 (npm symlink regression) #8743

@tkd4444

Description

@tkd4444

Description

After upgrading from aws-sam-cli 1.154.0 to aws-sam-cli 1.155.2, sam build --use-container started failing in AWS CodeBuild during artifact extraction from the build container with a LinkOutsideDestinationError caused by an npm symlink under node_modules/.bin.

Pinning back to aws-sam-cli==1.154.0 restores successful builds.


Steps to Reproduce

  1. Use AWS CodeBuild on Amazon Linux 2 with Python 3.9
  2. Install:
pip install awscli==1.44.52 aws-sam-cli==1.155.2
  1. Have a SAM app with Node.js functions that include node_modules/.bin symlinks (e.g. is-docker)
  2. Run:
sam build --use-container --template ${SAM_TEMPLATE} --debug
  1. Build fails during artifact copy/extraction from the container

For comparison, the following succeeds with the same repository and build flow:

pip install awscli==1.44.49 aws-sam-cli==1.154.0

Expected Behavior

sam build --use-container completes successfully, as it did on 1.154.0.


Actual Behavior

Build aborts with:

Mounting /codebuild/output/src2979588853/src/hooks as /tmp/samcli/source:ro,delegated, inside runtime container
SAM_CONTAINER_ID: 17748ca2b368a46db0645723368639d985ed4cfc9de625d3fb60739b7a4942a5
package.json file not found. Continuing the build without dependencies.
Running NodejsNpmBuilder:CopySource

Error: './node_modules/.bin/is-docker' would link to '/codebuild/output/src2979588853/src/.aws-sam/build/is-docker/cli.js', which is outside the destination
Traceback:
  ...
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/utils/tar.py", line 154, in extract_tarfile
    tar.extractall(path=unpack_dir, filter="data")
  ...
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/tarfile.py", line 805, in _get_filtered_attrs
    raise LinkOutsideDestinationError(member, target_path)

An unexpected error was encountered while executing "sam build".
Full traceback
Mounting /codebuild/output/src2979588853/src/hooks as /tmp/samcli/source:ro,delegated, inside runtime container
SAM_CONTAINER_ID: 17748ca2b368a46db0645723368639d985ed4cfc9de625d3fb60739b7a4942a5
package.json file not found. Continuing the build without dependencies.
 Running NodejsNpmBuilder:CopySource

Error: './node_modules/.bin/is-docker' would link to '/codebuild/output/src2979588853/src/.aws-sam/build/is-docker/cli.js', which is outside the destination
Traceback:
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/click/core.py", line 1082, in main
    rv = self.invoke(ctx)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/click/core.py", line 1697, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/click/core.py", line 1443, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/cli/cli_config_file.py", line 366, in wrapper
    return func(*args, **kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/click/decorators.py", line 92, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/telemetry/metric.py", line 190, in wrapped
    raise exception
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/telemetry/metric.py", line 155, in wrapped
    return_value = func(*args, **kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/utils/version_checker.py", line 43, in wrapped
    actual_result = func(*args, **kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/cli/main.py", line 95, in wrapper
    return func(*args, **kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/commands/build/command.py", line 172, in cli
    do_cli(
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/commands/build/command.py", line 264, in do_cli
    ctx.run()
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/commands/build/build_context.py", line 289, in run
    self._build_result = builder.build()
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/app_builder.py", line 255, in build
    return ApplicationBuildResult(build_graph, build_strategy.build())
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 415, in build
    return super().build()
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 83, in build
    result.update(self._build_functions(self._build_graph))
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 421, in _build_functions
    return self._run_builds_async(
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 437, in _run_builds_async
    async_results = async_context.run_async()
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/utils/async_utils.py", line 138, in run_async
    return run_given_tasks_async(self._async_tasks, event_loop)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/utils/async_utils.py", line 96, in run_given_tasks_async
    return event_loop.run_until_complete(_run_given_tasks_async(tasks, event_loop, executor))
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/utils/async_utils.py", line 62, in _run_given_tasks_async
    raise result
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 448, in build_single_function_definition
    return self._delegate_build_strategy.build_single_function_definition(build_definition)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 594, in build_single_function_definition
    return self._cached_build_strategy.build_single_function_definition(build_definition)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 302, in build_single_function_definition
    build_result = self._delegate_build_strategy.build_single_function_definition(build_definition)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/build_strategy.py", line 167, in build_single_function_definition
    result = self._build_function(
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/app_builder.py", line 765, in _build_function
    return self._build_function_on_container(
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/build/app_builder.py", line 1037, in _build_function_on_container
    container.copy(result_dir_in_container, artifacts_dir)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/local/docker/container.py", line 660, in copy
    extract_tarfile(file_obj=fp, unpack_dir=to_host_path, mount_symlinks=bool(self._mount_symlinks))
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/site-packages/samcli/lib/utils/tar.py", line 154, in extract_tarfile
    tar.extractall(path=unpack_dir, filter="data")
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/tarfile.py", line 2235, in extractall
    tarinfo = self._get_extract_tarinfo(member, filter_function, path)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/tarfile.py", line 2289, in _get_extract_tarinfo
    self._handle_fatal_error(e)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/tarfile.py", line 2287, in _get_extract_tarinfo
    tarinfo = filter_function(tarinfo, path)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/tarfile.py", line 818, in data_filter
    new_attrs = _get_filtered_attrs(member, dest_path, True)
  File "/root/.pyenv/versions/3.9.17/lib/python3.9/tarfile.py", line 805, in _get_filtered_attrs
    raise LinkOutsideDestinationError(member, target_path)

An unexpected error was encountered while executing "sam build".

Root Cause (suspected)

The traceback points to samcli/lib/utils/tar.py calling tar.extractall(..., filter="data"). The "data" filter, introduced for security in Python's tarfile module, rejects symlinks whose resolved target falls outside the extraction destination. npm-generated symlinks in node_modules/.bin (e.g. is-docker -> ../is-docker/cli.js) are valid relative symlinks but appear to resolve outside the destination under this filter, causing the error.

This behavior was not present in 1.154.0, suggesting filter="data" was introduced or its handling changed in 1.155.2.


Environment

Working Failing
aws-sam-cli 1.154.0 1.155.2
awscli 1.44.49 1.44.52
boto3 1.42.26 1.42.59
botocore 1.42.59 1.42.62
OS AWS CodeBuild / Amazon Linux 2 AWS CodeBuild / Amazon Linux 2
Python 3.9.17 3.9.17
Docker 20.10.24 20.10.24
Architecture x86_64 x86_64

Workaround

Pin to aws-sam-cli==1.154.0:

pip install aws-sam-cli==1.154.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    blocked/more-info-neededMore info is needed from the requester. If no response in 14 days, it will become stale.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions