Dashboard › institutional-transition-lab › Session 16WhjkBRkUOk
16WhjkBRkUOkgxiJmPerform a fresh, read-only security audit of only ZIP metadata and archive-structure validation for issue #4 in /home/byk/Code/institutional-transition-lab. This is one smaller disjoint replacement for a ZIP reviewer that returned empty twice. Never edit files and never inspect governance bodies, codings, outcomes, reports, dates, detector output, or source-adjudication scopes.
Scope only: archive entry-count enforcement; duplicate raw names; normalized/path/case/backslash collisions; empty names, absolute paths, drive prefixes, parent traversal; directory entries; Unix/DOS mode metadata for symlink/device/FIFO/socket/special entries; encryption flags; unsupported compression methods; duplicate uniqueness of required member names; inconsistencies visible from central-directory metadata. Treat _read_regular_file, JSON, pins/hashes, decompression/read loops, required-member content equality, and CLI outputs as out of scope.
Primary files are only the ZIP metadata helpers/constants in src/institution_lab/governance_adjudication.py and narrowly related tests in tests/test_governance_adjudication.py. Review the current unchanged working copy. Run narrow read-only tests/probes. Return substantive evidence, never empty. Findings first, severity ordered, with exact current file:line references and PASS/CONCERN/MUST-FIX/BLOCKED labels. Every defect needs a deterministic regression. If clean, state PASS with tests/probes and residual risks. End exactly MERGE or DO-NOT-MERGE.
Found 26 matches
/home/byk/Code/institutional-transition-lab/src/institution_lab/governance_adjudication.py:
Line 10: import zipfile
Line 67: MAX_ARCHIVE_MEMBERS = 128
Line 68: MAX_ARCHIVE_MEMBER_BYTES = 16 * 1024 * 1024
Line 69: MAX_ARCHIVE_EXPANDED_BYTES = 64 * 1024 * 1024
Line 180: with zipfile.ZipFile(io.BytesIO(artifact)) as archive:
Line 181: infos = archive.infolist()
Line 182: if len(infos) > MAX_ARCHIVE_MEMBERS:
Line 183: raise ValueError("artifact member count exceeds limit")
Line 184: member_counts = Counter(info.filename for info in infos)
Line 185: for member_name, count in member_counts.items():
Line 187: raise ValueError(f"artifact member is not unique: {member_name}")
Line 188: if sum(info.file_size for info in infos) > MAX_ARCHIVE_EXPANDED_BYTES:
Line 190: members = {
Line 194: for member_name, durable_bytes in members.items():
Line 196: info = archive.getinfo(member_name)
Line 198: ...
Found 26 matches
/home/byk/Code/institutional-transition-lab/tests/test_governance_adjudication.py:
Line 8: import zipfile
Line 37: MAX_TEST_ARCHIVE_MEMBERS = 256
Line 52: "artifact": tmp_path / "artifact.zip",
Line 65: with zipfile.ZipFile(paths["artifact"], "w") as archive:
Line 66: archive.writestr("documents.json", paths["documents"].read_bytes())
Line 67: archive.writestr(
Line 190: "filename": None,
Line 687: artifact = tmp_path / "artifact.zip"
Line 703: with zipfile.ZipFile(artifact, "w") as archive:
Line 704: archive.writestr("documents.json", documents.read_bytes())
Line 705: archive.writestr("v1.2-adjudication-package.json", coding_package.read_bytes())
Line 733: artifact = tmp_path / "artifact.zip"
Line 743: with zipfile.ZipFile(artifact, "w") as archive:
Line 744: archive.writestr("documents.json", b"different documents")
Line 745: archive.writestr("v1.2-adjudication-package.json", ...
Found 27 matches /home/byk/Code/institutional-transition-lab/src/institution_lab/governance_adjudication.py: Line 80: def canonical_sha256(value: Any) -> str: Line 90: def _bytes_sha256(payload: bytes) -> str: Line 94: def _read_regular_file(path: Path, *, max_bytes: int = MAX_INPUT_BYTES) -> bytes: Line 112: def file_sha256(path: Path) -> str: Line 116: def _reject_duplicate_keys(pairs: list[tuple[str, Any]]) -> dict[str, Any]: Line 125: def _reject_non_finite_number(value: str) -> None: Line 129: def _parse_json_object(payload: bytes, label: str) -> dict[str, Any]: Line 143: def _validate_manifest_identity(manifest: Any) -> None: Line 157: def _verify_input_payloads( Line 220: def verify_input_manifest( Line 242: def _duplicates(values: list[str]) -> set[str]: Line 247: def _source_index(document: dict[str, Any]) -> dict[str, str]: Line 263: def _evidence_errors( Line 290: def _response_for(record: dict[str, Any], source: str) -> dict[str, ...
<path>/home/byk/Code/institutional-transition-lab/src/institution_lab/governance_adjudication.py</path>
<type>file</type>
<content>
55: }
56: CLAIM_FIELDS = {
57: "record_class",
58: "event_kind",
59: "title",
60: "announced_on",
61: "effective_on",
62: "affected_scope",
63: "body_patch_relation",
64: }
65: MAX_INPUT_BYTES = 16 * 1024 * 1024
66: MAX_ARTIFACT_BYTES = 32 * 1024 * 1024
67: MAX_ARCHIVE_MEMBERS = 128
68: MAX_ARCHIVE_MEMBER_BYTES = 16 * 1024 * 1024
69: MAX_ARCHIVE_EXPANDED_BYTES = 64 * 1024 * 1024
70:
71:
72: @dataclass(frozen=True)
73: class VerifiedInputBundle:
74: pins: dict[str, Any]
(Showing lines 55-74 of 946. Use offset=75 to continue.)
</content>
<path>/home/byk/Code/institutional-transition-lab/src/institution_lab/governance_adjudication.py</path>
<type>file</type>
<content>
157: def _verify_input_payloads(
158: manifest: Any,
159: *,
160: artifact: bytes,
161: documents: bytes,
162: coding_package: bytes,
163: protocol: bytes,
164: coding_schema: bytes,
165: adjudication_schema: bytes,
166: ) -> VerifiedInputBundle:
167: _validate_manifest_identity(manifest)
168: computed = {
169: "artifact_sha256": _bytes_sha256(artifact),
170: "documents_file_sha256": _bytes_sha256(documents),
171: "coding_package_file_sha256": _bytes_sha256(coding_package),
172: "protocol_sha256": _bytes_sha256(protocol),
173: "coding_schema_sha256": _bytes_sha256(coding_schema),
174: "adjudication_schema_sha256": _bytes_sha256(adjudication_schema),
175: }
176: for field, value in computed.items():
177: if manifest.get(field) != value:
178: raise ValueError(f"input manifest mismatch: {field}")
179: try:
180: with ...
<path>/home/byk/Code/institutional-transition-lab/tests/test_governance_adjudication.py</path>
<type>file</type>
<content>
860: )
861: )
862: paths["summary_json"].write_text('{"canonicalization_gate":"open"}\n')
863:
864: with pytest.raises(ValueError, match="duplicate JSON key: artifact_sha256"):
865: _run_cli(monkeypatch, paths)
866:
867: assert json.loads(paths["summary_json"].read_text())["canonicalization_gate"] == "closed"
868:
869:
870: def test_input_manifest_rejects_non_object() -> None:
871: with pytest.raises(ValueError, match="input manifest must be an object"):
872: verify_input_manifest(
873: [], # type: ignore[arg-type]
874: artifact=Path("unused"),
875: documents=Path("unused"),
876: coding_package=Path("unused"),
877: protocol=Path("unused"),
878: coding_schema=Path("unused"),
879: adjudication_schema=Path("unused"),
880: )
881:
882:
883: def test_input_manifest_rejects_duplicate_artifact_members(
884: tmp_path: Path,
885: ...
Python 3.12.3 /usr/bin/bash: line 1: pytest: command not found
/home/byk/.local/bin/uv
No files found
drwxr-xr-x 3 byk byk 4096 Sep 9 04:59 /tmp/opencode
Using CPython 3.13.11
Creating virtual environment at: /tmp/opencode/itl-zip-audit-venv
Building institutional-transition-lab @ file:///home/byk/Code/institutional-transition-lab
Downloading ruff (9.8MiB)
Downloading pygments (1.2MiB)
Downloaded pygments
Built institutional-transition-lab @ file:///home/byk/Code/institutional-transition-lab
Downloaded ruff
Installed 12 packages in 18ms
============================= test session starts ==============================
platform linux -- Python 3.13.11, pytest-8.4.2, pluggy-1.6.0
rootdir: /home/byk/Code/institutional-transition-lab
configfile: pyproject.toml
collected 2 items
tests/test_governance_adjudication.py .. [100%]
============================== 2 passed in 0.17s ===============================
<4s4B4HL2L5H2L
b'PK\x01\x02'
0 1 2 3 4 5 6 9 10 11 12 13 14 15 16 17 18
('orig_filename', 'filename', 'date_time', 'compress_type', '_compresslevel', 'comment', 'extra', 'create_system', 'create_version', 'extract_version', 'reserved', 'flag_bits', 'volume', 'internal_attr', 'external_attr', 'header_offset', 'CRC', 'compress_size', 'file_size', '_raw_time', '_end_offset')
def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
self.orig_filename = filename # Original file name in archive
# Terminate the file name at the first null byte and
# ensure paths always use forward slashes as the directory separator.
filename = _sanitize_filename(filename)
self.filename = filename # Normalized file name
self.date_time = date_time # year, month, day, hour, min, sec
if date_time[0] < 1980:
raise ValueError('ZIP does not support timestamps before 1980')
# Standard values:
self.compress_type = ZIP_STORED # Type of compression for the file
self._compresslevel = None # Level for the compressor
self.comment = b"" # Comment for each file
self.extra = b"" # ZIP extra data
if sys.platform == 'win32':
self.create_system = 0 # System which created ZIP archive
else:
...
def _sanitize_filename(filename):
"""Terminate the file name at the first null byte and
ensure paths always use forward slashes as the directory separator."""
# Terminate the file name at the first null byte. Null bytes in file
# names are used as tricks by viruses in archives.
null_byte = filename.find(chr(0))
if null_byte >= 0:
filename = filename[0:null_byte]
# This is used to ensure paths in generated ZIP files always use
# forward slashes as the directory separator, as required by the
# ZIP format specification.
if os.sep != "/" and os.sep in filename:
filename = filename.replace(os.sep, "/")
if os.altsep and os.altsep != "/" and os.altsep in filename:
filename = filename.replace(os.altsep, "/")
return filename
'' ok '' '' False '/' ok '/' '/' True '../x' ok '../x' '../x' False '/x' ok '/x' '/x' False 'C:/x' ok 'C:/x' 'C:/x' False 'x\\y' ok 'x\\y' 'x\\y' False
def open(self, name, mode="r", pwd=None, *, force_zip64=False):
"""Return file-like object for 'name'.
name is a string for the file name within the ZIP file, or a ZipInfo
object.
mode should be 'r' to read a file already in the ZIP file, or 'w' to
write to a file newly added to the archive.
pwd is the password to decrypt files (only used for reading).
When writing, if the file size is not known in advance but may exceed
2 GiB, pass force_zip64 to use the ZIP64 format, which can handle large
files. If the size is known in advance, it is best to pass a ZipInfo
instance for name, with zinfo.file_size set.
"""
if mode not in {"r", "w"}:
raise ValueError('open() requires mode "r" or "w"')
if pwd and (mode == "w"):
raise ValueError("pwd is only supported for reading files")
if not self.fp:
raise ValueError(
"Attempt to ...
count=128: ACCEPT count=129: REJECT ValueError: artifact member count exceeds limit exact duplicate required name: REJECT ValueError: artifact member is not unique: documents.json dot-segment collision: ACCEPT case collision: ACCEPT backslash collision: ACCEPT repeated-separator collision: ACCEPT Unicode-normalization collision: ACCEPT empty name: ACCEPT absolute POSIX name: ACCEPT absolute backslash name: ACCEPT drive-prefixed name: ACCEPT parent traversal: ACCEPT directory by trailing slash: ACCEPT Unix symlink mode: ACCEPT Unix character-device mode: ACCEPT Unix block-device mode: ACCEPT Unix FIFO mode: ACCEPT Unix socket mode: ACCEPT Unix directory mode: ACCEPT DOS volume-label attribute: ACCEPT DOS directory attribute: ACCEPT DOS device attribute: ACCEPT traditional-encryption flag: ACCEPT strong-encryption flag: ACCEPT unsupported compression method 99: ACCEPT nonzero starting disk: ACCEPT unknown creator system: ACCEPT nonzero reserved extractor-system byte: ACCEPT impossible ...
No files found
(no output)
?? src/institution_lab/governance_adjudication.py ?? tests/test_governance_adjudication.py
<path>/home/byk/Code/institutional-transition-lab/tests/test_governance_adjudication.py</path> <type>file</type> <content> 33: RIGHT_KINDS, 34: ) 35: 36: ROOT = Path(__file__).parents[1] 37: MAX_TEST_ARCHIVE_MEMBERS = 256 38: 39: 40: def _write_pinned_cli_inputs( (Showing lines 33-40 of 1024. Use offset=41 to continue.) </content>
Found 4 matches /home/byk/Code/institutional-transition-lab/tests/test_governance_adjudication.py: Line 772: with pytest.raises(ValueError, match="artifact member mismatch: documents.json"): Line 889: pytest.warns(UserWarning, match="Duplicate name"), Line 896: with pytest.raises(ValueError, match="artifact member is not unique: documents.json"): Line 919: with pytest.raises(ValueError, match="artifact member count exceeds limit"):
c686c4878409e68b958dd61850a59e9234416d817fc2fa3246fc728d51ebe0a5 src/institution_lab/governance_adjudication.py abf64b5e78a616d53b703dee5291ce7bf23fa9156fe59263a702e01cb8667bc5 tests/test_governance_adjudication.py
c686c4878409e68b958dd61850a59e9234416d817fc2fa3246fc728d51ebe0a5 src/institution_lab/governance_adjudication.py abf64b5e78a616d53b703dee5291ce7bf23fa9156fe59263a702e01cb8667bc5 tests/test_governance_adjudication.py
def _RealGetContents(self):
"""Read in the table of contents for the ZIP file."""
fp = self.fp
try:
endrec = _EndRecData(fp)
except OSError:
raise BadZipFile("File is not a zip file")
if not endrec:
raise BadZipFile("File is not a zip file")
if self.debug > 1:
print(endrec)
size_cd = endrec[_ECD_SIZE] # bytes in central directory
offset_cd = endrec[_ECD_OFFSET] # offset of central directory
self._comment = endrec[_ECD_COMMENT] # archive comment
# "concat" is zero, unless zip was concatenated to another file
concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
if self.debug > 2:
inferred = concat + offset_cd
print("given, inferred, offset", offset_cd, inferred, concat)
# self.start_dir: Position of start of central directory
self.start_dir = offset_cd + concat
if ...
def _decodeExtra(self, filename_crc):
# Try to decode the extra field.
extra = self.extra
unpack = struct.unpack
while len(extra) >= 4:
tp, ln = unpack('<HH', extra[:4])
if ln+4 > len(extra):
raise BadZipFile("Corrupt extra field %04x (size=%d)" % (tp, ln))
if tp == 0x0001:
data = extra[4:ln+4]
# ZIP64 extension (large files and/or large archives)
try:
if self.file_size in (0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF):
field = "File size"
self.file_size, = unpack('<Q', data[:8])
data = data[8:]
if self.compress_size == 0xFFFF_FFFF:
field = "Compress size"
self.compress_size, = unpack('<Q', data[:8])
data = data[8:]
if self.header_offset == 0xFFFF_FFFF:
...
Unicode-path-extra required-name alias: ACCEPT duplicate Unicode-path extra fields: ACCEPT trailing malformed central extra-field bytes: ACCEPT
EOCD claims one entry while central directory contains three: ACCEPT EOCD claims nonzero disk numbers: ACCEPT
src/institution_lab/governance_adjudication.py:184-187 counts info.filename, which Python has already decoded and sanitized. It never checks the central-directory filename bytes. Required members are then resolved through the same sanitized name at :190-198.
In-memory probes reached the end of ZIP validation with:
documents.json\x00x, sanitized to documents.json.documents.json through a Unicode-path extra field.Regression: Build these archives byte-for-byte and assert a stable ValueError for duplicate raw names, NUL-containing names, alternate required-member identities, and duplicate path extra fields.
The exact-string counter at src/institution_lab/governance_adjudication.py:184 performs no slash normalization, Unicode normalization, case folding, or path validation.
Probes accepted:
./documents.json beside documents.jsonDOCUMENTS.JSON beside documents.jsona/b with a\b, a//b, or Unicode-equivalent names/absolute and \absoluteC:/drivea/../../escapedirectory/These archives can have different meanings across ZIP consumers and filesystems.
Regression: Add parameterized rejection tests for empty, absolute, UNC/backslash-rooted, drive-relative and drive-absolute, dot-segment, parent-traversal, and directory names. Add collision pairs covering separators, case folding, and Unicode normalization.
After infolist() at src/institution_lab/governance_adjudication.py:181, the code inspects only names, counts, and sizes through :200. It never checks create_system, external_attr, Unix file types, or DOS attributes. ...
2026-09-09 🔴 (05:03) [enforced-read-only] User directed that files must never be edited during work in `/home/byk/Code/institutional-transition-lab`. 🔴 (05:03) User directed never to inspect governance bodies, codings, outcomes, reports, dates, detector output, or source-adjudication scopes. 🔴 (05:03) User limited issue #4 review scope to ZIP metadata and archive-structure validation: archive …