fix(repo): Harden catalog sync and release integrity
Tighten the repo-state automation so canonical bot commits remain predictable while leaving main clean after each sync. Make the public catalog UI more honest by hiding dev-only sync, turning stars into explicit browser-local saves, aligning risk types, and removing hardcoded catalog counts. Add shared public asset URL helpers, risk suggestion plumbing, safer unpack/sync guards, and CI coverage gates so release and maintainer workflows catch drift earlier.
This commit is contained in:
@@ -2,6 +2,7 @@ import importlib.util
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import stat
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
@@ -20,21 +21,51 @@ def load_module(relative_path: str, module_name: str):
|
||||
|
||||
class OfficeUnpackSecurityTests(unittest.TestCase):
|
||||
def test_extract_archive_safely_blocks_zip_slip(self):
|
||||
module = load_module("skills/docx/ooxml/scripts/unpack.py", "docx_unpack")
|
||||
for relative_path, module_name in [
|
||||
("skills/docx-official/ooxml/scripts/unpack.py", "docx_unpack"),
|
||||
("skills/pptx-official/ooxml/scripts/unpack.py", "pptx_unpack"),
|
||||
]:
|
||||
module = load_module(relative_path, module_name)
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
temp_path = Path(temp_dir)
|
||||
archive_path = temp_path / "payload.zip"
|
||||
output_dir = temp_path / "output"
|
||||
with self.subTest(module=relative_path):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
temp_path = Path(temp_dir)
|
||||
archive_path = temp_path / "payload.zip"
|
||||
output_dir = temp_path / "output"
|
||||
|
||||
with zipfile.ZipFile(archive_path, "w") as archive:
|
||||
archive.writestr("../escape.txt", "escape")
|
||||
archive.writestr("word/document.xml", "<w:document/>")
|
||||
with zipfile.ZipFile(archive_path, "w") as archive:
|
||||
archive.writestr("../escape.txt", "escape")
|
||||
archive.writestr("word/document.xml", "<w:document/>")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
module.extract_archive_safely(archive_path, output_dir)
|
||||
with self.assertRaises(ValueError):
|
||||
module.extract_archive_safely(archive_path, output_dir)
|
||||
|
||||
self.assertFalse((temp_path / "escape.txt").exists())
|
||||
self.assertFalse((temp_path / "escape.txt").exists())
|
||||
|
||||
def test_extract_archive_safely_blocks_zip_symlinks(self):
|
||||
for relative_path, module_name in [
|
||||
("skills/docx-official/ooxml/scripts/unpack.py", "docx_unpack_symlink"),
|
||||
("skills/pptx-official/ooxml/scripts/unpack.py", "pptx_unpack_symlink"),
|
||||
]:
|
||||
module = load_module(relative_path, module_name)
|
||||
|
||||
with self.subTest(module=relative_path):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
temp_path = Path(temp_dir)
|
||||
archive_path = temp_path / "payload.zip"
|
||||
output_dir = temp_path / "output"
|
||||
|
||||
with zipfile.ZipFile(archive_path, "w") as archive:
|
||||
symlink_info = zipfile.ZipInfo("word/link")
|
||||
symlink_info.create_system = 3
|
||||
symlink_info.external_attr = (stat.S_IFLNK | 0o777) << 16
|
||||
archive.writestr(symlink_info, "../escape.txt")
|
||||
archive.writestr("word/document.xml", "<w:document/>")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
module.extract_archive_safely(archive_path, output_dir)
|
||||
|
||||
self.assertFalse((temp_path / "escape.txt").exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user