From 44a79a4bc8bfffc619cc7277f934ebd5060577cc Mon Sep 17 00:00:00 2001 From: Arya Rizky Date: Tue, 12 May 2026 17:42:54 +0700 Subject: [PATCH 1/2] fix(lambda): preserve Unix file permissions in zip2tar conversion --- moto/awslambda/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 0d9c4eda20bc..fb073a4f984f 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -92,6 +92,8 @@ def zip2tar(zip_bytes: bytes) -> io.BytesIO: tarinfo = tarfile.TarInfo(name=zipinfo.filename) tarinfo.size = zipinfo.file_size tarinfo.mtime = calendar.timegm(zipinfo.date_time) - timeshift + if zipinfo.external_attr >> 16: + tarinfo.mode = zipinfo.external_attr >> 16 infile = zipf.open(zipinfo.filename) tarf.addfile(tarinfo, infile) From f7e8b11988df9ceba071e3fce1b1e1855e4a6076 Mon Sep 17 00:00:00 2001 From: Arya Rizky Date: Tue, 12 May 2026 19:07:00 +0700 Subject: [PATCH 2/2] fix(zip2tar): ensure minimum read+execute permissions on extracted files When zipinfo.external_attr >> 16 is 0 (common for Lambda ZIPs built on systems without Unix permissions, e.g. Windows or CI), the previous code skipped setting tarinfo.mode entirely, leaving it at 0000. This caused PermissionError when Lambda tried to read /var/task/index.py. Fix: always set tarinfo.mode from external_attr, then OR in minimum bits: - Files: 0o444 (read for all) - Dirs: 0o555 (read+execute for all) Closes getmoto/moto#10021 --- moto/awslambda/models.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index fb073a4f984f..5a242c4bffcf 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -92,8 +92,14 @@ def zip2tar(zip_bytes: bytes) -> io.BytesIO: tarinfo = tarfile.TarInfo(name=zipinfo.filename) tarinfo.size = zipinfo.file_size tarinfo.mtime = calendar.timegm(zipinfo.date_time) - timeshift - if zipinfo.external_attr >> 16: - tarinfo.mode = zipinfo.external_attr >> 16 + tarinfo.mode = zipinfo.external_attr >> 16 + # Ensure minimum read bits for all users. + # Lambda extracts these files to /var/task and needs + # at least 0444 (read) for files and 0555 (read+execute) for dirs. + if zipinfo.is_dir(): + tarinfo.mode |= 0o555 + else: + tarinfo.mode |= 0o444 infile = zipf.open(zipinfo.filename) tarf.addfile(tarinfo, infile)