"""Check every published image layer for private core source or Git metadata.""" import argparse from pathlib import PurePosixPath import subprocess import tarfile def is_private_path(name, *, empty_file=False): parts = PurePosixPath(name).parts if PurePosixPath(name).name == "decompile-verify-declarations": return True if "verifier" in parts: return True if name.lstrip("./").startswith("home/user/app/core/"): return True if ".git" in parts: # uv creates an empty sdists-v9/.git sentinel to stop build tools from # discovering an enclosing repository. It is not repository metadata. sentinel = (".cache", "uv", "sdists-v9", ".git") if tuple(parts[-4:]) == sentinel and empty_file: return False return True return False def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("image") args = parser.parse_args() process = subprocess.Popen(["docker", "image", "save", args.image], stdout=subprocess.PIPE) failures, layers = [], 0 with tarfile.open(fileobj=process.stdout, mode="r|") as archive: for member in archive: if not member.isfile(): continue # Docker's OCI archive stores filesystem layers as tar blobs. if member.name.endswith(".tar") or member.name.startswith("blobs/sha256/"): blob = archive.extractfile(member) try: with tarfile.open(fileobj=blob, mode="r|*") as layer: layers += 1 for item in layer: if is_private_path(item.name, empty_file=item.isfile() and item.size == 0): failures.append(item.name) except tarfile.ReadError: # OCI manifests/config blobs are JSON, not filesystem layers. pass if process.wait() != 0: raise SystemExit("docker image save failed") if not layers: raise SystemExit("no image filesystem layers were inspected") if failures: raise SystemExit("private paths found in image layers: " + ", ".join(failures)) print(f"Inspected {layers} image layers: no private verifier source or Git metadata.") if __name__ == "__main__": main()