This is an automated email from the ASF dual-hosted git repository.

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new 643fdfba79 [release] Reject macOS metadata in source archives
643fdfba79 is described below

commit 643fdfba79b67b91cacbf7e012bdf2b3bb013d2a
Author: JingsongLi <[email protected]>
AuthorDate: Sat Aug 1 22:29:25 2026 +0800

    [release] Reject macOS metadata in source archives
---
 docs/docs/project/creating-a-release.md            |  1 +
 docs/docs/project/verifying-a-release-candidate.md | 28 ++++++++++++++++++++++
 tools/releasing/create_source_release.sh           | 27 +++++++++++++++++++--
 3 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/docs/docs/project/creating-a-release.md 
b/docs/docs/project/creating-a-release.md
index 5476d1ed6a..ed1e157167 100644
--- a/docs/docs/project/creating-a-release.md
+++ b/docs/docs/project/creating-a-release.md
@@ -331,6 +331,7 @@ repository image.
 
 Create both source candidates locally from the exact signed tag in a fresh
 clone. The Paimon helper creates, signs, and checksums the main source archive.
+It also rejects unsafe archive paths and hidden macOS AppleDouble metadata.
 Build the PyPaimon source distribution separately and sign it with the same RM
 key:
 
diff --git a/docs/docs/project/verifying-a-release-candidate.md 
b/docs/docs/project/verifying-a-release-candidate.md
index 145cbaf345..97988b0265 100644
--- a/docs/docs/project/verifying-a-release-candidate.md
+++ b/docs/docs/project/verifying-a-release-candidate.md
@@ -107,6 +107,34 @@ List the archives before extracting them:
 ```shell
 tar tzf "${PAIMON_ARCHIVE}" | sed -n '1,100p'
 tar tzf "${PYPAIMON_ARCHIVE}" | sed -n '1,100p'
+
+# Use Python as well because macOS tar hides AppleDouble (._*) entries.
+python3 - "${PAIMON_ARCHIVE}" "${PYPAIMON_ARCHIVE}" <<'PY'
+import sys
+import tarfile
+
+for archive in sys.argv[1:]:
+    with tarfile.open(archive, "r:*") as source:
+        for member in source.getmembers():
+            parts = [
+                part
+                for part in member.name.split("/")
+                if part not in ("", ".")
+            ]
+            if member.name.startswith("/") or ".." in parts:
+                raise ValueError(
+                    "%s contains an unsafe path: %s"
+                    % (archive, member.name)
+                )
+            if "__MACOSX" in parts or any(
+                part.startswith("._") for part in parts
+            ):
+                raise ValueError(
+                    "%s contains macOS metadata: %s"
+                    % (archive, member.name)
+                )
+    print("Archive metadata check passed: " + archive)
+PY
 ```
 
 Check at least the following:
diff --git a/tools/releasing/create_source_release.sh 
b/tools/releasing/create_source_release.sh
index 9a391920ad..0f63c1969f 100755
--- a/tools/releasing/create_source_release.sh
+++ b/tools/releasing/create_source_release.sh
@@ -52,6 +52,11 @@ else
     SHASUM="sha512sum"
 fi
 
+# macOS libarchive may otherwise add AppleDouble entries (._*) for filesystem
+# metadata even when --no-xattrs is used. These entries are hidden by the
+# macOS tar listing but are visible, and can break the build, on Linux.
+export COPYFILE_DISABLE=1
+
 ###########################
 
 RELEASE_DIR=${PROJECT_ROOT}/release
@@ -84,8 +89,26 @@ if [ -n "${UNEXPECTED_BINARY}" ]; then
     exit 1
 fi
 
-tar czf ${RELEASE_DIR}/apache-paimon-${RELEASE_VERSION}-src.tgz --no-xattrs 
paimon-${RELEASE_VERSION}
-gpg --armor --detach-sig 
${RELEASE_DIR}/apache-paimon-${RELEASE_VERSION}-src.tgz
+SOURCE_ARCHIVE=${RELEASE_DIR}/apache-paimon-${RELEASE_VERSION}-src.tgz
+tar czf ${SOURCE_ARCHIVE} --no-xattrs paimon-${RELEASE_VERSION}
+
+python3 - "${SOURCE_ARCHIVE}" <<'PY'
+import sys
+import tarfile
+
+archive = sys.argv[1]
+with tarfile.open(archive, "r:gz") as source:
+    for member in source.getmembers():
+        parts = [part for part in member.name.split("/") if part not in ("", 
".")]
+        if member.name.startswith("/") or ".." in parts:
+            raise ValueError("Source release contains an unsafe path: " + 
member.name)
+        if "__MACOSX" in parts or any(part.startswith("._") for part in parts):
+            raise ValueError(
+                "Source release contains macOS metadata: " + member.name
+            )
+PY
+
+gpg --armor --detach-sig ${SOURCE_ARCHIVE}
 cd ${RELEASE_DIR}
 ${SHASUM} apache-paimon-${RELEASE_VERSION}-src.tgz > 
apache-paimon-${RELEASE_VERSION}-src.tgz.sha512
 

Reply via email to