Dashboard › institutional-transition-lab › Session 0RsRJeRgksVA
0RsRJeRgksVAwRSzBPerform a fresh, minimal, read-only security audit of only declared ZIP-size limit arithmetic for issue #4 in /home/byk/Code/institutional-transition-lab. This replaces a resource-accounting reviewer that returned empty twice. Never edit files or inspect governance records/codings/outcomes/reports/dates/detectors/source-adjudication.
Scope only: how central-directory file_size declarations are checked against per-member and total expanded-byte constants; exact boundary behavior; integer/negative/overflow/impossible values as exposed or byte-patchable; whether malformed declarations bypass limits before decompression. Do not inspect actual member read loops, CRC/content comparison, archive names/path/mode/encryption/count, regular-file reads, JSON/pins/hashes, or CLI output.
Review only relevant code/constants in src/institution_lab/governance_adjudication.py and narrow tests. Run small read-only probes. Return substantive evidence, never empty. Findings first with exact file:line references and PASS/CONCERN/MUST-FIX/BLOCKED labels; deterministic regression for every defect. End exactly MERGE or DO-NOT-MERGE.
Found 10 matches
/home/byk/Code/institutional-transition-lab/src/institution_lab/governance_adjudication.py:
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 181: infos = archive.infolist()
Line 182: if len(infos) > MAX_ARCHIVE_MEMBERS:
Line 188: if sum(info.file_size for info in infos) > MAX_ARCHIVE_EXPANDED_BYTES:
Line 189: raise ValueError("artifact expanded size exceeds limit")
Line 199: if info.file_size > MAX_ARCHIVE_MEMBER_BYTES:
Line 202: member_bytes = source.read(MAX_ARCHIVE_MEMBER_BYTES + 1)
Line 203: if len(member_bytes) > MAX_ARCHIVE_MEMBER_BYTES:
<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>
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 zipfile.ZipFile(io.BytesIO(artifact)) as archive:
181: infos = archive.infolist()
182: if len(infos) > MAX_ARCHIVE_MEMBERS:
183: raise ValueError("artifact member count exceeds limit")
184: ...
No files found
No files found
/home/byk/Code/institutional-transition-lab/tests/test_governance_adjudication.py /home/byk/Code/institutional-transition-lab/tests/test_model_policy.py /home/byk/Code/institutional-transition-lab/tests/test_source_retrieval.py /home/byk/Code/institutional-transition-lab/tests/test_source_enrichment.py /home/byk/Code/institutional-transition-lab/tests/test_robustness.py /home/byk/Code/institutional-transition-lab/tests/test_phases.py /home/byk/Code/institutional-transition-lab/tests/test_oss_metrics.py /home/byk/Code/institutional-transition-lab/tests/test_oss_ingest.py /home/byk/Code/institutional-transition-lab/tests/test_llm_triage_compare.py /home/byk/Code/institutional-transition-lab/tests/test_llm_event_probe.py /home/byk/Code/institutional-transition-lab/tests/test_llm_candidate_triage.py /home/byk/Code/institutional-transition-lab/tests/test_llm_benchmark_subset.py /home/byk/Code/institutional-transition-lab/tests/test_llm_benchmark_gate.py /home/byk/Code/institutional-transiti...
Found 13 matches
/home/byk/Code/institutional-transition-lab/tests/test_governance_adjudication.py:
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 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 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", coding_package.read_bytes())
Line 890: zipfile.ZipFile(paths["artifact"], "a") as archive,
Line 892: archive.writestr("documents.json", paths["documents"].read_bytes())
Line 913: with zipfile.ZipFile(paths["artifact"], "a") as archive:
Line 915: ...
No files found
Found 5 matches
/home/byk/Code/institutional-transition-lab/tests/test_governance_adjudication.py:
Line 271: "evidence_limitations": None,
Line 423: def test_bounded_source_requires_explicit_evidence_limitation() -> None:
Line 446: assert any("bounded evidence requires evidence_limitations" in error for error in errors)
Line 919: with pytest.raises(ValueError, match="artifact member count exceeds limit"):
Line 1017: "evidence_limitations": None,
<path>/home/byk/Code/institutional-transition-lab/src/institution_lab/governance_adjudication.py</path>
<type>file</type>
<content>
1: from __future__ import annotations
2:
3: import argparse
4: import hashlib
5: import io
6: import json
7: import os
8: import stat
9: import tempfile
10: import zipfile
11: from collections import Counter
12: from contextlib import suppress
13: from dataclasses import dataclass
14: from pathlib import Path
15: from typing import Any
16:
17: from jsonschema import Draft202012Validator, FormatChecker
18:
19: from institution_lab.governance_coding import validate_response
20:
21: DECISIONS = {"accept", "revise", "reject", "abstain"}
22: INSTITUTIONAL_CLASSES = {
(Showing lines 1-22 of 946. Use offset=23 to continue.)
</content>
member_exact [16777216, 0] member_reject False total_reject False member_plus_one [16777217, 0] member_reject True total_reject False total_exact [16777216, 50331648] member_reject True total_reject False total_plus_one [16777216, 50331649] member_reject True total_reject True underdeclared [0, 0] member_reject False total_reject False u32_max_minus_sentinel [4294967294, 0] member_reject True total_reject True u32_sentinel 4294967295 pack_u32 -1 error pack_u32 4294967296 error
No files found
<path>/home/byk/Code/institutional-transition-lab</path> <type>directory</type> <entries> .git/ .github/ .gitignore .lore.md .pytest_cache/ .ruff_cache/ .venv/ AGENTS.md cases/ data/ docs/ node_modules/ package-lock.json package.json PROTOCOL.md pyproject.toml README.md research/ schema/ scripts/ src/ tests/ uv.lock (23 entries) </entries>
?? src/institution_lab/governance_adjudication.py ?? tests/test_governance_adjudication.py
<path>/home/byk/Code/institutional-transition-lab/src/institution_lab/governance_adjudication.py</path>
<type>file</type>
<content>
150: if type(manifest.get("artifact_id")) is not int or manifest["artifact_id"] < 1:
151: raise ValueError("input manifest artifact_id is invalid")
152: for field, value in FROZEN_INPUT_PINS.items():
153: if manifest.get(field) != value:
154: raise ValueError(f"input manifest does not identify frozen issue #4 input: {field}")
155:
156:
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)
(Showing lines 150-167 of 946. Use offset=168 to continue.)
</content>
member_at_limit [16777216] (True, True) member_over_limit [16777217] (False, True) total_at_limit [16777216, 16777216, 16777216, 16777216] (True, True) total_over_limit [16777216, 16777216, 16777216, 16777216, 1] (True, False) underdeclared local_size 1 central_size 0 exposed 0 gate (True, True) missing_zip64_extra_sentinel 4294967295 (False, False) python_sum_exact 8589934590 True u32_unrepresentable -1 u32_unrepresentable 4294967296
zip64_u64_max 18446744073709551615 member_reject True total_reject True sum_two_exact True u64_negative_unrepresentable True u64_too_large_unrepresentable True
declared_sizes [1, 1, 16777217] production_preopen_size_checks_pass True
No files found
truncated_zip64 BadZipFile Corrupt zip64 extra field. File size not found.
compressed_archive_bytes 16576 local_uncompressed_size 16777217 central_sizes_exposed [0, 1] production_preopen_size_checks_pass True
open_before_read accepted declared 0
M pyproject.toml M uv.lock ?? .lore.md ?? AGENTS.md ?? cases/review/oss-governance-adjudication-v1.inputs.json ?? cases/review/oss-governance-adjudication-v1/ ?? schema/governance-adjudication-v1.schema.json ?? src/institution_lab/governance_adjudication.py ?? tests/test_governance_adjudication.py
local_flags 0 central_flags 0 local_uncompressed_size 16777217 central_uncompressed_size 16777217
MUST-FIX β a forged central-directory underdeclaration bypasses both size gates.
infolist() supplies central-directory values at src/institution_lab/governance_adjudication.py:181. The aggregate check trusts those values at :188, and the selected-member check trusts them again at :199. Member opening follows at :201, with no prior declaration-consistency check.
A read-only probe created a 16,777,217-byte member, then changed only its central-directory size to zero. The local header remained 16,777,217 with the data-descriptor flag clear. Python exposed the size as zero, both production predicates passed, and ZipFile.open() accepted the member before any read. Therefore malformed metadata reaches decompression despite exceeding MAX_ARCHIVE_MEMBER_BYTES.
Deterministic regression: create an over-limit compressed member, patch its central size below the limit, instrument ZipFile.open() to fail if reached, and assert verification rejects the inconsistent declaration first.
CONCERN β the per-member limit is not applied archive-wide.
The total check covers every info at :188, but the per-member check occurs only inside the selected-member loop at :194-200. A probe with declared sizes [1, 1, 16777217] passed all current pre-open size checks because the oversized third entry remained below the 64 MiB aggregate limit.
Deterministic regression: add a third entry declared as MAX_ARCHIVE_MEMBER_BYTES + 1, keep the total below MAX_ARCHIVE_EXPANDED_BYTES, and assert rejection before opening any member.
PASS β upper-bound arithmetic does not wrap or admit negative values.
The constants are 16 MiB and 64 MiB at :68-69; the > comparisons at :188 and :199 correctly allow equality and reject limit + 1. ...
Date: Sep 9, 2026 * π‘ (05:56) Repository status additionally showed modified files `pyproject.toml` and `uv.lock`, plus untracked files/directories `.lore.md`, `AGENTS.md`, `cases/review/oss-governance-adjudication-v1.inputs.json`, `cases/review/oss-governance-adjudication-v1/`, and `schema/governance-adjudication-v1.schema.json`.
Date: Sep 9, 2026 * π΄ [requested-security-audit] (05:38) User requested a fresh, minimal, read-only security audit for issue #4 in `/home/byk/Code/institutional-transition-lab`, limited exclusively to declared ZIP-size limit arithmetic. * π΄ (05:38) User stated this audit replaces a resource-accounting reviewer that returned empty twice. * π΄ [enforced-read-only-scope] (05:38) User instructed neβ¦