From 7e6ebc7f3cfda189b85359336cc4fd919bcf4885 Mon Sep 17 00:00:00 2001 From: mldangelo-oai <269034524+mldangelo-oai@users.noreply.github.com> Date: Mon, 24 Aug 2026 00:09:05 +0000 Subject: [PATCH 1/5] fix(plugin): preserve committed diff scan integrity --- .../_bundled_plugin/.codex-plugin/plugin.json | 2 +- .../mcp/server.mjs.br.part-000 | Bin 140000 -> 140000 bytes .../mcp/server.mjs.br.part-001 | Bin 80447 -> 80484 bytes .../scripts/workbench_constants.py | 4 + .../_bundled_plugin/scripts/workbench_db.py | 884 ++++- .../scripts/workbench_target.py | 614 ++- sdk/typescript/src/version.ts | 2 +- .../tests-ts/compact-diff-scan.test.ts | 1315 +++++-- .../git-batch-object-validation.test.ts | 3411 +++++++++++++++++ .../prompt-only-start-timeout.test.ts | 171 +- 10 files changed, 5862 insertions(+), 541 deletions(-) create mode 100644 sdk/typescript/tests-ts/git-batch-object-validation.test.ts diff --git a/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json b/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json index 76688fe96..93934fc55 100644 --- a/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json +++ b/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "codex-security", - "version": "0.1.22", + "version": "0.1.23", "description": "Codex Security workflows for security scans, analysis, and investigation.", "author": { "name": "OpenAI" diff --git a/sdk/typescript/_bundled_plugin/mcp/server.mjs.br.part-000 b/sdk/typescript/_bundled_plugin/mcp/server.mjs.br.part-000 index 7ced89d9c2a1eabc170c1ee2175aeaa5b3c5a30c..ccb200305a5216b28347880347538499663a0475 100644 GIT binary patch literal 140000 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∿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 z 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

35&Dq<$j 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�J4ZQo3~W@p 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


^|XqAc0|Y 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 diff --git a/sdk/typescript/_bundled_plugin/scripts/workbench_constants.py b/sdk/typescript/_bundled_plugin/scripts/workbench_constants.py index 2019115f8..5c3bc4b59 100644 --- a/sdk/typescript/_bundled_plugin/scripts/workbench_constants.py +++ b/sdk/typescript/_bundled_plugin/scripts/workbench_constants.py @@ -68,6 +68,10 @@ "GIT_WORK_TREE", ) EMPTY_GIT_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" +EMPTY_GIT_TREES = { + "sha1": EMPTY_GIT_TREE, + "sha256": "6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321", +} def main() -> None: diff --git a/sdk/typescript/_bundled_plugin/scripts/workbench_db.py b/sdk/typescript/_bundled_plugin/scripts/workbench_db.py index e3717c1da..5c6481410 100644 --- a/sdk/typescript/_bundled_plugin/scripts/workbench_db.py +++ b/sdk/typescript/_bundled_plugin/scripts/workbench_db.py @@ -17,6 +17,7 @@ import tempfile import time import uuid +from collections.abc import Callable from contextlib import closing, contextmanager from datetime import datetime, timedelta, timezone from pathlib import Path, PurePosixPath @@ -65,7 +66,7 @@ CLAIM_LEASE_SECONDS, DELIVERED_ACTION_LEASE_SECONDS, DIFF_TARGET_KINDS, - EMPTY_GIT_TREE, + EMPTY_GIT_TREES, FINDING_ABSOLUTE_PATH_BYTES, FINDING_LEVEL_BYTES, FINDING_LOCATION_PATH_BYTES, @@ -103,10 +104,13 @@ from workbench_source_excerpt import finding_source_excerpt, safe_source_path from workbench_target import ( clean_worktree_content_digest, + committed_diff_content_snapshot, + committed_diff_object_identity, copy_directory_excluding, copy_git_worktree_files, directory_content_digest, directory_snapshot_regular_file_count, + empty_git_tree, git_bytes, git_command, git_output, @@ -248,6 +252,82 @@ def connect() -> sqlite3.Connection: raise AssertionError("SQLite retry loop exhausted unexpectedly.") +def begin_immediate_after_external_inspection( + connection: sqlite3.Connection, + inspect: Callable[[], bool], + validate: Callable[[], bool], + inspection_unnecessary: Callable[[], bool] | None = None, +) -> bool: + """Inspect outside the lock, then validate immutable Git coordinates under it.""" + connection.execute("BEGIN IMMEDIATE") + try: + if inspection_unnecessary is not None and inspection_unnecessary(): + return True + except BaseException: + connection.rollback() + raise + connection.rollback() + busy_timeout = int(connection.execute("PRAGMA busy_timeout").fetchone()[0]) + while True: + try: + inspected = inspect() + except (Exception, SystemExit): + if inspection_unnecessary is None: + raise + connection.execute("BEGIN IMMEDIATE") + try: + if inspection_unnecessary(): + return True + except BaseException: + connection.rollback() + raise + connection.rollback() + raise + blocked = False + connection.execute("PRAGMA busy_timeout = 0") + try: + connection.execute("BEGIN IMMEDIATE") + except sqlite3.OperationalError as exc: + if not sqlite_busy(exc): + raise + blocked = True + finally: + connection.execute(f"PRAGMA busy_timeout = {busy_timeout}") + if not blocked: + try: + if inspection_unnecessary is not None and inspection_unnecessary(): + return True + return bool(inspected and validate()) + except BaseException: + connection.rollback() + raise + + connection.execute("BEGIN IMMEDIATE") + try: + if inspection_unnecessary is not None and inspection_unnecessary(): + return True + except BaseException: + connection.rollback() + raise + connection.rollback() + + +def begin_immediate_with_target_inspection( + connection: sqlite3.Connection, + inspect: Callable[[], bool], + inspection_unnecessary: Callable[[], bool] | None = None, +) -> bool: + """Inspect a mutable target while holding the writer transaction.""" + connection.execute("BEGIN IMMEDIATE") + try: + if inspection_unnecessary is not None and inspection_unnecessary(): + return True + return inspect() + except BaseException: + connection.rollback() + raise + + def apply_migrations(connection: sqlite3.Connection) -> None: apply_schema_migrations(connection, MIGRATIONS, now, backfill_security_targets) @@ -271,7 +351,13 @@ def inspect_target(target_path: str) -> dict[str, Any]: } -def resolve_git_commit(target: Path, revision: str, label: str) -> str: +def resolve_git_commit( + target: Path, + revision: str, + label: str, + *, + local_objects_only: bool = False, +) -> str: value = optional_text(revision, maximum=512) if not value: raise SystemExit(f"{label} is required.") @@ -281,12 +367,254 @@ def resolve_git_commit(target: Path, revision: str, label: str) -> str: "--verify", "--end-of-options", f"{value}^{{commit}}", + local_objects_only=local_objects_only, ) if resolved is None: raise SystemExit(f"{label} does not resolve to a local Git commit: {value}") return resolved +def is_canonical_git_object_id(value: Any, object_id_length: int) -> bool: + return ( + isinstance(value, str) + and len(value) == object_id_length + and all(character in "0123456789abcdef" for character in value) + ) + + +def require_committed_diff_digest( + target: Path, + base: str, + head: str, + selected_digest: str | None, +) -> str: + return require_committed_diff_snapshot(target, base, head, selected_digest)[0] + + +def require_committed_diff_snapshot( + target: Path, + base: str, + head: str, + selected_digest: str | None, +) -> tuple[str, str]: + current_digest, object_identity = committed_diff_content_snapshot(target, base, head) + if selected_digest is not None and selected_digest != current_digest: + raise SystemExit( + "The committed changes selected for review no longer produce the same " + "diff. Select the changes to review again." + ) + return current_digest, object_identity + + +class ResolvedDiffTargetError(SystemExit): + def __init__( + self, + message: str, + *, + kind: str, + base_revision: str | None, + head_revision: str, + ) -> None: + super().__init__(message) + self.kind = kind + self.base_revision = base_revision + self.head_revision = head_revision + + +def require_resolved_committed_diff_target( + target: Path, + kind: str, + base: str, + head: str, + content_digest: str | None, + *, + persisted_base: str | None, +) -> dict[str, str]: + return require_resolved_committed_diff_snapshot( + target, + kind, + base, + head, + content_digest, + persisted_base=persisted_base, + )[0] + + +def require_resolved_committed_diff_snapshot( + target: Path, + kind: str, + base: str, + head: str, + content_digest: str | None, + *, + persisted_base: str | None, +) -> tuple[dict[str, str], str]: + try: + digest, object_identity = require_committed_diff_snapshot( + target, + base, + head, + content_digest, + ) + except SystemExit as exc: + raise ResolvedDiffTargetError( + str(exc), + kind=kind, + base_revision=persisted_base, + head_revision=head, + ) from None + return ( + { + "kind": kind, + "baseRevision": base, + "headRevision": head, + "contentDigest": digest, + }, + object_identity, + ) + + +def resolve_committed_diff_coordinates( + target: Path, + kind: str, + base_revision: str | None, + head_revision: str | None, + *, + allow_equal_range: bool = False, + local_objects_only: bool = False, +) -> tuple[str, str, str | None]: + if kind == "commit": + head = resolve_git_commit( + target, + head_revision or "", + "Commit", + local_objects_only=local_objects_only, + ) + commit = git_bytes( + target, + "cat-file", + "-p", + head, + local_objects_only=local_objects_only, + ) + if commit is None: + raise SystemExit(f"Commit is not available in the local checkout: {head}") + parent_line = next( + (line for line in commit.splitlines() if line.startswith(b"parent ")), + None, + ) + if parent_line is None: + parent = empty_git_tree(target) + else: + parent = resolve_git_commit( + target, + parent_line.removeprefix(b"parent ").decode("ascii").strip(), + "Commit parent", + local_objects_only=local_objects_only, + ) + if base_revision and base_revision != parent: + supplied_base = ( + base_revision + if base_revision in EMPTY_GIT_TREES.values() + else resolve_git_commit( + target, + base_revision, + "Commit base", + local_objects_only=local_objects_only, + ) + ) + if supplied_base != parent: + raise SystemExit("Commit base revision must match the selected commit's parent.") + return parent, head, parent if base_revision is not None else None + if kind != "range": + raise ValueError(f"Unsupported committed diff kind: {kind}") + base = resolve_git_commit( + target, + base_revision or "", + "Base revision", + local_objects_only=local_objects_only, + ) + head = resolve_git_commit( + target, + head_revision or "", + "Head revision", + local_objects_only=local_objects_only, + ) + if base == head and not allow_equal_range: + raise SystemExit("Base and head revisions must identify different commits.") + return base, head, base + + +def committed_diff_lock_identity( + target: Path, + kind: str, + base: str, + head: str, + object_identity: str | None = None, +) -> tuple[int, int, str, str, str, str]: + metadata = target.stat() + return ( + metadata.st_dev, + metadata.st_ino, + kind, + base, + head, + object_identity + if object_identity is not None + else committed_diff_object_identity(target, base, head), + ) + + +def committed_diff_lock_validator( + target: Path, + diff_target: dict[str, str], + object_identity: str, + base_revision: str | None, + head_revision: str | None, + *, + allow_equal_range: bool = False, +) -> tuple[ + Callable[[Path, dict[str, str], str], bool], + Callable[[], bool], +]: + target_path = str(target) + kind = diff_target["kind"] + inspected_identity = committed_diff_lock_identity( + target, + kind, + diff_target["baseRevision"], + diff_target["headRevision"], + object_identity, + ) + + def matches_inspected_identity( + target: Path, + diff_target: dict[str, str], + object_identity: str, + ) -> bool: + return committed_diff_lock_identity( + target, + diff_target["kind"], + diff_target["baseRevision"], + diff_target["headRevision"], + object_identity, + ) == inspected_identity + + def validate() -> bool: + target = require_remediation_target(target_path) + base, head, _ = resolve_committed_diff_coordinates( + target, + kind, + base_revision, + head_revision, + allow_equal_range=allow_equal_range, + local_objects_only=True, + ) + return committed_diff_lock_identity(target, kind, base, head) == inspected_identity + + return matches_inspected_identity, validate + + def require_diff_target( target: Path, kind: str | None, @@ -317,37 +645,96 @@ def require_diff_target( "headRevision": current_head, "contentDigest": current_digest, } - if kind == "commit": - head = resolve_git_commit(target, head_revision or "", "Commit") - commit = git_bytes(target, "cat-file", "-p", head) - if commit is None: - raise SystemExit(f"Commit is not available in the local checkout: {head}") - parent_line = next( - (line for line in commit.splitlines() if line.startswith(b"parent ")), + base, head, persisted_base = resolve_committed_diff_coordinates( + target, + kind, + base_revision, + head_revision, + ) + return require_resolved_committed_diff_snapshot( + target, + kind, + base, + head, + content_digest, + persisted_base=persisted_base, + )[0] + + +def require_diff_target_snapshot( + target: Path, + kind: str | None, + base_revision: str | None, + head_revision: str | None, + content_digest: str | None, +) -> tuple[dict[str, str], str | None]: + if kind not in {"commit", "range"}: + return ( + require_diff_target( + target, + kind, + base_revision, + head_revision, + content_digest, + ), None, ) - if parent_line is None: - parent = EMPTY_GIT_TREE - else: - parent = resolve_git_commit( - target, - parent_line.removeprefix(b"parent ").decode("ascii").strip(), - "Commit parent", - ) - if base_revision and base_revision != parent: - supplied_base = ( - base_revision - if base_revision == EMPTY_GIT_TREE - else resolve_git_commit(target, base_revision, "Commit base") + require_review_changes_target(target) + base, head, persisted_base = resolve_committed_diff_coordinates( + target, + kind, + base_revision, + head_revision, + ) + return require_resolved_committed_diff_snapshot( + target, + kind, + base, + head, + content_digest, + persisted_base=persisted_base, + ) + + +def require_registered_diff_target( + target: Path, + diff_target: dict[str, str], +) -> dict[str, str]: + return require_registered_diff_target_snapshot(target, diff_target)[0] + + +def require_registered_diff_target_snapshot( + target: Path, + diff_target: dict[str, str], +) -> tuple[dict[str, str], str | None]: + kind = diff_target["kind"] + base = resolve_git_commit(target, diff_target["baseRevision"], "Base revision") + head = resolve_git_commit(target, diff_target["headRevision"], "Head revision") + if kind == "working_tree": + if head != require_review_changes_target(target): + raise SystemExit("Working-tree HEAD changed before the scan started.") + current_digest = worktree_content_digest(target) + if current_digest != diff_target["contentDigest"]: + raise SystemExit( + "Working-tree contents changed after they were selected. " + "Select Uncommitted changes again." ) - if supplied_base != parent: - raise SystemExit("Commit base revision must match the selected commit's parent.") - return {"kind": kind, "baseRevision": parent, "headRevision": head} - base = resolve_git_commit(target, base_revision or "", "Base revision") - head = resolve_git_commit(target, head_revision or "", "Head revision") - if base == head: - raise SystemExit("Base and head revisions must identify different commits.") - return {"kind": kind, "baseRevision": base, "headRevision": head} + else: + current_digest, object_identity = require_committed_diff_snapshot( + target, + base, + head, + diff_target["contentDigest"], + ) + return ( + { + "kind": kind, + "baseRevision": base, + "headRevision": head, + "contentDigest": current_digest, + }, + None if kind == "working_tree" else object_identity, + ) def inspect_setup_values( @@ -358,6 +745,8 @@ def inspect_setup_values( diff_base_revision: str | None, diff_head_revision: str | None, diff_content_digest: str | None, + *, + include_committed_identity: bool = False, ) -> dict[str, Any]: target = require_target(target_path) require_scannable_target(target) @@ -374,8 +763,8 @@ def inspect_setup_values( ) ): raise SystemExit("A Git diff target requires Review changes mode.") - diff_target = ( - require_diff_target( + diff_target, committed_identity = ( + require_diff_target_snapshot( target, diff_target_kind, diff_base_revision, @@ -383,13 +772,16 @@ def inspect_setup_values( diff_content_digest, ) if mode == "diff" - else None + else (None, None) ) - return { + inspected = { "diffTarget": diff_target, "scope": normalized_scope, "target": inspect_target(str(target)), } + if include_committed_identity: + inspected["committedDiffIdentity"] = committed_identity + return inspected def inspect_setup(args: argparse.Namespace) -> dict[str, Any]: @@ -509,7 +901,7 @@ def workbench_completion_binding(scan: sqlite3.Row, completed_at: str) -> dict[s if scan["mode"] == "diff": target["baseRevision"] = scan["diff_base_revision"] target["headRevision"] = scan["diff_head_revision"] - if scan["diff_target_kind"] == "working_tree" and scan["diff_content_digest"]: + if scan["diff_content_digest"]: target["snapshotDigest"] = scan["diff_content_digest"] else: if scan["target_revision"] != "unversioned": @@ -579,11 +971,11 @@ def verify_manifest_binding(scan: sqlite3.Row, manifest: dict[str, Any]) -> None ) if ( scan["diff_target_kind"] == "working_tree" - and target.get("snapshotDigest") != scan["diff_content_digest"] - ): + or scan["diff_content_digest"] is not None + ) and target.get("snapshotDigest") != scan["diff_content_digest"]: raise SystemExit( "scan-manifest.json target snapshotDigest must match the selected " - "working-tree contents." + "reviewed contents." ) scope = manifest_scan.get("scope") if not isinstance(scope, dict): @@ -677,6 +1069,9 @@ def create_workspace(connection: sqlite3.Connection, args: argparse.Namespace) - diff_content_digest = ( optional_text(args.diff_content_digest, maximum=128) if args.mode == "diff" else None ) + inspected = None + inspection_error = None + inspected_target_metadata = None if target_path: try: inspected = inspect_setup_values( @@ -695,8 +1090,18 @@ def create_workspace(connection: sqlite3.Connection, args: argparse.Namespace) - diff_base_revision = inspected["diffTarget"]["baseRevision"] diff_head_revision = inspected["diffTarget"]["headRevision"] diff_content_digest = inspected["diffTarget"].get("contentDigest") - except SystemExit: - pass + except SystemExit as exc: + inspection_error = str(exc) + if isinstance(exc, ResolvedDiffTargetError): + diff_target_kind = exc.kind + diff_base_revision = exc.base_revision + diff_head_revision = exc.head_revision + try: + inspected_target = require_target(target_path) + target_path = str(inspected_target) + inspected_target_metadata = git_target_metadata(inspected_target) + except SystemExit: + pass with connection: target_id = ( ensure_security_target(connection, target_path) if target_path is not None else None @@ -728,7 +1133,15 @@ def create_workspace(connection: sqlite3.Connection, args: argparse.Namespace) - timestamp, ), ) - return workspace_state(connection, workspace_id) + result = inspected_workspace_state( + connection, + workspace_id, + expected_updated_at=timestamp, + inspection_error=inspection_error, + inspected_setup=inspected, + inspected_target_metadata=inspected_target_metadata, + ) + return result def save_workspace(connection: sqlite3.Connection, args: argparse.Namespace) -> dict[str, Any]: @@ -747,6 +1160,63 @@ def save_workspace(connection: sqlite3.Connection, args: argparse.Namespace) -> target = Path(inspected["target"]["targetPath"]) scope = inspected["scope"] target_path = str(target) + diff_target = inspected["diffTarget"] + stored_committed_selection = ( + diff_target is not None + and diff_target["kind"] != "working_tree" + and workspace["target_path"] == target_path + and workspace["diff_target_kind"] == diff_target["kind"] + ) + if stored_committed_selection and workspace["submitted"]: + object_id_length = len(empty_git_tree(target)) + if ( + not is_canonical_git_object_id( + workspace["diff_head_revision"], object_id_length + ) + or ( + workspace["diff_base_revision"] is not None + and not is_canonical_git_object_id( + workspace["diff_base_revision"], object_id_length + ) + ) + or ( + diff_target["kind"] == "range" + and workspace["diff_base_revision"] is None + ) + ): + raise SystemExit( + "The committed changes selected for review no longer produce the same " + "diff. Select the changes to review again." + ) + same_committed_identity = ( + diff_target is not None + and diff_target["kind"] != "working_tree" + and workspace["target_path"] == target_path + and workspace["diff_target_kind"] == diff_target["kind"] + and workspace["diff_head_revision"] == diff_target["headRevision"] + and ( + diff_target["kind"] == "commit" + or workspace["diff_base_revision"] == diff_target["baseRevision"] + ) + ) + if same_committed_identity: + stored_digest = workspace["diff_content_digest"] + base_compatible = workspace["diff_base_revision"] == diff_target[ + "baseRevision" + ] or ( + diff_target["kind"] == "commit" + and workspace["diff_base_revision"] is None + and stored_digest is None + ) + digest_compatible = stored_digest == diff_target["contentDigest"] or ( + stored_digest is None + and args.diff_content_digest == diff_target["contentDigest"] + ) + if not base_compatible or not digest_compatible: + raise SystemExit( + "The committed changes selected for review no longer produce the same " + "diff. Select the changes to review again." + ) target_changed = workspace["target_path"] != target_path target_title = target.name if target_changed else workspace["target_title"] target_summary = ( @@ -756,7 +1226,6 @@ def save_workspace(connection: sqlite3.Connection, args: argparse.Namespace) -> if target_changed else workspace["target_summary"] ) - diff_target = inspected["diffTarget"] if diff_target and not target_summary: target_summary = diff_target_summary(diff_target) timestamp = now() @@ -791,7 +1260,13 @@ def save_workspace(connection: sqlite3.Connection, args: argparse.Namespace) -> raise SystemExit( "This workspace already has a scan. Open a new workspace to change setup." ) - return workspace_state(connection, workspace["id"]) + result = inspected_workspace_state( + connection, + workspace["id"], + expected_updated_at=timestamp, + inspected_setup=inspected, + ) + return result def scan_target_root(scan_root: str | None, target: Path) -> Path: @@ -809,14 +1284,18 @@ def start_scan(connection: sqlite3.Connection, args: argparse.Namespace) -> dict workspace = require_workspace(connection, workspace_id) if not workspace["submitted"] or not workspace["target_path"]: raise SystemExit("Save the Codex Security setup before starting the scan.") - active = connection.execute( - """ - SELECT * - FROM scans - WHERE workspace_id = ? AND status = 'running' AND canceled_at IS NULL - """, - (workspace["id"],), - ).fetchone() + + def active_scan() -> sqlite3.Row | None: + return connection.execute( + """ + SELECT * + FROM scans + WHERE workspace_id = ? AND status = 'running' AND canceled_at IS NULL + """, + (workspace_id,), + ).fetchone() + + active = active_scan() if active is not None: return workspace_state(connection, workspace["id"]) workspace_version = workspace["updated_at"] @@ -827,8 +1306,9 @@ def start_scan(connection: sqlite3.Connection, args: argparse.Namespace) -> dict target_metadata = target.stat() scope = require_scope(workspace["default_scope"], workspace["default_mode"], target) diff_target = None + committed_object_identity = None if workspace["default_mode"] == "diff": - diff_target = require_diff_target( + diff_target, committed_object_identity = require_diff_target_snapshot( target, workspace["diff_target_kind"], workspace["diff_base_revision"], @@ -848,31 +1328,89 @@ def start_scan(connection: sqlite3.Connection, args: argparse.Namespace) -> dict diff_target, metadata=target_metadata, ) + match_committed_diff_identity: ( + Callable[[Path, dict[str, str], str], bool] | None + ) = None + validate_committed_diff: Callable[[], bool] | None = None + if diff_target is not None and diff_target["kind"] in {"commit", "range"}: + assert committed_object_identity is not None + match_committed_diff_identity, validate_committed_diff = ( + committed_diff_lock_validator( + target, + diff_target, + committed_object_identity, + workspace["diff_base_revision"], + workspace["diff_head_revision"], + ) + ) + + def target_matches_initial_snapshot() -> bool: + current_target = require_remediation_target(str(target)) + current_target_metadata = current_target.stat() + if (current_target_metadata.st_dev, current_target_metadata.st_ino) != ( + target_metadata.st_dev, + target_metadata.st_ino, + ): + return False + current_diff_target, current_object_identity = ( + require_diff_target_snapshot( + current_target, + workspace["diff_target_kind"], + workspace["diff_base_revision"], + workspace["diff_head_revision"], + workspace["diff_content_digest"], + ) + if workspace["default_mode"] == "diff" + else (None, None) + ) + matches = ( + scan_target_identity( + current_target, + current_diff_target, + metadata=current_target_metadata, + ) + == target_identity + and scan_diff_identity(current_diff_target) == scan_diff_identity(diff_target) + ) + if matches and match_committed_diff_identity is not None: + assert current_diff_target is not None + assert current_object_identity is not None + matches = match_committed_diff_identity( + current_target, + current_diff_target, + current_object_identity, + ) + return matches + target_root = scan_target_root(args.scan_root, target) target_root.mkdir(parents=True, exist_ok=True) if manages_transaction: - connection.execute("BEGIN IMMEDIATE") + if validate_committed_diff is None: + target_is_current = begin_immediate_with_target_inspection( + connection, + target_matches_initial_snapshot, + active_scan, + ) + else: + target_is_current = begin_immediate_after_external_inspection( + connection, + target_matches_initial_snapshot, + validate_committed_diff, + active_scan, + ) + else: + target_is_current = ( + True if active_scan() is not None else target_matches_initial_snapshot() + ) workspace = require_workspace(connection, workspace_id) - active = connection.execute( - """ - SELECT * - FROM scans - WHERE workspace_id = ? AND status = 'running' AND canceled_at IS NULL - """, - (workspace["id"],), - ).fetchone() + active = active_scan() if active is not None: if manages_transaction: connection.commit() return workspace_state(connection, workspace["id"]) if workspace["updated_at"] != workspace_version: raise SystemExit("Codex Security setup changed while the scan was starting. Try again.") - current_target = require_remediation_target(str(target)) - current_target_metadata = current_target.stat() - if (current_target_metadata.st_dev, current_target_metadata.st_ino) != ( - target_metadata.st_dev, - target_metadata.st_ino, - ): + if not target_is_current: raise SystemExit( "The selected scan target changed while the scan was starting. Try again." ) @@ -938,11 +1476,13 @@ def _start_prompt_driven_scan( args.diff_base_revision, args.diff_head_revision, args.diff_content_digest, + include_committed_identity=True, ) target = Path(inspected["target"]["targetPath"]) target_path = str(target) scope = inspected["scope"] diff_target = inspected["diffTarget"] + committed_object_identity = inspected["committedDiffIdentity"] user_context = user_context_argument(args) target_summary = optional_text(args.target_summary, maximum=2400) if diff_target is not None and not target_summary: @@ -952,13 +1492,26 @@ def _start_prompt_driven_scan( ) diff_identity = scan_diff_identity(diff_target) target_identity = scan_target_identity(target, diff_target) - target_root = scan_target_root(args.scan_root, target) + match_committed_diff_identity: ( + Callable[[Path, dict[str, str], str], bool] | None + ) = None + validate_committed_diff: Callable[[], bool] | None = None + if diff_target is not None and diff_target["kind"] in {"commit", "range"}: + assert committed_object_identity is not None + match_committed_diff_identity, validate_committed_diff = ( + committed_diff_lock_validator( + target, + diff_target, + committed_object_identity, + args.diff_base_revision, + args.diff_head_revision, + ) + ) - connection.execute("BEGIN IMMEDIATE") - try: + def target_matches_initial_snapshot() -> bool: current_target = require_remediation_target(target_path) - current_diff_target = ( - require_diff_target( + current_diff_target, current_object_identity = ( + require_diff_target_snapshot( current_target, args.diff_target_kind, args.diff_base_revision, @@ -966,12 +1519,40 @@ def _start_prompt_driven_scan( args.diff_content_digest, ) if args.mode == "diff" - else None + else (None, None) ) - if ( - scan_target_identity(current_target, current_diff_target) != target_identity - or scan_diff_identity(current_diff_target) != diff_identity - ): + matches = ( + scan_target_identity(current_target, current_diff_target) == target_identity + and scan_diff_identity(current_diff_target) == diff_identity + ) + if matches and match_committed_diff_identity is not None: + assert current_diff_target is not None + assert current_object_identity is not None + matches = match_committed_diff_identity( + current_target, + current_diff_target, + current_object_identity, + ) + return matches + + target_root = scan_target_root(args.scan_root, target) + allow_legacy_digest = int( + diff_target is not None + and diff_target["kind"] in {"commit", "range"} + and args.diff_content_digest is None + ) + if validate_committed_diff is None: + target_is_current = begin_immediate_with_target_inspection( + connection, target_matches_initial_snapshot + ) + else: + target_is_current = begin_immediate_after_external_inspection( + connection, + target_matches_initial_snapshot, + validate_committed_diff, + ) + try: + if not target_is_current: raise SystemExit( "The selected scan target changed while the scan was starting. Try again." ) @@ -983,7 +1564,17 @@ def _start_prompt_driven_scan( AND workspaces.default_scope = ? AND workspaces.default_mode = ? AND workspaces.user_context IS ? AND workspaces.target_summary IS ? AND workspaces.diff_target_kind IS ? AND workspaces.diff_base_revision IS ? - AND workspaces.diff_head_revision IS ? AND workspaces.diff_content_digest IS ? + AND workspaces.diff_head_revision IS ? + AND ( + ( + workspaces.diff_content_digest IS ? + AND scans.diff_content_digest IS ? + ) + OR ( + ? = 1 AND workspaces.diff_content_digest IS NULL + AND scans.diff_content_digest IS NULL + ) + ) AND workspaces.submitted = 1 AND scans.target_revision = ? AND scans.target_snapshot_digest IS ? AND scans.target_device = ? AND scans.target_inode = ? AND scans.status = 'running' @@ -995,7 +1586,10 @@ def _start_prompt_driven_scan( AND scans.continuation_thread_id = ? ) ) - ORDER BY scans.updated_at DESC, scans.started_at DESC, scans.id LIMIT 1 + ORDER BY + CASE WHEN workspaces.diff_content_digest IS ? + AND scans.diff_content_digest IS ? THEN 0 ELSE 1 END, + scans.updated_at DESC, scans.started_at DESC, scans.id LIMIT 1 """, ( thread_id, @@ -1004,11 +1598,16 @@ def _start_prompt_driven_scan( args.mode, user_context, target_summary, - *diff_identity, + *diff_identity[:3], + diff_identity[3], + diff_identity[3], + allow_legacy_digest, *target_identity, int(headless_standard), int(headless_standard), thread_id, + diff_identity[3], + diff_identity[3], ), ).fetchone() if existing is not None: @@ -1466,7 +2065,6 @@ def add_warning() -> None: if warning not in items: items.append(warning) - add_warning() scan_dir = require_canonical_scan_directory(Path(scan["scan_dir"])) completion_timestamp = now() completion_binding = workbench_completion_binding(scan, completion_timestamp) @@ -1661,6 +2259,7 @@ def register_cli_scan(connection: sqlite3.Connection, args: argparse.Namespace) paths = requested_target["paths"] scope = paths[0] if len(paths) == 1 else "." diff_target = None + committed_object_identity = None if requested_target["kind"] in {"refs", "working_tree"}: current_head = require_review_changes_target(repository) base = resolve_git_commit(repository, requested_target["base"], "Base revision") @@ -1674,6 +2273,11 @@ def register_cli_scan(connection: sqlite3.Connection, args: argparse.Namespace) if head != current_head: raise SystemExit("Working-tree HEAD changed before the scan started.") diff_target["contentDigest"] = worktree_content_digest(repository) + else: + ( + diff_target["contentDigest"], + committed_object_identity, + ) = committed_diff_content_snapshot(repository, base, head) mode = "diff" if diff_target is not None else recipe["mode"] target_identity = scan_target_identity(repository, diff_target) scope_file_count = ( @@ -1695,8 +2299,59 @@ def register_cli_scan(connection: sqlite3.Connection, args: argparse.Namespace) scan_id = str(uuid.uuid4()) workspace_id = str(uuid.uuid4()) - connection.execute("BEGIN IMMEDIATE") + match_committed_diff_identity: ( + Callable[[Path, dict[str, str], str], bool] | None + ) = None + validate_committed_diff: Callable[[], bool] | None = None + if diff_target is not None and diff_target["kind"] == "range": + assert committed_object_identity is not None + match_committed_diff_identity, validate_committed_diff = ( + committed_diff_lock_validator( + repository, + diff_target, + committed_object_identity, + requested_target["base"], + requested_target["head"], + allow_equal_range=True, + ) + ) + + def target_matches_initial_snapshot() -> bool: + current_repository = require_remediation_target(str(repository)) + current_diff_target, current_object_identity = ( + require_registered_diff_target_snapshot(current_repository, diff_target) + if diff_target is not None + else (None, None) + ) + matches = ( + scan_target_identity(current_repository, current_diff_target) == target_identity + and scan_diff_identity(current_diff_target) == scan_diff_identity(diff_target) + ) + if matches and match_committed_diff_identity is not None: + assert current_diff_target is not None + assert current_object_identity is not None + matches = match_committed_diff_identity( + current_repository, + current_diff_target, + current_object_identity, + ) + return matches + + if validate_committed_diff is None: + target_is_current = begin_immediate_with_target_inspection( + connection, target_matches_initial_snapshot + ) + else: + target_is_current = begin_immediate_after_external_inspection( + connection, + target_matches_initial_snapshot, + validate_committed_diff, + ) try: + if not target_is_current: + raise SystemExit( + "The selected scan target changed while the scan was starting. Try again." + ) archive_scan(connection, args, scan_dir, timestamp, require_canonical_scan_directory) target_id = ensure_security_target(connection, str(repository)) if parent_scan_id is not None: @@ -3032,6 +3687,63 @@ def workspace_state( refresh_stopped: bool = False, ) -> dict[str, Any]: workspace = require_workspace(connection, workspace_id) + return render_workspace_state( + connection, + workspace, + result_scan_id=result_scan_id, + thread_id=thread_id, + refresh_stopped=refresh_stopped, + ) + + +def inspected_workspace_state( + connection: sqlite3.Connection, + workspace_id: str, + *, + expected_updated_at: str, + inspection_error: str | None = None, + inspected_setup: dict[str, Any] | None, + inspected_target_metadata: dict[str, Any] | None = None, +) -> dict[str, Any]: + manages_transaction = not connection.in_transaction + if manages_transaction: + connection.execute("BEGIN IMMEDIATE") + try: + workspace = require_workspace(connection, workspace_id) + if ( + workspace["updated_at"] != expected_updated_at + or workspace["active_scan_id"] is not None + ): + raise SystemExit("Codex Security setup changed while it was being saved. Try again.") + result = render_workspace_state( + connection, + workspace, + inspection_complete=True, + inspection_error=inspection_error, + inspected_setup=inspected_setup, + inspected_target_metadata=inspected_target_metadata, + ) + if manages_transaction: + connection.commit() + return result + except BaseException: + if manages_transaction: + connection.rollback() + raise + + +def render_workspace_state( + connection: sqlite3.Connection, + workspace: sqlite3.Row, + *, + result_scan_id: str | None = None, + thread_id: str | None = None, + refresh_stopped: bool = False, + inspection_complete: bool = False, + inspection_error: str | None = None, + inspected_setup: dict[str, Any] | None = None, + inspected_target_metadata: dict[str, Any] | None = None, +) -> dict[str, Any]: if thread_id is not None and workspace["thread_id"] != optional_text(thread_id, maximum=512): raise SystemExit("Codex Security workspace not found in this thread.") persisted_diff_target = stored_diff_target(workspace) @@ -3060,7 +3772,13 @@ def workspace_state( target_metadata = None setup_error = None validated_diff_target = None - if workspace["target_path"]: + if inspected_setup is not None: + target_metadata = inspected_setup["target"]["targetMetadata"] + validated_diff_target = inspected_setup["diffTarget"] + elif inspection_complete: + setup_error = inspection_error + target_metadata = inspected_target_metadata + elif workspace["target_path"]: try: inspected = inspect_setup_values( workspace["target_path"], diff --git a/sdk/typescript/_bundled_plugin/scripts/workbench_target.py b/sdk/typescript/_bundled_plugin/scripts/workbench_target.py index 3e26d5acd..9968991ee 100644 --- a/sdk/typescript/_bundled_plugin/scripts/workbench_target.py +++ b/sdk/typescript/_bundled_plugin/scripts/workbench_target.py @@ -4,19 +4,24 @@ import argparse import hashlib +import io import os import shutil import sqlite3 import stat import subprocess import sys +import tempfile from pathlib import Path -from typing import Any +from typing import IO, Any # Some plugin hosts launch Python with safe-path isolation enabled. sys.path.insert(0, str(Path(__file__).resolve().parent)) from filesystem_identity import stored_filesystem_identity_matches -from workbench_constants import GIT_REPOSITORY_ENVIRONMENT +from workbench_constants import ( + EMPTY_GIT_TREES, + GIT_REPOSITORY_ENVIRONMENT, +) def git_output( @@ -24,8 +29,18 @@ def git_output( *args: str, git_dir: Path | None = None, work_tree: Path | None = None, + local_objects_only: bool = False, + object_directory: Path | None = None, ) -> str | None: - completed = git_command(target, *args, text=False, git_dir=git_dir, work_tree=work_tree) + completed = git_command( + target, + *args, + text=False, + git_dir=git_dir, + work_tree=work_tree, + local_objects_only=local_objects_only, + object_directory=object_directory, + ) output = os.fsdecode(completed.stdout).strip() return output if completed.returncode == 0 and output else None @@ -35,11 +50,117 @@ def git_bytes( *args: str, git_dir: Path | None = None, work_tree: Path | None = None, + local_objects_only: bool = False, ) -> bytes | None: - completed = git_command(target, *args, text=False, git_dir=git_dir, work_tree=work_tree) + completed = git_command( + target, + *args, + text=False, + git_dir=git_dir, + work_tree=work_tree, + local_objects_only=local_objects_only, + ) return completed.stdout if completed.returncode == 0 else None +def read_stream_nul_field(stream: IO[bytes]) -> bytes | None: + """Read one NUL-terminated field, returning ``None`` only at clean EOF.""" + field = bytearray() + while character := stream.read(1): + if character == b"\0": + return bytes(field) + field.extend(character) + if field: + raise ValueError("missing NUL terminator") + return None + + +def write_committed_diff_object_requests( + metadata: IO[bytes], + requests: IO[bytes], +) -> None: + """Write ordered changed-blob requests from NUL-framed raw diff records.""" + seen: set[bytes] = set() + while (header := read_stream_nul_field(metadata)) is not None: + if not header or not read_stream_nul_field(metadata): + raise ValueError("invalid raw Git diff record") + fields = header.split() + if len(fields) != 5 or not fields[0].startswith(b":"): + raise ValueError("invalid raw Git diff record") + for mode, object_name in ( + (fields[0][1:], fields[2]), + (fields[1], fields[3]), + ): + if mode in {b"000000", b"160000"}: + continue + if ( + len(object_name) not in {40, 64} + or any( + character not in b"0123456789abcdef" + for character in object_name + ) + ): + raise ValueError("invalid raw Git diff record") + if object_name in seen: + continue + seen.add(object_name) + requests.write(object_name + b"\0") + + +def validate_git_batch_blob_stream( + requests: IO[bytes], + output: IO[bytes], +) -> None: + """Require one exact, ordered blob response for every object request.""" + while (expected_object := read_stream_nul_field(requests)) is not None: + if not expected_object: + raise ValueError("invalid empty object request") + if _read_git_batch_blob(output, expected_object, require_object_match=True) is None: + raise ValueError("missing batch object") + if output.read(1): + raise ValueError("unexpected batch response") + + +def _read_git_batch_blob( + output: IO[bytes], + expected_request: bytes, + *, + require_object_match: bool, + collect: bool = False, +) -> bytes | None: + """Read one strict newline-framed response for a NUL-terminated request.""" + start = output.tell() + missing = expected_request + b" missing\n" + if output.read(len(missing)) == missing: + return None + output.seek(start) + header = output.readline() + if not header.endswith(b"\n"): + raise ValueError("unterminated batch header") + fields = header[:-1].split(b" ") + if ( + len(fields) != 3 + or len(fields[0]) not in {40, 64} + or any(character not in b"0123456789abcdef" for character in fields[0]) + or (require_object_match and fields[0] != expected_request) + or fields[1] != b"blob" + or not fields[2].isdigit() + ): + raise ValueError("invalid batch response") + remaining = int(fields[2]) + chunks: list[bytes] = [] + while remaining: + chunk = output.read(min(1024 * 1024, remaining)) + if not chunk: + raise ValueError("truncated blob response") + if collect: + chunks.append(chunk) + remaining -= len(chunk) + if output.read(1) != b"\n": + raise ValueError("missing blob terminator") + return b"".join(chunks) + + def git_blob_bytes( target: Path, object_names: list[str], @@ -47,77 +168,45 @@ def git_blob_bytes( git_dir: Path | None = None, work_tree: Path | None = None, ) -> list[bytes | None]: - """Read ordered raw blobs with one NUL-framed ``git cat-file --batch`` call.""" + """Read ordered raw blobs with one NUL-request ``git cat-file --batch`` call.""" if not object_names: return [] - request = b"\0".join(os.fsencode(name) for name in object_names) + b"\0" + encoded_names = [os.fsencode(name) for name in object_names] + request = b"\0".join(encoded_names) + b"\0" completed = git_command( target, "cat-file", "--batch", - "-Z", + "-z", text=False, input_data=request, git_dir=git_dir, work_tree=work_tree, + local_objects_only=True, ) if completed.returncode != 0: return [None] * len(object_names) try: - return _decode_git_batch_blobs(completed.stdout, len(object_names)) + return _decode_git_batch_blobs(completed.stdout, encoded_names) except ValueError: return [None] * len(object_names) -def _decode_git_batch_blobs(output: bytes, count: int) -> list[bytes | None]: - """Decode ordered ``cat-file --batch -Z`` records without scanning blob bytes.""" - blobs: list[bytes | None] = [] - offset = 0 - for _ in range(count): - header, offset = _read_nul_field(output, offset) - size = _git_batch_blob_size(header) - if size is None: - blobs.append(None) - continue - blob, offset = _read_sized_nul_field(output, offset, size) - blobs.append(blob) - return blobs - - -def _read_nul_field(output: bytes, offset: int) -> tuple[bytes, int]: - """Read one NUL-terminated protocol field and return the next offset.""" - end = output.find(b"\0", offset) - if end < 0: - raise ValueError("missing NUL terminator") - return output[offset:end], end + 1 - - -def _git_batch_blob_size(header: bytes) -> int | None: - """Return a blob header's byte count, or ``None`` for a non-blob record.""" - fields = header.rsplit(b" ", 2) - if len(fields) != 3 or fields[1] != b"blob": - return None - try: - size = int(fields[2]) - except ValueError as error: - raise ValueError("invalid blob size") from error - if size < 0: - raise ValueError("invalid blob size") - return size - - -def _read_sized_nul_field( +def _decode_git_batch_blobs( output: bytes, - offset: int, - size: int, -) -> tuple[bytes, int]: - """Read exactly ``size`` blob bytes followed by one NUL record terminator.""" - end = offset + size - if output[end : end + 1] != b"\0": - raise ValueError("missing blob terminator") - return output[offset:end], end + 1 + expected_requests: list[bytes], +) -> list[bytes | None]: + """Decode exactly one strict newline-framed response per ordered request.""" + stream = io.BytesIO(output) + blobs = [ + _read_git_batch_blob(stream, request, require_object_match=False, collect=True) + for request in expected_requests + ] + if stream.read(1): + raise ValueError("unexpected batch response") + return blobs def git_command( @@ -127,12 +216,21 @@ def git_command( input_data: str | bytes | None = None, git_dir: Path | None = None, work_tree: Path | None = None, + stdin: IO[bytes] | None = None, + stdout: IO[bytes] | None = None, + local_objects_only: bool = False, + object_directory: Path | None = None, ) -> subprocess.CompletedProcess[str] | subprocess.CompletedProcess[bytes]: if (git_dir is None) != (work_tree is None): raise ValueError("git_dir and work_tree must be provided together") environment = os.environ.copy() for name in GIT_REPOSITORY_ENVIRONMENT: environment.pop(name, None) + if object_directory is not None: + environment["GIT_OBJECT_DIRECTORY"] = os.fspath(object_directory) + if local_objects_only: + environment["GIT_ALLOW_PROTOCOL"] = "" + environment["GIT_NO_LAZY_FETCH"] = "1" environment["GIT_LITERAL_PATHSPECS"] = "1" # Repository-local config is untrusted; fsmonitor may name an executable hook. command = [ @@ -151,7 +249,9 @@ def git_command( return subprocess.run( full_command, check=False, - capture_output=True, + stdin=stdin, + stdout=subprocess.PIPE if stdout is None else stdout, + stderr=subprocess.PIPE, env=environment, text=text, encoding="utf-8" if text else None, @@ -172,12 +272,393 @@ def update_digest_field(digest: Any, label: bytes, value: bytes) -> None: digest.update(value) +def update_digest_stream_field(digest: Any, label: bytes, stream: IO[bytes]) -> None: + """Hash a length-framed stream without loading it into memory.""" + digest.update(len(label).to_bytes(4, "big")) + digest.update(label) + digest.update(os.fstat(stream.fileno()).st_size.to_bytes(8, "big")) + stream.seek(0) + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + + def worktree_content_digest(target: Path) -> str: require_clean_submodule_worktrees(target) repository, pathspec = git_worktree_context(target) return worktree_content_digest_for_context(repository, pathspec) +def empty_git_tree(target: Path) -> str: + object_format = git_output(target, "rev-parse", "--show-object-format") + return EMPTY_GIT_TREES.get(object_format or "", EMPTY_GIT_TREES["sha1"]) + + +def _replacement_refs( + repository: Path, + *, + object_id_length: int, + object_directory: Path | None = None, +) -> bytes: + replacement_ref_base = os.fsencode( + os.environ.get("GIT_REPLACE_REF_BASE", "refs/replace/") + ) + replacements = git_command( + repository, + "for-each-ref", + "--sort=refname", + "--format=%(refname)%00%(objectname)", + text=False, + local_objects_only=True, + object_directory=object_directory, + ) + if replacements.returncode != 0: + raise SystemExit("Could not inspect the selected committed changes.") + selected = bytearray() + for record in replacements.stdout.splitlines(): + fields = record.split(b"\0") + if len(fields) != 2: + raise SystemExit("Could not inspect the selected committed changes.") + if not fields[0].startswith(replacement_ref_base): + continue + original_object_id = fields[0][len(replacement_ref_base) :].rsplit(b"/", 1)[-1] + if ( + len(original_object_id) != object_id_length + or any( + character not in b"0123456789abcdefABCDEF" + for character in original_object_id + ) + ): + continue + selected.extend(record) + selected.extend(b"\n") + return bytes(selected) + + +def _replacement_refs_enabled( + repository: Path, + *, + object_directory: Path | None = None, +) -> bool: + if "GIT_NO_REPLACE_OBJECTS" in os.environ: + return False + configured = git_command( + repository, + "config", + "--bool", + "--get", + "core.useReplaceRefs", + text=False, + local_objects_only=True, + object_directory=object_directory, + ) + value = configured.stdout.strip() + if configured.returncode == 1 and not value: + return True + if configured.returncode == 0 and value in {b"true", b"false"}: + return value == b"true" + raise SystemExit("Could not inspect the selected committed changes.") + + +def _create_committed_diff_view(repository: Path, view: Path) -> Path: + object_format = git_output( + repository, + "rev-parse", + "--show-object-format", + local_objects_only=True, + ) + object_directory_value = git_output( + repository, + "rev-parse", + "--path-format=absolute", + "--git-path", + "objects", + local_objects_only=True, + ) + if object_format not in {"sha1", "sha256"} or object_directory_value is None: + raise SystemExit("Could not snapshot the selected committed changes.") + object_directory = Path(object_directory_value) + if not object_directory.is_dir(): + raise SystemExit("Could not snapshot the selected committed changes.") + + object_id_length = 40 if object_format == "sha1" else 64 + replacements = _replacement_refs( + repository, + object_id_length=object_id_length, + ) + replacements_enabled = _replacement_refs_enabled(repository) + parsed_replacements: list[tuple[list[str], bytes]] = [] + for record in replacements.splitlines(): + fields = record.split(b"\0") + if ( + len(fields) != 2 + or len(fields[1]) != object_id_length + or any(character not in b"0123456789abcdef" for character in fields[1]) + ): + raise SystemExit("Could not snapshot the selected committed changes.") + refname = os.fsdecode(fields[0]) + parts = refname.split("/") + if ( + len(parts) < 2 + or parts[0] != "refs" + or "\\" in refname + or any(part in {"", ".", ".."} for part in parts) + ): + raise SystemExit("Could not snapshot the selected committed changes.") + parsed_replacements.append((parts, fields[1])) + + try: + view.mkdir(mode=0o700) + (view / "objects" / "info").mkdir(parents=True) + (view / "objects" / "pack").mkdir() + (view / "refs" / "heads").mkdir(parents=True) + repository_format_version = 0 if object_format == "sha1" else 1 + config = ( + ( + b"[extensions]\n\tobjectformat = sha256\n" + if object_format == "sha256" + else b"" + ) + + b"[core]\n\trepositoryformatversion = " + + str(repository_format_version).encode("ascii") + + b"\n\tfilemode = false\n\tbare = true\n\tuseReplaceRefs = " + + (b"true" if replacements_enabled else b"false") + + b"\n" + ) + (view / "config").write_bytes(config) + (view / "HEAD").write_bytes(b"ref: refs/heads/codex-security-snapshot\n") + for parts, object_id in parsed_replacements: + ref = view.joinpath(*parts) + ref.parent.mkdir(parents=True, exist_ok=True) + ref.write_bytes(object_id + b"\n") + except OSError as exc: + raise SystemExit("Could not snapshot the selected committed changes.") from exc + return object_directory + + +def committed_diff_content_snapshot( + target: Path, + base: str, + head: str, +) -> tuple[str, str]: + """Return a digest and identity from one frozen replacement view.""" + repository, pathspec = git_worktree_context(target) + configured_state = os.environ.get("CODEX_SECURITY_STATE_DIR") + if configured_state: + state_directory = Path(configured_state).expanduser().resolve() + state_directory.mkdir(mode=0o700, parents=True, exist_ok=True) + with tempfile.TemporaryDirectory( + prefix="codex-security-committed-view-", + dir=state_directory, + ) as directory: + return _committed_diff_content_snapshot( + repository, + pathspec, + base, + head, + Path(directory), + ) + with tempfile.TemporaryDirectory(prefix="codex-security-committed-diff-") as directory: + return _committed_diff_content_snapshot( + repository, + pathspec, + base, + head, + Path(directory), + ) + + +def committed_diff_content_digest(target: Path, base: str, head: str) -> str: + """Bind normalized committed-diff metadata to every changed blob byte.""" + return committed_diff_content_snapshot(target, base, head)[0] + + +def _committed_diff_object_identity( + repository: Path, + pathspec: str, + base: str, + head: str, + *, + object_directory: Path | None = None, +) -> str: + digest = hashlib.sha256() + update_digest_field(digest, b"format", b"codex-security-committed-objects/v1") + update_digest_field( + digest, + b"pathspec", + pathspec.encode("utf-8", errors="surrogateescape"), + ) + for label, revision in ((b"base", base), (b"head", head)): + if revision in EMPTY_GIT_TREES.values(): + tree = revision + else: + tree = git_output( + repository, + "rev-parse", + "--verify", + "--end-of-options", + f"{revision}^{{tree}}", + local_objects_only=True, + object_directory=object_directory, + ) + if tree is None: + raise SystemExit("Could not inspect the selected committed changes.") + update_digest_field(digest, label, os.fsencode(revision)) + update_digest_field(digest, label + b"-tree", os.fsencode(tree)) + + replacement_ref_base = os.environ.get("GIT_REPLACE_REF_BASE", "refs/replace/") + object_format = git_output( + repository, + "rev-parse", + "--show-object-format", + local_objects_only=True, + object_directory=object_directory, + ) + if object_format not in {"sha1", "sha256"}: + raise SystemExit("Could not inspect the selected committed changes.") + replacements_enabled = _replacement_refs_enabled( + repository, + object_directory=object_directory, + ) + replacements = _replacement_refs( + repository, + object_id_length=40 if object_format == "sha1" else 64, + object_directory=object_directory, + ) + update_digest_field( + digest, + b"replacement-ref-base", + os.fsencode(replacement_ref_base), + ) + update_digest_field( + digest, + b"replacement-objects-disabled", + os.fsencode(os.environ.get("GIT_NO_REPLACE_OBJECTS", "")), + ) + update_digest_field( + digest, + b"replacement-refs-enabled", + b"true" if replacements_enabled else b"false", + ) + update_digest_field(digest, b"replacement-refs", replacements) + return f"codex-security-committed-objects/v1:sha256:{digest.hexdigest()}" + + +def committed_diff_object_identity(target: Path, base: str, head: str) -> str: + """Bind immutable commit trees to the replacement view used by Git.""" + repository, pathspec = git_worktree_context(target) + return _committed_diff_object_identity(repository, pathspec, base, head) + + +def _committed_diff_content_snapshot( + repository: Path, + pathspec: str, + base: str, + head: str, + operation_directory: Path, +) -> tuple[str, str]: + view = operation_directory / "repository.git" + object_directory = _create_committed_diff_view(repository, view) + before = _committed_diff_object_identity( + view, + pathspec, + base, + head, + object_directory=object_directory, + ) + content_digest = _committed_diff_content_digest( + view, + pathspec, + base, + head, + operation_directory, + object_directory=object_directory, + ) + after = _committed_diff_object_identity( + view, + pathspec, + base, + head, + object_directory=object_directory, + ) + if before != after: + raise SystemExit("Could not snapshot the selected committed changes.") + return content_digest, after + + +def _committed_diff_content_digest( + repository: Path, + pathspec: str, + base: str, + head: str, + state_directory: Path, + *, + object_directory: Path | None = None, +) -> str: + digest = hashlib.sha256() + update_digest_field(digest, b"format", b"codex-security-snapshot/v1") + with ( + tempfile.TemporaryFile(dir=state_directory) as metadata, + tempfile.TemporaryFile(dir=state_directory) as requests, + tempfile.TemporaryFile(dir=state_directory) as objects, + ): + diff = git_command( + repository, + "-c", + f"diff.orderFile={os.devnull}", + "diff", + "--raw", + "-z", + "--no-abbrev", + "--no-ext-diff", + "--no-textconv", + "--no-color", + "--no-relative", + "--no-renames", + "--ignore-submodules=none", + base, + head, + "--", + pathspec, + text=False, + stdout=metadata, + local_objects_only=True, + object_directory=object_directory, + ) + if diff.returncode != 0: + raise SystemExit("Could not snapshot the selected committed changes.") + metadata.seek(0) + try: + write_committed_diff_object_requests(metadata, requests) + except ValueError as exc: + raise SystemExit("Could not snapshot the selected committed changes.") from exc + update_digest_stream_field(digest, b"tracked-diff", metadata) + + requests.seek(0, os.SEEK_END) + if requests.tell(): + requests.seek(0) + batch = git_command( + repository, + "cat-file", + "--batch", + "-z", + text=False, + stdin=requests, + stdout=objects, + local_objects_only=True, + object_directory=object_directory, + ) + if batch.returncode != 0: + raise SystemExit("Could not snapshot the selected committed changes.") + requests.seek(0) + objects.seek(0) + try: + validate_git_batch_blob_stream(requests, objects) + except ValueError as exc: + raise SystemExit("Could not snapshot the selected committed changes.") from exc + update_digest_stream_field(digest, b"tracked-objects", objects) + return f"codex-security-snapshot/v1:sha256:{digest.hexdigest()}" + + def remediation_checkout_snapshot( scan: sqlite3.Row, *, expected_revision: str | None = None ) -> tuple[str, str | None]: @@ -636,10 +1117,31 @@ def require_git_worktree_head(target: Path) -> str: def scan_target_warning(scan: sqlite3.Row) -> str | None: - if scan["diff_target_kind"] != "working_tree" and not scan["target_snapshot_digest"]: + committed_diff = scan["diff_target_kind"] in {"commit", "range"} + if ( + not committed_diff + and scan["diff_target_kind"] != "working_tree" + and not scan["target_snapshot_digest"] + ): + return None + if committed_diff and not scan["diff_content_digest"]: return None try: target = require_scan_target_identity(scan) + if committed_diff: + if ( + committed_diff_content_digest( + target, + scan["diff_base_revision"], + scan["diff_head_revision"], + ) + != scan["diff_content_digest"] + ): + return ( + "Committed changes changed while the scan was running; " + "results were saved for the original snapshot." + ) + return None if scan["target_revision"] == "unversioned": if ( directory_content_digest(target, excluded=(Path(scan["scan_dir"]),)) diff --git a/sdk/typescript/src/version.ts b/sdk/typescript/src/version.ts index 241666585..a6165b5ac 100644 --- a/sdk/typescript/src/version.ts +++ b/sdk/typescript/src/version.ts @@ -9,7 +9,7 @@ const PACKAGE_VERSIONS = packageVersions( export const VERSION = PACKAGE_VERSIONS.package; export const CODEX_SDK_VERSION = PACKAGE_VERSIONS.sdk; export const CODEX_EXECUTABLE_VERSION = PACKAGE_VERSIONS.executable; -export const BUNDLED_PLUGIN_VERSION = "0.1.22" as const; +export const BUNDLED_PLUGIN_VERSION = "0.1.23" as const; const PACKAGE_NAME = "@openai/codex-security"; diff --git a/sdk/typescript/tests-ts/compact-diff-scan.test.ts b/sdk/typescript/tests-ts/compact-diff-scan.test.ts index f117cb0c3..c431e1a23 100644 --- a/sdk/typescript/tests-ts/compact-diff-scan.test.ts +++ b/sdk/typescript/tests-ts/compact-diff-scan.test.ts @@ -1,10 +1,12 @@ import { execFileSync, spawn, spawnSync } from "node:child_process"; import { createHash, randomUUID } from "node:crypto"; import { + existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, + renameSync, rmSync, writeFileSync, } from "node:fs"; @@ -36,6 +38,12 @@ function createRepository(): { root: string; repository: string } { return { root, repository }; } +function createMcpDirectories(root: string): void { + mkdirSync(join(root, "scans"), { mode: 0o700 }); + mkdirSync(join(root, "scans", "repository"), { mode: 0o700 }); + mkdirSync(join(root, "state"), { mode: 0o700 }); +} + function git(repository: string, ...args: string[]): string { return execFileSync( "git", @@ -80,6 +88,101 @@ function candidate(path: string): JsonObject { }; } +function workbenchState(root: string): { + scans: number; + submitted: number; + workspaces: number; +} { + const command = + Bun.which("python3") ?? Bun.which("python") ?? Bun.which("py"); + expect(command).not.toBeNull(); + const result = spawnSync( + command!, + [ + "-I", + "-B", + "-c", + [ + "import json, sqlite3, sys", + "with sqlite3.connect(sys.argv[1]) as connection:", + " print(json.dumps({", + " 'workspaces': connection.execute('SELECT COUNT(*) FROM workspaces').fetchone()[0],", + " 'submitted': connection.execute('SELECT COUNT(*) FROM workspaces WHERE submitted = 1').fetchone()[0],", + " 'scans': connection.execute('SELECT COUNT(*) FROM scans').fetchone()[0],", + " }))", + ].join("\n"), + join(root, "state", "workbench.sqlite3"), + ], + { encoding: "utf8" }, + ); + expect(result.status, result.stderr).toBe(0); + return JSON.parse(result.stdout) as { + scans: number; + submitted: number; + workspaces: number; + }; +} + +function workspaceDiffDigest(root: string, workspaceId: string): string { + const command = + Bun.which("python3") ?? Bun.which("python") ?? Bun.which("py"); + expect(command).not.toBeNull(); + const result = spawnSync( + command!, + [ + "-I", + "-B", + "-c", + [ + "import sqlite3, sys", + "with sqlite3.connect(sys.argv[1]) as connection:", + " print(connection.execute('SELECT diff_content_digest FROM workspaces WHERE id = ?', (sys.argv[2],)).fetchone()[0])", + ].join("\n"), + join(root, "state", "workbench.sqlite3"), + workspaceId, + ], + { encoding: "utf8" }, + ); + expect(result.status, result.stderr).toBe(0); + return result.stdout.trim(); +} + +function workspaceDiffSelection( + root: string, + workspaceId: string, +): { + baseRevision: string | null; + contentDigest: string | null; + headRevision: string | null; +} { + const command = + Bun.which("python3") ?? Bun.which("python") ?? Bun.which("py"); + expect(command).not.toBeNull(); + const result = spawnSync( + command!, + [ + "-I", + "-B", + "-c", + [ + "import json, sqlite3, sys", + "with sqlite3.connect(sys.argv[1]) as connection:", + " row = connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest FROM workspaces WHERE id = ?', (sys.argv[2],)).fetchone()", + " print(json.dumps({'baseRevision': row[0], 'headRevision': row[1], 'contentDigest': row[2]}))", + ].join("\n"), + join(root, "state", "workbench.sqlite3"), + workspaceId, + ], + { encoding: "utf8" }, + ); + expect(result.status, result.stderr).toBe(0); + return JSON.parse(result.stdout) as { + baseRevision: string | null; + contentDigest: string | null; + headRevision: string | null; + }; +} + async function startMcp(root: string) { const child = spawn( process.execPath, @@ -420,8 +523,7 @@ describe("compact diff scan", () => { test("streams maximum-size preflight checks through the MCP workbench", async () => { const { root, repository } = createRepository(); writeSource(repository, "src/handler.py", "value = 1\n"); - mkdirSync(join(root, "scans")); - mkdirSync(join(root, "state")); + createMcpDirectories(root); const client = await startMcp(root); const owner = "preflight-stdin-owner"; @@ -455,8 +557,7 @@ describe("compact diff scan", () => { test("streams oversized option-like user context through the MCP workbench", async () => { const { root, repository } = createRepository(); writeSource(repository, "src/handler.py", "value = 1\n"); - mkdirSync(join(root, "scans")); - mkdirSync(join(root, "state")); + createMcpDirectories(root); const client = await startMcp(root); const userContext = `--${"é".repeat(64 * 1_024)}`; @@ -503,174 +604,223 @@ describe("compact diff scan", () => { } }, 30_000); - test.each(["object", "Markdown"])("MCP diff retains %s", async (format) => { - const { root, repository } = createRepository(); - writeSource(repository, "src/guard.py", "allowed = True\n"); - writeSource(repository, "src/handler.py", "value = 1\n"); - git(repository, "add", "."); - git(repository, "commit", "-qm", "base"); - const baseRevision = git(repository, "rev-parse", "HEAD"); - rmSync(join(repository, "src", "guard.py")); - writeSource(repository, "src/handler.py", "value = 2\n"); - git(repository, "add", "."); - git(repository, "commit", "-qm", "changed"); - const headRevision = git(repository, "rev-parse", "HEAD"); - mkdirSync(join(root, "scans")); - mkdirSync(join(root, "state")); - const client = await startMcp(root); - const owner = "compact-diff-owner"; - const call = (name: string, args: JsonObject) => - client.call(name, args, owner); + test.each(["object", "Markdown"])( + "MCP diff retains %s", + async (format) => { + const { root, repository } = createRepository(); + writeSource(repository, "src/guard.py", "allowed = True\n"); + writeSource(repository, "src/handler.py", "value = 1\n"); + git(repository, "add", "."); + git(repository, "commit", "-qm", "base"); + const baseRevision = git(repository, "rev-parse", "HEAD"); + rmSync(join(repository, "src", "guard.py")); + writeSource(repository, "src/handler.py", "value = 2\n"); + git(repository, "add", "."); + git(repository, "commit", "-qm", "changed"); + const headRevision = git(repository, "rev-parse", "HEAD"); + createMcpDirectories(root); + const client = await startMcp(root); + const owner = "compact-diff-owner"; + const call = (name: string, args: JsonObject) => + client.call(name, args, owner); - try { - const tools = (await client.request("tools/list", {}))["tools"] as { - name: string; - inputSchema: { properties: Record }; - }[]; - expect(tools.map((tool) => tool.name)).toContain( - "prepare_codex_security_review_items", - ); - expect(tools.map((tool) => tool.name)).toContain( - "record_codex_security_discovery_candidates", - ); - const preservedContextMaxLength = tools.find( - (tool) => tool.name === "start_codex_security_standard_scan", - )?.inputSchema.properties["userContext"]?.maxLength; - expect(preservedContextMaxLength).toBeUndefined(); + try { + const tools = (await client.request("tools/list", {}))["tools"] as { + name: string; + inputSchema: { properties: Record }; + }[]; + expect(tools.map((tool) => tool.name)).toContain( + "prepare_codex_security_review_items", + ); + expect(tools.map((tool) => tool.name)).toContain( + "record_codex_security_discovery_candidates", + ); + const preservedContextMaxLength = tools.find( + (tool) => tool.name === "start_codex_security_standard_scan", + )?.inputSchema.properties["userContext"]?.maxLength; + expect(preservedContextMaxLength).toBeUndefined(); - const selection = { - targetPath: repository, - scope: ".", - mode: "diff", - diffTarget: { kind: "range", baseRevision, headRevision }, - }; - const opened = await call("open_codex_security_workspace", selection); - const sessionId = (opened["workspace"] as JsonObject)["id"] as string; - await call("submit_codex_security_setup", { ...selection, sessionId }); - const started = await call("start_codex_security_scan", { sessionId }); - const results = (started["workspace"] as JsonObject)[ - "results" - ] as JsonObject; - const scanId = results["scanId"] as string; - const handoffClaimToken = randomUUID(); - await call("claim_codex_security_scan_handoff_delivery", { - scanId, - claimToken: handoffClaimToken, - }); - await call("attach_codex_security_scan_continuation_thread", { - scanId, - claimToken: handoffClaimToken, - threadId: owner, - }); - const context = await call("get_codex_security_scan_context", { - scanId, - handoffClaimToken, - }); - const scanDir = (context["scan"] as JsonObject)["scanDir"] as string; + const selection = { + targetPath: repository, + scope: ".", + mode: "diff", + diffTarget: { kind: "range", baseRevision, headRevision }, + }; + const opened = await call("open_codex_security_workspace", selection); + const openedWorkspace = opened["workspace"] as JsonObject; + const selectedDiffTarget = openedWorkspace["diffTarget"] as JsonObject; + const contentDigest = selectedDiffTarget["contentDigest"] as string; + expect(contentDigest).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + const sessionId = openedWorkspace["id"] as string; + await call("submit_codex_security_setup", { + ...selection, + diffTarget: selectedDiffTarget, + sessionId, + }); + const started = await call("start_codex_security_scan", { sessionId }); + const results = (started["workspace"] as JsonObject)[ + "results" + ] as JsonObject; + const scanId = results["scanId"] as string; + const handoffClaimToken = randomUUID(); + await call("claim_codex_security_scan_handoff_delivery", { + scanId, + claimToken: handoffClaimToken, + }); + await call("attach_codex_security_scan_continuation_thread", { + scanId, + claimToken: handoffClaimToken, + threadId: owner, + }); + const context = await call("get_codex_security_scan_context", { + scanId, + handoffClaimToken, + }); + const scanDir = (context["scan"] as JsonObject)["scanDir"] as string; - const inventory = await call("prepare_codex_security_review_items", { - scanId, - handoffClaimToken, - }); - expect(inventory["reviewItemsTotal"]).toBe(2); - const items = await call("list_codex_security_review_items", { - scanId, - handoffClaimToken, - }); - expect(items["items"]).toEqual([ - { path: "src/guard.py" }, - { path: "src/handler.py" }, - ]); - - await call("record_codex_security_discovery_candidates", { - scanId, - candidates: [candidate("src/handler.py")], - }); - const listed = await call("list_codex_security_candidates", { scanId }); - const rows = listed["rows"] as JsonObject[]; - expect(rows).toHaveLength(1); - await call("record_codex_security_candidate_validations", { - scanId, - validations: [ + const inventory = await call("prepare_codex_security_review_items", { + scanId, + handoffClaimToken, + }); + expect(inventory["reviewItemsTotal"]).toBe(2); + const items = await call("list_codex_security_review_items", { + scanId, + handoffClaimToken, + }); + expect(items["items"]).toEqual([ + { path: "src/guard.py" }, + { path: "src/handler.py" }, + ]); + + await call("record_codex_security_discovery_candidates", { + scanId, + candidates: [candidate("src/handler.py")], + }); + const listed = await call("list_codex_security_candidates", { scanId }); + const rows = listed["rows"] as JsonObject[]; + expect(rows).toHaveLength(1); + await call("record_codex_security_candidate_validations", { + scanId, + validations: [ + { + candidateId: rows[0]?.["candidate_id"], + validation: { + disposition: "suppressed", + method: "Static review of the changed handler.", + confidence: "high", + confidence_rationale: "The assignment is directly visible.", + rubric: ["The assignment does not cross a trust boundary."], + evidence: ["value = 2"], + counterevidence_or_proof_gap: "No sensitive operation exists.", + remaining_uncertainty: "", + }, + }, + ], + }); + await call("record_candidate_attack_paths", { + scanId, + attackPaths: [], + }); + const canonicalModel = { + summary: + "A local handler processes selected input (src/handler.py:1).", + assets: ["Integrity of the selected result."], + trustBoundaries: [ + "Caller input reaches the handler without authority over private state (src/handler.py:1).", + ], + attackerCapabilities: [ + "A caller can choose input but cannot choose another user's state.", + ], + securityObjectives: ["Keep each result bound to its selected input."], + assumptions: [ + "A shared-service deployment has not been established.", + ], + }; + const markdownFact = + "Selected input stays separate from private state (src/handler.py:1)."; + const savedModelPath = join( + scanDir, + "artifacts", + "01_context", + "threat_model.md", + ); + mkdirSync(dirname(savedModelPath), { recursive: true, mode: 0o700 }); + writeFileSync( + savedModelPath, + `# Saved threat model\n\n${markdownFact}\n`, + ); + const threatModel = + format === "Markdown" + ? { summary: readFileSync(savedModelPath, "utf8") } + : canonicalModel; + const openQuestions = [ { - candidateId: rows[0]?.["candidate_id"], - validation: { - disposition: "suppressed", - method: "Static review of the changed handler.", - confidence: "high", - confidence_rationale: "The assignment is directly visible.", - rubric: ["The assignment does not cross a trust boundary."], - evidence: ["value = 2"], - counterevidence_or_proof_gap: "No sensitive operation exists.", - remaining_uncertainty: "", + question: + "Does a supported embedding share this worker across callers?", + followUpPrompt: + "Confirm the deployment's ownership and isolation controls.", + }, + ]; + const coverageNote = + "The handler does not grant access to another caller's state (src/handler.py:1)."; + const finding = { + ruleId: "path-traversal.archive-extraction", + title: "Unsafe archive extraction", + summary: "An untrusted archive entry reaches a filesystem write.", + severity: { level: "high" }, + confidence: { + level: "high", + rationale: "Source evidence establishes reachability.", + }, + taxonomy: { category: "path-traversal", cwe: ["CWE-22"] }, + locations: [{ path: "src/handler.py", startLine: 1 }], + remediation: "Validate each output path before writing.", + provenance: { source: "local_plugin" }, + }; + const invalidRootCauseReference = await client.request("tools/call", { + name: "record_codex_security_scan_draft", + arguments: { + scanId, + handoffClaimToken, + findings: [ + { + ...finding, + root_cause: { + evidenceRefs: ["missing-root-cause-evidence"], + }, + }, + ], + coverage: { + completeness: "complete", + surfaces: [{ label: "Changed files", disposition: "rejected" }], + explicitExclusions: [], + deferred: [], }, }, - ], - }); - await call("record_candidate_attack_paths", { scanId, attackPaths: [] }); - const canonicalModel = { - summary: "A local handler processes selected input (src/handler.py:1).", - assets: ["Integrity of the selected result."], - trustBoundaries: [ - "Caller input reaches the handler without authority over private state (src/handler.py:1).", - ], - attackerCapabilities: [ - "A caller can choose input but cannot choose another user's state.", - ], - securityObjectives: ["Keep each result bound to its selected input."], - assumptions: ["A shared-service deployment has not been established."], - }; - const markdownFact = - "Selected input stays separate from private state (src/handler.py:1)."; - const savedModelPath = join( - scanDir, - "artifacts", - "01_context", - "threat_model.md", - ); - mkdirSync(dirname(savedModelPath), { recursive: true, mode: 0o700 }); - writeFileSync( - savedModelPath, - `# Saved threat model\n\n${markdownFact}\n`, - ); - const threatModel = - format === "Markdown" - ? { summary: readFileSync(savedModelPath, "utf8") } - : canonicalModel; - const openQuestions = [ - { - question: - "Does a supported embedding share this worker across callers?", - followUpPrompt: - "Confirm the deployment's ownership and isolation controls.", - }, - ]; - const coverageNote = - "The handler does not grant access to another caller's state (src/handler.py:1)."; - const finding = { - ruleId: "path-traversal.archive-extraction", - title: "Unsafe archive extraction", - summary: "An untrusted archive entry reaches a filesystem write.", - severity: { level: "high" }, - confidence: { - level: "high", - rationale: "Source evidence establishes reachability.", - }, - taxonomy: { category: "path-traversal", cwe: ["CWE-22"] }, - locations: [{ path: "src/handler.py", startLine: 1 }], - remediation: "Validate each output path before writing.", - provenance: { source: "local_plugin" }, - }; - const invalidRootCauseReference = await client.request("tools/call", { - name: "record_codex_security_scan_draft", - arguments: { + _meta: { "openai/threadId": owner }, + }); + expect(invalidRootCauseReference["isError"]).toBe(true); + expect(JSON.stringify(invalidRootCauseReference)).toContain( + "root_cause.evidenceRefs", + ); + await call("record_codex_security_scan_draft", { scanId, handoffClaimToken, findings: [ { ...finding, - root_cause: { - evidenceRefs: ["missing-root-cause-evidence"], + identity: { + anchor: "candidate-duplicate-instance", + instance: "dss-147-a", + }, + }, + { + ...finding, + extensions: { + candidateId: "candidate-duplicate-instance", + reportId: "DSS-147-A", }, }, ], @@ -680,261 +830,628 @@ describe("compact diff scan", () => { explicitExclusions: [], deferred: [], }, - }, - _meta: { "openai/threadId": owner }, - }); - expect(invalidRootCauseReference["isError"]).toBe(true); - expect(JSON.stringify(invalidRootCauseReference)).toContain( - "root_cause.evidenceRefs", - ); - await call("record_codex_security_scan_draft", { - scanId, - handoffClaimToken, - findings: [ - { - ...finding, - identity: { - anchor: "candidate-duplicate-instance", - instance: "dss-147-a", - }, - }, - { - ...finding, - extensions: { - candidateId: "candidate-duplicate-instance", - reportId: "DSS-147-A", + }); + expect( + ( + JSON.parse( + readFileSync(join(scanDir, "findings.json"), "utf8"), + ) as { + findings: JsonObject[]; + } + ).findings.map((draftFinding) => draftFinding["identity"]), + ).toEqual([ + { anchor: "candidate-duplicate-instance", instance: "dss-147-a" }, + { anchor: "candidate-duplicate-instance", instance: "dss-147-a" }, + ]); + await call("record_codex_security_scan_draft", { + scanId, + handoffClaimToken, + findings: [ + { + ...finding, + extensions: { + candidateId: "candidate-singleton", + reportId: "DSS-144-A", + }, }, - }, - ], - coverage: { - completeness: "complete", - surfaces: [{ label: "Changed files", disposition: "rejected" }], - explicitExclusions: [], - deferred: [], - }, - }); - expect( - ( - JSON.parse(readFileSync(join(scanDir, "findings.json"), "utf8")) as { - findings: JsonObject[]; - } - ).findings.map((draftFinding) => draftFinding["identity"]), - ).toEqual([ - { anchor: "candidate-duplicate-instance", instance: "dss-147-a" }, - { anchor: "candidate-duplicate-instance", instance: "dss-147-a" }, - ]); - await call("record_codex_security_scan_draft", { - scanId, - handoffClaimToken, - findings: [ - { - ...finding, - extensions: { - candidateId: "candidate-singleton", - reportId: "DSS-144-A", + { + ...finding, + code_evidence: [ + { + code: "value = 2", + id: "legacy-source", + }, + ], + attackPath: { + dataflow: { evidence_refs: ["legacy-source"] }, + }, }, - }, - { - ...finding, - code_evidence: [ - { - code: "value = 2", - id: "legacy-source", + { + ...finding, + ruleId: "path-traversal.archive-upload", + identity: { + anchor: "candidate-cross-rule", + instance: "shared-report", }, - ], - attackPath: { - dataflow: { evidence_refs: ["legacy-source"] }, }, - }, - { - ...finding, - ruleId: "path-traversal.archive-upload", - identity: { - anchor: "candidate-cross-rule", - instance: "shared-report", + { + ...finding, + extensions: { + candidateId: "candidate-cross-rule", + reportId: "shared-report", + }, }, - }, - { - ...finding, - extensions: { - candidateId: "candidate-cross-rule", - reportId: "shared-report", + { + ...finding, + extensions: { + candidateId: "candidate-cross-rule", + reportId: "second-report", + }, }, - }, - { - ...finding, - extensions: { - candidateId: "candidate-cross-rule", - reportId: "second-report", + { + ...finding, + identity: { + anchor: "candidate-authored-instance", + instance: "dss-147-a", + }, }, - }, - { - ...finding, - identity: { - anchor: "candidate-authored-instance", - instance: "dss-147-a", + { + ...finding, + extensions: { + candidateId: "candidate-authored-instance", + reportId: "DSS-147-B", + }, }, - }, - { - ...finding, - extensions: { - candidateId: "candidate-authored-instance", - reportId: "DSS-147-B", + { + ...finding, + extensions: { + candidateId: "candidate-authored-instance", + ledgerRowId: "ledger-row-c", + }, }, + ], + threatModel, + coverage: { + completeness: "complete", + surfaces: [ + { + label: "Changed files", + disposition: "rejected", + notes: coverageNote, + }, + ], + explicitExclusions: [], + deferred: [], + openQuestions, }, + }); + const draftManifest = JSON.parse( + readFileSync(join(scanDir, "scan-manifest.json"), "utf8"), + ) as JsonObject; + const draftTarget = (draftManifest["scan"] as JsonObject)[ + "target" + ] as JsonObject; + expect(draftTarget["snapshotDigest"]).toBe(contentDigest); + const canonicalDraftIdentities = ( + JSON.parse(readFileSync(join(scanDir, "findings.json"), "utf8")) as { + findings: JsonObject[]; + } + ).findings.map((draftFinding) => draftFinding["identity"]); + expect(canonicalDraftIdentities).toHaveLength(9); + const legacyCoordinateDigest = `codex-security-snapshot/v1:sha256:${createHash( + "sha256", + ) + .update("codex-security-diff/v1\0") + .update("range") + .update("\0") + .update(baseRevision) + .update("\0") + .update(headRevision) + .digest("hex")}`; + await call("complete_codex_security_scan", { + scanId, + handoffClaimToken, + }); + const completed = await call("get_codex_security_completed_scan", { + scanId, + handoffClaimToken, + }); + const target = ( + (completed["manifest"] as JsonObject)["scan"] as JsonObject + )["target"] as JsonObject; + expect(target["snapshotDigest"]).toBe(contentDigest); + expect((completed["coverage"] as JsonObject)["inventoryStrategy"]).toBe( + "diff", + ); + const completedIdentities = ( + (completed["findings"] as JsonObject)["findings"] as JsonObject[] + ).map((completedFinding) => completedFinding["identity"]); + expect(completedIdentities).toEqual(canonicalDraftIdentities); + expect(completedIdentities).toEqual([ + { anchor: "candidate-singleton", instance: "dss-144-a" }, + { anchor: "unsafe-archive-extraction" }, + { anchor: "candidate-cross-rule", instance: "shared-report" }, + { anchor: "candidate-cross-rule", instance: "shared-report" }, + { anchor: "candidate-cross-rule", instance: "second-report" }, + { anchor: "candidate-authored-instance", instance: "dss-147-a" }, { - ...finding, - extensions: { - candidateId: "candidate-authored-instance", - ledgerRowId: "ledger-row-c", - }, + anchor: "candidate-authored-instance", + instance: "dss-147-b", }, - ], - threatModel, - coverage: { - completeness: "complete", - surfaces: [ - { - label: "Changed files", - disposition: "rejected", - notes: coverageNote, - }, + { anchor: "candidate-authored-instance", instance: "ledger-row-c" }, + { anchor: "candidate-duplicate-instance", instance: "dss-147-a" }, + ]); + const legacyFinding = ( + (completed["findings"] as JsonObject)["findings"] as JsonObject[] + )[1]; + expect(legacyFinding?.["code_evidence"]).toEqual([ + { code: "value = 2", id: "legacy-source" }, + ]); + expect(legacyFinding?.["attackPath"]).toEqual({ + dataflow: { evidence_refs: ["legacy-source"] }, + }); + expect( + ((completed["manifest"] as JsonObject)["scan"] as JsonObject)[ + "threatModel" ], - explicitExclusions: [], - deferred: [], + ).toEqual(threatModel); + expect((completed["coverage"] as JsonObject)["openQuestions"]).toEqual( openQuestions, - }, - }); - const canonicalDraftIdentities = ( - JSON.parse(readFileSync(join(scanDir, "findings.json"), "utf8")) as { - findings: JsonObject[]; + ); + const contract = await loadContract(scanDir, { + pluginRoot: PLUGIN_ROOT, + }); + expect(contract.manifest.scan.threatModel).toEqual(threatModel); + expect(contract.coverage.openQuestions).toEqual(openQuestions); + expect(contract.coverage.surfaces[0]?.notes).toBe(coverageNote); + const report = readFileSync(join(scanDir, "report.md"), "utf8"); + const modelFacts = + format === "Markdown" + ? [markdownFact] + : Object.values(canonicalModel).flat(); + for (const fact of modelFacts) { + expect(report).toContain(fact); } - ).findings.map((draftFinding) => draftFinding["identity"]); - expect(canonicalDraftIdentities).toHaveLength(9); - await call("complete_codex_security_scan", { - scanId, - handoffClaimToken, - }); - const completed = await call("get_codex_security_completed_scan", { - scanId, - handoffClaimToken, - }); - const target = ( - (completed["manifest"] as JsonObject)["scan"] as JsonObject - )["target"] as JsonObject; - const digest = createHash("sha256") - .update("codex-security-diff/v1\0") - .update("range") - .update("\0") - .update(baseRevision) - .update("\0") - .update(headRevision) - .digest("hex"); - expect(target["snapshotDigest"]).toBe( - `codex-security-snapshot/v1:sha256:${digest}`, - ); - expect((completed["coverage"] as JsonObject)["inventoryStrategy"]).toBe( - "diff", - ); - const completedIdentities = ( - (completed["findings"] as JsonObject)["findings"] as JsonObject[] - ).map((completedFinding) => completedFinding["identity"]); - expect(completedIdentities).toEqual(canonicalDraftIdentities); - expect(completedIdentities).toEqual([ - { anchor: "candidate-singleton", instance: "dss-144-a" }, - { anchor: "unsafe-archive-extraction" }, - { anchor: "candidate-cross-rule", instance: "shared-report" }, - { anchor: "candidate-cross-rule", instance: "shared-report" }, - { anchor: "candidate-cross-rule", instance: "second-report" }, - { anchor: "candidate-authored-instance", instance: "dss-147-a" }, - { - anchor: "candidate-authored-instance", - instance: "dss-147-b", - }, - { anchor: "candidate-authored-instance", instance: "ledger-row-c" }, - { anchor: "candidate-duplicate-instance", instance: "dss-147-a" }, - ]); - const legacyFinding = ( - (completed["findings"] as JsonObject)["findings"] as JsonObject[] - )[1]; - expect(legacyFinding?.["code_evidence"]).toEqual([ - { code: "value = 2", id: "legacy-source" }, - ]); - expect(legacyFinding?.["attackPath"]).toEqual({ - dataflow: { evidence_refs: ["legacy-source"] }, - }); - expect( - ((completed["manifest"] as JsonObject)["scan"] as JsonObject)[ - "threatModel" - ], - ).toEqual(threatModel); - expect((completed["coverage"] as JsonObject)["openQuestions"]).toEqual( - openQuestions, - ); - const contract = await loadContract(scanDir, { pluginRoot: PLUGIN_ROOT }); - expect(contract.manifest.scan.threatModel).toEqual(threatModel); - expect(contract.coverage.openQuestions).toEqual(openQuestions); - expect(contract.coverage.surfaces[0]?.notes).toBe(coverageNote); - const report = readFileSync(join(scanDir, "report.md"), "utf8"); - const modelFacts = - format === "Markdown" - ? [markdownFact] - : Object.values(canonicalModel).flat(); - for (const fact of modelFacts) { - expect(report).toContain(fact); + expect(report).toContain(openQuestions[0]!.question); + expect(report).toContain(openQuestions[0]!.followUpPrompt); + expect(report).toContain(coverageNote); + + const terminalDir = join(root, "terminal-scan"); + mkdirSync(terminalDir, { mode: 0o700 }); + const markdownModel = `# Existing threat model\n\n## Assumptions\n\n${markdownFact}\n`; + const terminalManifest = structuredClone( + completed["manifest"], + ) as JsonObject; + const terminalScan = terminalManifest["scan"] as JsonObject; + terminalScan["threatModel"] = { summary: markdownModel }; + (terminalScan["target"] as JsonObject)["snapshotDigest"] = + legacyCoordinateDigest; + delete terminalScan["sealedAt"]; + delete terminalScan["artifacts"]; + for (const [name, document] of [ + ["scan-manifest.json", terminalManifest], + ["findings.json", completed["findings"]], + ["coverage.json", completed["coverage"]], + ] as const) { + writeFileSync(join(terminalDir, name), JSON.stringify(document)); + } + const finalized = python( + "finalize_scan_contract.py", + "--scan-dir", + terminalDir, + "--source-root", + repository, + ); + expect(finalized.status, finalized.stderr).toBe(0); + const validated = python( + "validate_scan_contract.py", + "--scan-dir", + terminalDir, + ); + expect(validated.status, validated.stderr).toBe(0); + const terminalResult = JSON.parse( + readFileSync(join(terminalDir, "scan-manifest.json"), "utf8"), + ) as { + scan: { + sealedAt: string; + target: { snapshotDigest: string }; + threatModel: unknown; + }; + }; + expect(terminalResult.scan.threatModel).toEqual({ + summary: markdownModel, + }); + expect(terminalResult.scan.target.snapshotDigest).toBe( + legacyCoordinateDigest, + ); + expect(terminalResult.scan.sealedAt).toBeDefined(); + const terminalReport = readFileSync( + join(terminalDir, "report.md"), + "utf8", + ); + expect(terminalReport).toContain(markdownFact); + expect(terminalReport.match(/^#{1,2} .+$/gm)).toEqual( + report.match(/^#{1,2} .+$/gm), + ); + } finally { + await client.close(); } - expect(report).toContain(openQuestions[0]!.question); - expect(report).toContain(openQuestions[0]!.followUpPrompt); - expect(report).toContain(coverageNote); - - const terminalDir = join(root, "terminal-scan"); - mkdirSync(terminalDir, { mode: 0o700 }); - const markdownModel = `# Existing threat model\n\n## Assumptions\n\n${markdownFact}\n`; - const terminalManifest = structuredClone( - completed["manifest"], - ) as JsonObject; - const terminalScan = terminalManifest["scan"] as JsonObject; - terminalScan["threatModel"] = { summary: markdownModel }; - delete terminalScan["sealedAt"]; - delete terminalScan["artifacts"]; - for (const [name, document] of [ - ["scan-manifest.json", terminalManifest], - ["findings.json", completed["findings"]], - ["coverage.json", completed["coverage"]], - ] as const) { - writeFileSync(join(terminalDir, name), JSON.stringify(document)); + }, + 30_000, + ); + + test.each(["commit", "range"] as const)( + "accepts a new clean %s selection without a repeated digest", + async (kind) => { + const { root, repository } = createRepository(); + writeSource(repository, "fixture.txt", "base\n"); + git(repository, "add", "fixture.txt"); + git(repository, "commit", "-qm", "base"); + const baseRevision = git(repository, "rev-parse", "HEAD"); + writeSource(repository, "fixture.txt", "head\n"); + git(repository, "add", "fixture.txt"); + git(repository, "commit", "-qm", "head"); + const headRevision = git(repository, "rev-parse", "HEAD"); + createMcpDirectories(root); + const client = await startMcp(root); + const owner = `new-${kind}-owner`; + const selection = { + targetPath: repository, + scope: ".", + mode: "diff", + diffTarget: + kind === "commit" + ? { kind, headRevision } + : { kind, baseRevision, headRevision }, + }; + + try { + const opened = await client.call( + "open_codex_security_workspace", + selection, + owner, + ); + const sessionId = (opened["workspace"] as JsonObject)["id"] as string; + writeSource(repository, "fixture.txt", "next\n"); + git(repository, "add", "fixture.txt"); + git(repository, "commit", "-qm", "next"); + const nextRevision = git(repository, "rev-parse", "HEAD"); + const nextDiffTarget = + kind === "commit" + ? { kind, headRevision: nextRevision } + : { + kind, + baseRevision: headRevision, + headRevision: nextRevision, + }; + + const submitted = await client.call( + "submit_codex_security_setup", + { + targetPath: repository, + scope: ".", + mode: "diff", + diffTarget: nextDiffTarget, + sessionId, + }, + owner, + ); + const submittedDiffTarget = (submitted["workspace"] as JsonObject)[ + "diffTarget" + ] as JsonObject; + expect(submittedDiffTarget).toMatchObject(nextDiffTarget); + expect(submittedDiffTarget["contentDigest"]).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + expect(workspaceDiffDigest(root, sessionId)).toBe( + submittedDiffTarget["contentDigest"] as string, + ); + expect(workbenchState(root)).toEqual({ + workspaces: 1, + submitted: 1, + scans: 0, + }); + + await client.call("start_codex_security_scan", { sessionId }, owner); + expect(workbenchState(root)).toEqual({ + workspaces: 1, + submitted: 1, + scans: 1, + }); + } finally { + await client.close(); } - const finalized = python( - "finalize_scan_contract.py", - "--scan-dir", - terminalDir, - "--source-root", + }, + 30_000, + ); + + test.each(["commit", "range"] as const)( + "recovers a persisted NULL-digest %s workspace after a missing blob is restored", + async (kind) => { + const { root, repository } = createRepository(); + writeSource(repository, "fixture.txt", "base\n"); + git(repository, "add", "fixture.txt"); + git(repository, "commit", "-qm", "base"); + const baseRevision = git(repository, "rev-parse", "HEAD"); + writeSource(repository, "fixture.txt", "head\n"); + git(repository, "add", "fixture.txt"); + git(repository, "commit", "-qm", "head"); + const headRevision = git(repository, "rev-parse", "HEAD"); + const blob = git(repository, "rev-parse", `${headRevision}:fixture.txt`); + const objectPath = join( repository, + ".git", + "objects", + blob.slice(0, 2), + blob.slice(2), ); - expect(finalized.status, finalized.stderr).toBe(0); - const validated = python( - "validate_scan_contract.py", - "--scan-dir", - terminalDir, - ); - expect(validated.status, validated.stderr).toBe(0); - const terminalResult = JSON.parse( - readFileSync(join(terminalDir, "scan-manifest.json"), "utf8"), - ) as { scan: { threatModel: unknown; sealedAt: string } }; - expect(terminalResult.scan.threatModel).toEqual({ - summary: markdownModel, - }); - expect(terminalResult.scan.sealedAt).toBeDefined(); - const terminalReport = readFileSync( - join(terminalDir, "report.md"), - "utf8", - ); - expect(terminalReport).toContain(markdownFact); - expect(terminalReport.match(/^#{1,2} .+$/gm)).toEqual( - report.match(/^#{1,2} .+$/gm), - ); - } finally { - await client.close(); - } - }); + const backupPath = `${objectPath}.missing`; + mkdirSync(join(repository, "nested")); + const selectedPath = join(repository, "nested", ".."); + createMcpDirectories(root); + const client = await startMcp(root); + const owner = `missing-blob-${kind}-owner`; + const selection = { + targetPath: selectedPath, + scope: ".", + mode: "diff", + diffTarget: + kind === "commit" + ? { kind, headRevision } + : { kind, baseRevision, headRevision }, + }; + + try { + renameSync(objectPath, backupPath); + const opened = await client.call( + "open_codex_security_workspace", + selection, + owner, + ); + renameSync(backupPath, objectPath); + const openedWorkspace = opened["workspace"] as JsonObject; + const sessionId = openedWorkspace["id"] as string; + expect(openedWorkspace["setupValidation"]).toMatchObject({ + valid: false, + }); + expect(JSON.stringify(openedWorkspace["setupValidation"])).toContain( + "Could not snapshot the selected committed changes.", + ); + expect(workspaceDiffSelection(root, sessionId)).toEqual({ + baseRevision: kind === "commit" ? null : baseRevision, + contentDigest: null, + headRevision, + }); + + const omittedDigest = await client.request("tools/call", { + name: "submit_codex_security_setup", + arguments: { ...selection, sessionId }, + _meta: { "openai/threadId": owner }, + }); + expect(omittedDigest["isError"], JSON.stringify(omittedDigest)).toBe( + true, + ); + expect(JSON.stringify(omittedDigest)).toContain( + "no longer produce the same diff", + ); + expect(workspaceDiffSelection(root, sessionId)).toEqual({ + baseRevision: kind === "commit" ? null : baseRevision, + contentDigest: null, + headRevision, + }); + + const inspected = await client.call( + "inspect_codex_security_setup", + selection, + owner, + ); + const currentDiffTarget = (inspected["setup"] as JsonObject)[ + "diffTarget" + ] as JsonObject; + expect(currentDiffTarget).toMatchObject({ + baseRevision, + headRevision, + kind, + }); + expect(currentDiffTarget["contentDigest"]).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + + const submitted = await client.call( + "submit_codex_security_setup", + { + ...selection, + diffTarget: currentDiffTarget, + sessionId, + }, + owner, + ); + expect( + ((submitted["workspace"] as JsonObject)["diffTarget"] as JsonObject)[ + "contentDigest" + ], + ).toBe(currentDiffTarget["contentDigest"]); + expect(workspaceDiffSelection(root, sessionId)).toEqual({ + baseRevision, + contentDigest: currentDiffTarget["contentDigest"] as string, + headRevision, + }); + expect(workbenchState(root)).toEqual({ + workspaces: 1, + submitted: 1, + scans: 0, + }); + + await client.call("start_codex_security_scan", { sessionId }, owner); + expect(workbenchState(root)).toEqual({ + workspaces: 1, + submitted: 1, + scans: 1, + }); + } finally { + if (existsSync(backupPath)) renameSync(backupPath, objectPath); + await client.close(); + } + }, + 30_000, + ); + + test.each(["commit", "range"] as const)( + "rejects a stale %s selection through the bundled MCP", + async (kind) => { + const { root, repository } = createRepository(); + writeSource(repository, "fixture.txt", "base\n"); + git(repository, "add", "fixture.txt"); + git(repository, "commit", "-qm", "base"); + const baseRevision = git(repository, "rev-parse", "HEAD"); + writeSource(repository, "fixture.txt", "head\n"); + git(repository, "add", "fixture.txt"); + git(repository, "commit", "-qm", "head"); + const headRevision = git(repository, "rev-parse", "HEAD"); + createMcpDirectories(root); + const client = await startMcp(root); + const owner = `stale-${kind}-owner`; + const requestedDiffTarget = + kind === "commit" + ? { kind, headRevision } + : { kind, baseRevision, headRevision }; + const selection = { + targetPath: repository, + scope: ".", + mode: "diff", + diffTarget: requestedDiffTarget, + }; + + try { + const opened = await client.call( + "open_codex_security_workspace", + selection, + owner, + ); + const workspace = opened["workspace"] as JsonObject; + const sessionId = workspace["id"] as string; + const selectedDiffTarget = workspace["diffTarget"] as JsonObject; + expect(selectedDiffTarget["kind"]).toBe(kind); + expect(selectedDiffTarget["contentDigest"]).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + expect(workbenchState(root)).toEqual({ + workspaces: 1, + submitted: 0, + scans: 0, + }); + + const selectedBlob = git( + repository, + "rev-parse", + `${headRevision}:fixture.txt`, + ); + const replacement = execFileSync( + "git", + ["hash-object", "-w", "--stdin"], + { cwd: repository, encoding: "utf8", input: "substituted\n" }, + ).trim(); + git(repository, "replace", "-f", selectedBlob, replacement); + + const inspected = await client.call( + "inspect_codex_security_setup", + selection, + owner, + ); + const currentDiffTarget = (inspected["setup"] as JsonObject)[ + "diffTarget" + ] as JsonObject; + expect(currentDiffTarget["contentDigest"]).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + expect(currentDiffTarget["contentDigest"]).not.toBe( + selectedDiffTarget["contentDigest"], + ); + const withoutContentDigest = { ...selectedDiffTarget }; + delete withoutContentDigest["contentDigest"]; + for (const diffTarget of [ + withoutContentDigest, + selectedDiffTarget, + currentDiffTarget, + ]) { + const submitted = await client.request("tools/call", { + name: "submit_codex_security_setup", + arguments: { + ...selection, + diffTarget, + sessionId, + }, + _meta: { "openai/threadId": owner }, + }); + expect(submitted["isError"], JSON.stringify(submitted)).toBe(true); + expect(JSON.stringify(submitted)).toContain( + "no longer produce the same diff", + ); + expect(workbenchState(root)).toEqual({ + workspaces: 1, + submitted: 0, + scans: 0, + }); + expect(workspaceDiffDigest(root, sessionId)).toBe( + selectedDiffTarget["contentDigest"] as string, + ); + } + + const started = await client.request("tools/call", { + name: "start_codex_security_scan", + arguments: { sessionId }, + _meta: { "openai/threadId": owner }, + }); + expect(started["isError"], JSON.stringify(started)).toBe(true); + expect(JSON.stringify(started)).toContain( + "Save the Codex Security setup", + ); + expect(workbenchState(root)).toEqual({ + workspaces: 1, + submitted: 0, + scans: 0, + }); + + const replacementWorkspace = await client.call( + "open_codex_security_workspace", + { ...selection, diffTarget: currentDiffTarget }, + owner, + ); + const replacementSessionId = ( + replacementWorkspace["workspace"] as JsonObject + )["id"] as string; + expect(replacementSessionId).not.toBe(sessionId); + await client.call( + "submit_codex_security_setup", + { + ...selection, + diffTarget: currentDiffTarget, + sessionId: replacementSessionId, + }, + owner, + ); + expect(workspaceDiffDigest(root, replacementSessionId)).toBe( + currentDiffTarget["contentDigest"] as string, + ); + expect(workbenchState(root)).toEqual({ + workspaces: 2, + submitted: 1, + scans: 0, + }); + await client.call( + "start_codex_security_scan", + { sessionId: replacementSessionId }, + owner, + ); + expect(workbenchState(root)).toEqual({ + workspaces: 2, + submitted: 1, + scans: 1, + }); + } finally { + await client.close(); + } + }, + 30_000, + ); }); diff --git a/sdk/typescript/tests-ts/git-batch-object-validation.test.ts b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts new file mode 100644 index 000000000..ce7a66daa --- /dev/null +++ b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts @@ -0,0 +1,3411 @@ +import { spawnSync } from "node:child_process"; +import { + cpSync, + existsSync, + mkdirSync, + mkdtempSync, + readdirSync, + readFileSync, + realpathSync, + renameSync, + rmSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { afterEach, describe, expect, test } from "bun:test"; +import { BUNDLED_PLUGIN_VERSION, bootstrapPlugin } from "../src/index.js"; +import { PLUGIN_ROOT } from "./plugin-root.js"; + +const temporaryRoots: string[] = []; +const scripts = join(PLUGIN_ROOT, "scripts"); +const python = + process.env["PYTHON"] ?? Bun.which("python3") ?? Bun.which("python"); + +afterEach(() => { + for (const root of temporaryRoots.splice(0)) { + rmSync(root, { recursive: true, force: true }); + } +}); + +function git(repository: string, ...args: string[]): string { + const result = spawnSync("git", ["-C", repository, ...args], { + encoding: "utf8", + }); + expect(result.status, result.stderr).toBe(0); + return result.stdout.trim(); +} + +function commit(repository: string, message: string): void { + git( + repository, + "-c", + "user.name=synthetic-test", + "-c", + "user.email=synthetic-test@example.invalid", + "commit", + "--quiet", + "-m", + message, + ); +} + +function runPython( + source: string[], + args: string[], + state?: string, + environment: NodeJS.ProcessEnv = {}, + scriptRoot = scripts, +): string { + expect(python).not.toBeNull(); + const result = spawnSync( + python!, + [ + "-I", + "-B", + "-c", + ["import sys", "sys.path.insert(0, sys.argv[1])", ...source].join("\n"), + scriptRoot, + ...args, + ], + { + encoding: "utf8", + env: { + PATH: process.env["PATH"], + ...environment, + ...(state === undefined ? {} : { CODEX_SECURITY_STATE_DIR: state }), + }, + }, + ); + expect(result.status, result.stderr).toBe(0); + return result.stdout.trim(); +} + +function runPythonJson( + source: string[], + args: string[], + state?: string, + environment: NodeJS.ProcessEnv = {}, + scriptRoot = scripts, +): T { + return JSON.parse( + runPython(source, args, state, environment, scriptRoot), + ) as T; +} + +function createRepository(): { + base: string; + head: string; + repository: string; + root: string; + state: string; +} { + const root = realpathSync( + mkdtempSync(join(tmpdir(), "codex-security-git-batch-")), + ); + temporaryRoots.push(root); + const repository = join(root, "repository"); + const state = join(root, "state"); + mkdirSync(repository); + mkdirSync(state, { mode: 0o700 }); + git(repository, "init", "--quiet"); + writeFileSync(join(repository, "fixture.txt"), "base\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "base"); + const base = git(repository, "rev-parse", "HEAD"); + writeFileSync(join(repository, "fixture.txt"), "head\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "head"); + return { + base, + head: git(repository, "rev-parse", "HEAD"), + repository, + root, + state, + }; +} + +async function upgradeBundledPlugin(root: string): Promise { + const previous = join(root, "previous-plugin"); + cpSync(PLUGIN_ROOT, previous, { recursive: true }); + const previousManifestPath = join(previous, ".codex-plugin", "plugin.json"); + const previousManifest = JSON.parse( + readFileSync(previousManifestPath, "utf8"), + ) as { version: string }; + previousManifest.version = "0.1.22"; + writeFileSync(previousManifestPath, JSON.stringify(previousManifest)); + const previousMcpPath = join(previous, ".mcp.json"); + const previousMcp = JSON.parse(readFileSync(previousMcpPath, "utf8")) as { + mcpServers: Record; + }; + for (const server of Object.values(previousMcp.mcpServers)) { + server.env_vars = server.env_vars?.filter( + (name) => name !== "CODEX_SAFETY_IDENTIFIER", + ); + } + writeFileSync(previousMcpPath, JSON.stringify(previousMcp)); + + const home = join(root, "codex-home"); + const marketplace = join(home, "sdk-marketplace"); + mkdirSync(home, { mode: 0o700 }); + const runCodex = async (_command: unknown, args: readonly string[]) => { + if (args[1] === "marketplace") { + writeFileSync( + join(home, "config.toml"), + `[marketplaces.codex-security-sdk]\nsource_type = "local"\nsource = ${JSON.stringify(marketplace)}\n`, + ); + return ""; + } + const selected = join(marketplace, "plugins", "codex-security"); + const manifest = JSON.parse( + readFileSync(join(selected, ".codex-plugin", "plugin.json"), "utf8"), + ) as { version: string }; + const installed = join(home, "installed", manifest.version); + rmSync(installed, { recursive: true, force: true }); + mkdirSync(join(home, "installed"), { recursive: true }); + cpSync(selected, installed, { recursive: true }); + return JSON.stringify({ + installedPath: installed, + version: manifest.version, + }); + }; + const options = { + codexCommand: { command: "/synthetic-codex" }, + runCodex, + }; + + expect((await bootstrapPlugin(home, previous, options)).version).toBe( + "0.1.22", + ); + const upgraded = await bootstrapPlugin(home, PLUGIN_ROOT, options); + expect(upgraded.version).not.toBe("0.1.22"); + expect(upgraded.version).toBe(BUNDLED_PLUGIN_VERSION); + const installedMcp = JSON.parse( + readFileSync(join(upgraded.installedRoot, ".mcp.json"), "utf8"), + ) as { mcpServers: Record }; + expect(installedMcp.mcpServers["codex-security"]?.env_vars).toContain( + "CODEX_SAFETY_IDENTIFIER", + ); + return upgraded.installedRoot; +} + +function batchRecord( + objectId: string, + type: string, + payload: Buffer, + declaredSize = payload.length, +): Buffer { + return Buffer.concat([ + Buffer.from(`${objectId} ${type} ${declaredSize}\n`), + payload, + Buffer.from("\n"), + ]); +} + +function validateBatch(requests: Buffer, output: Buffer) { + return runPythonJson<{ accepted: boolean; error?: string }>( + [ + "import io, json", + "from workbench_target import validate_git_batch_blob_stream", + "try:", + " validate_git_batch_blob_stream(io.BytesIO(bytes.fromhex(sys.argv[2])), io.BytesIO(bytes.fromhex(sys.argv[3])))", + "except ValueError as error:", + " print(json.dumps({'accepted': False, 'error': str(error)}))", + "else:", + " print(json.dumps({'accepted': True}))", + ], + [requests.toString("hex"), output.toString("hex")], + ); +} + +function committedDigest( + repository: string, + state: string | undefined, + base: string, + head: string, + environment: NodeJS.ProcessEnv = {}, + scriptRoot = scripts, +): string { + return runPython( + [ + "from pathlib import Path", + "from workbench_target import committed_diff_content_digest", + "print(committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4]))", + ], + [repository, base, head], + state, + environment, + scriptRoot, + ); +} + +function committedObjectIdentity( + repository: string, + base: string, + head: string, + environment: NodeJS.ProcessEnv = {}, +): string { + return runPython( + [ + "from pathlib import Path", + "from workbench_target import committed_diff_object_identity", + "print(committed_diff_object_identity(Path(sys.argv[2]), sys.argv[3], sys.argv[4]))", + ], + [repository, base, head], + undefined, + environment, + ); +} + +describe("committed diff Git batch validation", () => { + const firstObject = "1".repeat(40); + const secondObject = "2".repeat(40); + const firstRecord = batchRecord( + firstObject, + "blob", + Buffer.from([0, 10, 255]), + ); + const secondRecord = batchRecord( + secondObject, + "blob", + Buffer.from("second\n"), + ); + const firstRequest = Buffer.from(`${firstObject}\0`); + const bothRequests = Buffer.from(`${firstObject}\0${secondObject}\0`); + + test("accepts exactly ordered, size-framed blob responses", () => { + expect( + validateBatch(bothRequests, Buffer.concat([firstRecord, secondRecord])), + ).toEqual({ accepted: true }); + }); + + test.each([ + ["missing", Buffer.from(`${firstObject} missing\n`), firstRequest], + [ + "non-blob", + batchRecord(firstObject, "tree", Buffer.from("tree")), + firstRequest, + ], + ["malformed size", Buffer.from(`${firstObject} blob nope\n`), firstRequest], + ["negative size", Buffer.from(`${firstObject} blob -1\n`), firstRequest], + [ + "uppercase object ID", + batchRecord("A".repeat(40), "blob", Buffer.from("blob")), + firstRequest, + ], + [ + "short object ID", + batchRecord(firstObject.slice(1), "blob", Buffer.from("blob")), + firstRequest, + ], + ["unterminated header", Buffer.from(`${firstObject} blob 3`), firstRequest], + [ + "truncated payload", + Buffer.concat([ + Buffer.from(`${firstObject} blob 4\n`), + Buffer.from("abc"), + ]), + firstRequest, + ], + [ + "missing payload terminator", + Buffer.concat([ + Buffer.from(`${firstObject} blob 3\n`), + Buffer.from("abc"), + ]), + firstRequest, + ], + ["out-of-order", Buffer.concat([secondRecord, firstRecord]), bothRequests], + ["missing response", firstRecord, bothRequests], + [ + "extra response", + Buffer.concat([firstRecord, secondRecord]), + firstRequest, + ], + [ + "trailing data", + Buffer.concat([firstRecord, Buffer.from("x")]), + firstRequest, + ], + ] as const)("rejects %s batch transcripts", (_name, output, requests) => { + expect(validateBatch(requests, output)).toMatchObject({ accepted: false }); + }); + + test("reads newline-bearing revision paths and binary blobs", () => { + const { head, repository, state } = createRepository(); + const path = "line\nname.bin"; + const payload = Buffer.from([0, 10, 255, 13, 10]); + const hashed = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: payload }, + ); + expect(hashed.status, hashed.stderr).toBe(0); + git( + repository, + "update-index", + "--add", + "--cacheinfo", + `100644,${hashed.stdout.trim()},${path}`, + ); + expect(existsSync(join(repository, path))).toBe(false); + commit(repository, "binary path"); + const revision = git(repository, "rev-parse", "HEAD"); + const result = runPythonJson<{ + blobs: Array; + empty: unknown[]; + }>( + [ + "import base64, json", + "from pathlib import Path", + "from workbench_target import git_blob_bytes", + "requests = [sys.argv[3], sys.argv[4]]", + "blobs = git_blob_bytes(Path(sys.argv[2]), requests)", + "print(json.dumps({'blobs': [None if blob is None else base64.b64encode(blob).decode() for blob in blobs], 'empty': git_blob_bytes(Path(sys.argv[2]), [])}))", + ], + [repository, `${revision}:${path}`, `${head}:missing\npath.bin`], + state, + ); + + expect(result).toEqual({ + blobs: [payload.toString("base64"), null], + empty: [], + }); + }); + + test("hashes modified, added, and deleted blobs while skipping gitlinks", () => { + const { repository, state } = createRepository(); + writeFileSync(join(repository, "modified.bin"), Buffer.from("old\n")); + writeFileSync(join(repository, "deleted.txt"), "deleted\n"); + git(repository, "add", "."); + commit(repository, "matrix base"); + const matrixBase = git(repository, "rev-parse", "HEAD"); + const earlierCommit = git(repository, "rev-parse", "HEAD~1"); + writeFileSync( + join(repository, "modified.bin"), + Buffer.from([0, 10, 255, 13, 10]), + ); + writeFileSync(join(repository, "added.txt"), "added\n"); + rmSync(join(repository, "deleted.txt")); + git( + repository, + "update-index", + "--add", + "--cacheinfo", + `160000,${matrixBase},linked`, + ); + git(repository, "add", "modified.bin", "added.txt", "deleted.txt"); + commit(repository, "matrix head"); + const matrixHead = git(repository, "rev-parse", "HEAD"); + git( + repository, + "update-index", + "--cacheinfo", + `160000,${earlierCommit},linked`, + ); + commit(repository, "gitlink only"); + const gitlinkHead = git(repository, "rev-parse", "HEAD"); + + const result = runPythonJson<{ + batchArguments: string[][]; + digests: string[]; + requestCounts: number[]; + }>( + [ + "import json", + "from pathlib import Path", + "import workbench_target as target", + "original = target.git_command", + "request_counts, batch_arguments = [], []", + "def tracked_git_command(repository, *args, **kwargs):", + " if args[:2] == ('cat-file', '--batch'):", + " stream = kwargs['stdin']", + " requests = stream.read()", + " stream.seek(0)", + " request_counts.append(requests.count(b'\\0'))", + " batch_arguments.append(list(args))", + " return original(repository, *args, **kwargs)", + "target.git_command = tracked_git_command", + "repository = Path(sys.argv[2])", + "digests = [target.committed_diff_content_digest(repository, base, head) for base, head in ((sys.argv[3], sys.argv[4]), (sys.argv[4], sys.argv[5]))]", + "print(json.dumps({'batchArguments': batch_arguments, 'digests': digests, 'requestCounts': request_counts}))", + ], + [repository, matrixBase, matrixHead, gitlinkHead], + state, + ); + + expect(result.requestCounts).toEqual([4]); + expect(result.batchArguments).toEqual([["cat-file", "--batch", "-z"]]); + expect(result.digests).toEqual([ + expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + ]); + }); + + test("materializes each distinct changed blob once while binding raw paths", () => { + const { repository, state } = createRepository(); + const paths = Array.from( + { length: 32 }, + (_, index) => "shared-" + index.toString().padStart(2, "0") + ".bin", + ); + const oldPayload = Buffer.alloc(64 * 1024, 0x41); + const newPayload = Buffer.alloc(64 * 1024, 0x42); + for (const path of paths) writeFileSync(join(repository, path), oldPayload); + git(repository, "add", "."); + commit(repository, "shared blob base"); + const base = git(repository, "rev-parse", "HEAD"); + for (const path of paths) writeFileSync(join(repository, path), newPayload); + git(repository, "add", "."); + commit(repository, "shared blob head"); + const head = git(repository, "rev-parse", "HEAD"); + const oldObject = git(repository, "rev-parse", base + ":" + paths[0]); + const newObject = git(repository, "rev-parse", head + ":" + paths[0]); + + const result = runPythonJson<{ + digest: string; + objectBytes: number; + rawNewOccurrences: number; + rawOldOccurrences: number; + rawPaths: string[]; + requests: string[]; + }>( + [ + "import json, os", + "from pathlib import Path", + "import workbench_target as target", + "original = target.git_command", + "capture = {}", + "old_object = os.fsencode(sys.argv[5])", + "new_object = os.fsencode(sys.argv[6])", + "def tracked_git_command(repository, *args, **kwargs):", + " if args[:2] == ('cat-file', '--batch'):", + " stream = kwargs['stdin']", + " position = stream.tell()", + " stream.seek(0)", + " capture['requests'] = [os.fsdecode(value) for value in stream.read().split(b'\\0') if value]", + " stream.seek(position)", + " result = original(repository, *args, **kwargs)", + " if '--raw' in args and '-z' in args:", + " stream = kwargs['stdout']", + " position = stream.tell()", + " stream.seek(0)", + " fields = stream.read().split(b'\\0')", + " stream.seek(position)", + " headers = fields[:-1:2]", + " capture['rawPaths'] = [os.fsdecode(value) for value in fields[1:-1:2]]", + " capture['rawOldOccurrences'] = sum(header.split()[2] == old_object for header in headers)", + " capture['rawNewOccurrences'] = sum(header.split()[3] == new_object for header in headers)", + " if args[:2] == ('cat-file', '--batch'):", + " stream = kwargs['stdout']", + " position = stream.tell()", + " stream.seek(0, os.SEEK_END)", + " capture['objectBytes'] = stream.tell()", + " stream.seek(position)", + " return result", + "target.git_command = tracked_git_command", + "capture['digest'] = target.committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4])", + "print(json.dumps(capture))", + ], + [repository, base, head, oldObject, newObject], + state, + ); + + const { repository: singleRepository, state: singleState } = + createRepository(); + writeFileSync(join(singleRepository, "single.bin"), oldPayload); + git(singleRepository, "add", "."); + commit(singleRepository, "single blob base"); + const singleBase = git(singleRepository, "rev-parse", "HEAD"); + writeFileSync(join(singleRepository, "single.bin"), newPayload); + git(singleRepository, "add", "."); + commit(singleRepository, "single blob head"); + const singleHead = git(singleRepository, "rev-parse", "HEAD"); + expect(git(singleRepository, "rev-parse", singleBase + ":single.bin")).toBe( + oldObject, + ); + expect(git(singleRepository, "rev-parse", singleHead + ":single.bin")).toBe( + newObject, + ); + const singleDigest = runPythonJson<{ digest: string }>( + [ + "import json", + "from pathlib import Path", + "import workbench_target as target", + "print(json.dumps({'digest': target.committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4])}))", + ], + [singleRepository, singleBase, singleHead], + singleState, + ).digest; + + expect(result.rawPaths).toEqual(paths); + expect(result.rawOldOccurrences).toBe(paths.length); + expect(result.rawNewOccurrences).toBe(paths.length); + expect(result.requests).toEqual([oldObject, newObject]); + expect(result.objectBytes).toBeLessThan(newPayload.length * 3); + expect(result.digest).not.toBe(singleDigest); + expect(result.digest).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + }); + + test("preserves trusted Git selectors while forcing local-only controls", () => { + const { repository } = createRepository(); + const configParameters = "'safe.directory'='/synthetic/repository'"; + const result = runPythonJson>( + [ + "import json, subprocess", + "from pathlib import Path", + "import workbench_target as target", + "captured = {}", + "def fake_run(command, **kwargs):", + " captured.update(kwargs['env'])", + " captured['COMMAND'] = '\\0'.join(command)", + " return subprocess.CompletedProcess(command, 0, b'', b'')", + "target.subprocess.run = fake_run", + "target.git_command(Path(sys.argv[2]), 'status', text=False, local_objects_only=True)", + "names = ('GIT_DIR', 'GIT_WORK_TREE', 'GIT_NO_REPLACE_OBJECTS', 'GIT_REPLACE_REF_BASE', 'GIT_CONFIG_COUNT', 'GIT_CONFIG_KEY_0', 'GIT_CONFIG_VALUE_0', 'GIT_CONFIG_PARAMETERS', 'GIT_CONFIG_SYSTEM', 'GIT_CONFIG_GLOBAL', 'GIT_CONFIG_NOSYSTEM', 'GIT_ALLOW_PROTOCOL', 'GIT_NO_LAZY_FETCH', 'GIT_LITERAL_PATHSPECS', 'COMMAND')", + "print(json.dumps({name: captured.get(name) for name in names}))", + ], + [repository], + undefined, + { + GIT_ALLOW_PROTOCOL: "ext", + GIT_CONFIG_COUNT: "1", + GIT_CONFIG_GLOBAL: "/synthetic/global-config", + GIT_CONFIG_KEY_0: "safe.directory", + GIT_CONFIG_NOSYSTEM: "1", + GIT_CONFIG_PARAMETERS: configParameters, + GIT_CONFIG_SYSTEM: "/synthetic/system-config", + GIT_CONFIG_VALUE_0: repository, + GIT_DIR: "/synthetic/git-dir", + GIT_LITERAL_PATHSPECS: "0", + GIT_NO_REPLACE_OBJECTS: "1", + GIT_REPLACE_REF_BASE: "refs/synthetic-replacements/", + GIT_WORK_TREE: "/synthetic/work-tree", + }, + ); + + expect(result).toMatchObject({ + GIT_DIR: null, + GIT_WORK_TREE: null, + GIT_NO_REPLACE_OBJECTS: "1", + GIT_REPLACE_REF_BASE: "refs/synthetic-replacements/", + GIT_CONFIG_COUNT: "1", + GIT_CONFIG_KEY_0: "safe.directory", + GIT_CONFIG_VALUE_0: repository, + GIT_CONFIG_PARAMETERS: configParameters, + GIT_CONFIG_SYSTEM: "/synthetic/system-config", + GIT_CONFIG_GLOBAL: "/synthetic/global-config", + GIT_CONFIG_NOSYSTEM: "1", + GIT_ALLOW_PROTOCOL: "", + GIT_NO_LAZY_FETCH: "1", + GIT_LITERAL_PATHSPECS: "1", + }); + expect(result["COMMAND"]?.split("\0")).toContain("core.fsmonitor=false"); + }); + + test("matches trusted Git replacement views", () => { + const { base, head, repository, state } = createRepository(); + const selectedDigest = committedDigest(repository, state, base, head); + const selectedIdentity = committedObjectIdentity(repository, base, head); + const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "replacement view\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + const replacementBlob = replacement.stdout.trim(); + git( + repository, + "update-ref", + `refs/synthetic-replacements/${originalBlob}`, + replacementBlob, + ); + + const replacementEnvironment = { + GIT_REPLACE_REF_BASE: "refs/synthetic-replacements/", + }; + expect( + committedDigest(repository, state, base, head, replacementEnvironment), + ).not.toBe(selectedDigest); + expect( + committedObjectIdentity(repository, base, head, replacementEnvironment), + ).not.toBe(selectedIdentity); + git(repository, "replace", "-f", originalBlob, replacementBlob); + for (const value of ["1", ""]) { + expect( + committedDigest(repository, state, base, head, { + GIT_NO_REPLACE_OBJECTS: value, + }), + ).toBe(selectedDigest); + } + }); + + test("binds raw-prefix replacement refs in SHA-1 and supported SHA-256 repositories", () => { + const { root, state } = createRepository(); + const environment = { GIT_REPLACE_REF_BASE: "refs/repl-" }; + + for (const objectFormat of ["sha1", "sha256"] as const) { + const repository = join(root, `replacement-${objectFormat}`); + const initialized = spawnSync( + "git", + ["init", "--quiet", `--object-format=${objectFormat}`, repository], + { encoding: "utf8" }, + ); + if (objectFormat === "sha256" && initialized.status !== 0) continue; + expect(initialized.status, initialized.stderr).toBe(0); + writeFileSync(join(repository, "fixture.txt"), "base\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "base"); + const base = git(repository, "rev-parse", "HEAD"); + writeFileSync(join(repository, "fixture.txt"), "head\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "head"); + const head = git(repository, "rev-parse", "HEAD"); + const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const before = [ + committedDigest(repository, state, base, head, environment), + committedObjectIdentity(repository, base, head, environment), + ]; + const firstReplacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "first raw-prefix replacement\n" }, + ); + const finalReplacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "final raw-prefix replacement\n" }, + ); + expect(firstReplacement.status, firstReplacement.stderr).toBe(0); + expect(finalReplacement.status, finalReplacement.stderr).toBe(0); + const firstBlob = firstReplacement.stdout.trim(); + const finalBlob = finalReplacement.stdout.trim(); + git(repository, "update-ref", `refs/repl-${originalBlob}`, firstBlob); + git(repository, "update-ref", `refs/repl-${firstBlob}`, finalBlob); + const selected = spawnSync( + "git", + ["-C", repository, "cat-file", "blob", originalBlob], + { + encoding: "utf8", + env: { ...process.env, ...environment }, + }, + ); + expect(selected.status, selected.stderr).toBe(0); + expect(selected.stdout).toBe("final raw-prefix replacement\n"); + + expect( + committedDigest(repository, state, base, head, environment), + ).not.toBe(before[0]); + expect( + committedObjectIdentity(repository, base, head, environment), + ).not.toBe(before[1]); + } + }); + + test("binds nested uppercase replacement refs in SHA-1 and supported SHA-256 repositories", () => { + const { root, state } = createRepository(); + const replacementRefBase = "refs/synthetic-replacements/"; + const environment = { GIT_REPLACE_REF_BASE: replacementRefBase }; + + for (const objectFormat of ["sha1", "sha256"] as const) { + const repository = join(root, `nested-replacement-${objectFormat}`); + const initialized = spawnSync( + "git", + ["init", "--quiet", `--object-format=${objectFormat}`, repository], + { encoding: "utf8" }, + ); + if (objectFormat === "sha256" && initialized.status !== 0) continue; + expect(initialized.status, initialized.stderr).toBe(0); + writeFileSync(join(repository, "fixture.txt"), "base\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "base"); + const base = git(repository, "rev-parse", "HEAD"); + writeFileSync(join(repository, "fixture.txt"), "head\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "head"); + const head = git(repository, "rev-parse", "HEAD"); + const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const before = [ + committedDigest(repository, state, base, head, environment), + committedObjectIdentity(repository, base, head, environment), + ]; + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "nested uppercase replacement\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + const replacementBlob = replacement.stdout.trim(); + git( + repository, + "update-ref", + `${replacementRefBase}nested/${originalBlob.toUpperCase()}`, + replacementBlob, + ); + const selected = spawnSync( + "git", + ["-C", repository, "cat-file", "blob", originalBlob], + { + encoding: "utf8", + env: { ...process.env, ...environment }, + }, + ); + expect(selected.status, selected.stderr).toBe(0); + expect(selected.stdout).toBe("nested uppercase replacement\n"); + + expect( + committedDigest(repository, state, base, head, environment), + ).not.toBe(before[0]); + expect( + committedObjectIdentity(repository, base, head, environment), + ).not.toBe(before[1]); + } + }); + + test.each([ + ["a repository-local disable", false, false], + ["a repository-local enable over a global disable", true, true], + ] as const)( + "preserves %s of replacement refs in the frozen view", + (_label, localReplacementSetting, expectsReplacement) => { + const { base, head, repository, root, state } = createRepository(); + const originalDigest = committedDigest(repository, state, base, head); + const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "replacement policy\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + git(repository, "replace", "-f", originalBlob, replacement.stdout.trim()); + const replacementDigest = committedDigest(repository, state, base, head); + expect(replacementDigest).not.toBe(originalDigest); + + git( + repository, + "config", + "core.useReplaceRefs", + String(localReplacementSetting), + ); + const globalConfig = join(root, "global.gitconfig"); + writeFileSync(globalConfig, "[core]\n\tuseReplaceRefs = false\n"); + const environment = expectsReplacement + ? { GIT_CONFIG_GLOBAL: globalConfig } + : {}; + + expect(committedDigest(repository, state, base, head, environment)).toBe( + expectsReplacement ? replacementDigest : originalDigest, + ); + }, + ); + + test.skipIf(process.platform === "win32")( + "supports line-break-bearing quoted repository paths", + () => { + for (const separator of ["\n", "\r"]) { + const { base, head, repository, root, state } = createRepository(); + const expected = committedDigest(repository, state, base, head); + const relocated = join(root, `repository${separator}"quoted`); + renameSync(repository, relocated); + + expect(committedDigest(relocated, state, base, head)).toBe(expected); + } + }, + ); + + test("preserves the source repository's supported alternates depth", () => { + const { base, head, repository, root, state } = createRepository(); + const objectDirectory = git( + repository, + "rev-parse", + "--path-format=absolute", + "--git-path", + "objects", + ); + const alternateDirectories = Array.from({ length: 6 }, (_, index) => + join(root, `alternate-${index}`), + ); + for (const directory of alternateDirectories) { + mkdirSync(join(directory, "info"), { recursive: true }); + mkdirSync(join(directory, "pack")); + } + const deepest = alternateDirectories.at(-1)!; + for (const entry of readdirSync(objectDirectory)) { + if (entry !== "info" && entry !== "pack") { + renameSync(join(objectDirectory, entry), join(deepest, entry)); + } + } + const chain = [objectDirectory, ...alternateDirectories]; + for (let index = 0; index < chain.length - 1; index += 1) { + writeFileSync( + join(chain[index]!, "info", "alternates"), + `${chain[index + 1]}\n`, + ); + } + + git(repository, "cat-file", "-e", `${head}^{commit}`); + expect(committedDigest(repository, state, base, head)).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + }); + + test("binds a replacement chain while the source view toggles at every boundary", () => { + const { base, head, repository, state } = createRepository(); + const originalDigest = committedDigest(repository, state, base, head); + const originalIdentity = committedObjectIdentity(repository, base, head); + const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const firstReplacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "first replacement\n" }, + ); + const finalReplacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "final replacement\n" }, + ); + expect(firstReplacement.status, firstReplacement.stderr).toBe(0); + expect(finalReplacement.status, finalReplacement.stderr).toBe(0); + const firstBlob = firstReplacement.stdout.trim(); + const finalBlob = finalReplacement.stdout.trim(); + git(repository, "replace", "-f", originalBlob, firstBlob); + git(repository, "replace", "-f", firstBlob, finalBlob); + + const result = runPythonJson<{ + expected: [string, string]; + final: [string, string]; + identityCalls: number; + pair: [string, string]; + privateView: boolean; + residue: string[]; + viewCount: number; + }>( + [ + "import json, os, stat, subprocess", + "from pathlib import Path", + "import workbench_target as target", + "repository, state = Path(sys.argv[2]).resolve(), Path(sys.argv[3]).resolve()", + "base, head, original_blob, first_blob, final_blob = sys.argv[4:9]", + "original_ref = f'refs/replace/{original_blob}'", + "first_ref = f'refs/replace/{first_blob}'", + "def update(ref, object_id=None):", + " command = ['git', '-C', str(repository), 'update-ref']", + " command.extend(['-d', ref] if object_id is None else [ref, object_id])", + " subprocess.run(command, check=True, stdout=subprocess.DEVNULL)", + "def set_replacements(view):", + " update(original_ref)", + " update(first_ref)", + " if view in {'first', 'chain'}:", + " update(original_ref, first_blob)", + " if view == 'chain':", + " update(first_ref, final_blob)", + "expected = target.committed_diff_content_snapshot(repository, base, head)", + "original_create = target._create_committed_diff_view", + "original_digest = target._committed_diff_content_digest", + "original_identity = target._committed_diff_object_identity", + "views, modes = [], []", + "identity_calls = 0", + "def tracked_create(source, view):", + " object_directory = original_create(source, view)", + " views.append(view)", + " modes.append(stat.S_IMODE(view.parent.stat().st_mode))", + " set_replacements('none')", + " return object_directory", + "def tracked_identity(*args, **kwargs):", + " global identity_calls", + " set_replacements('first' if identity_calls == 0 else 'none')", + " identity_calls += 1", + " result = original_identity(*args, **kwargs)", + " set_replacements('none' if identity_calls == 1 else 'first')", + " return result", + "def tracked_digest(*args, **kwargs):", + " set_replacements('none')", + " result = original_digest(*args, **kwargs)", + " set_replacements('first')", + " return result", + "target._create_committed_diff_view = tracked_create", + "target._committed_diff_content_digest = tracked_digest", + "target._committed_diff_object_identity = tracked_identity", + "try:", + " pair = target.committed_diff_content_snapshot(repository, base, head)", + "finally:", + " target._create_committed_diff_view = original_create", + " target._committed_diff_content_digest = original_digest", + " target._committed_diff_object_identity = original_identity", + " set_replacements('chain')", + "final = target.committed_diff_content_snapshot(repository, base, head)", + "def outside_source(path):", + " try:", + " path.resolve().relative_to(repository)", + " except ValueError:", + " return True", + " return False", + "private_view = all(outside_source(view) for view in views) and (os.name == 'nt' or modes == [0o700])", + "print(json.dumps({'expected': expected, 'final': final, 'identityCalls': identity_calls, 'pair': pair, 'privateView': private_view, 'residue': sorted(entry.name for entry in state.iterdir()), 'viewCount': len(views)}))", + ], + [repository, state, base, head, originalBlob, firstBlob, finalBlob], + state, + ); + + expect(result.pair).toEqual(result.expected); + expect(result.final).toEqual(result.expected); + expect(result.expected[0]).not.toBe(originalDigest); + expect(result.expected[1]).not.toBe(originalIdentity); + expect(result).toMatchObject({ + identityCalls: 2, + privateView: true, + residue: [], + viewCount: 1, + }); + }); + + test("cleans private views without mutating target Git metadata", () => { + const { base, head, repository, state } = createRepository(); + const result = runPythonJson<{ + error: string; + privateViews: boolean; + residue: string[]; + sourceUnchanged: boolean; + viewsRemoved: boolean; + }>( + [ + "import hashlib, json, subprocess", + "from pathlib import Path", + "import workbench_target as target", + "repository, state = Path(sys.argv[2]).resolve(), Path(sys.argv[3]).resolve()", + "base, head = sys.argv[4:6]", + "git_dir = Path(subprocess.check_output(['git', '-C', str(repository), 'rev-parse', '--absolute-git-dir'], text=True).strip()).resolve()", + "def fingerprint():", + " result = {}", + " for name in ('HEAD', 'config', 'index', 'packed-refs', 'shallow'):", + " path = git_dir / name", + " result[name] = None if not path.is_file() else hashlib.sha256(path.read_bytes()).hexdigest()", + " for root_name in ('refs', 'logs', 'objects'):", + " root = git_dir / root_name", + " if root.is_dir():", + " for path in sorted(entry for entry in root.rglob('*') if entry.is_file()):", + " result[path.relative_to(git_dir).as_posix()] = hashlib.sha256(path.read_bytes()).hexdigest()", + " return result", + "before = fingerprint()", + "original_create = target._create_committed_diff_view", + "views = []", + "def tracked_create(source, view):", + " views.append(view)", + " return original_create(source, view)", + "target._create_committed_diff_view = tracked_create", + "target.committed_diff_content_snapshot(repository, base, head)", + "after_success = fingerprint()", + "original_digest = target._committed_diff_content_digest", + "def unavailable(*args, **kwargs):", + " raise SystemExit('synthetic snapshot failure')", + "target._committed_diff_content_digest = unavailable", + "try:", + " target.committed_diff_content_snapshot(repository, base, head)", + "except SystemExit as exc:", + " error = str(exc)", + "finally:", + " target._create_committed_diff_view = original_create", + " target._committed_diff_content_digest = original_digest", + "after_failure = fingerprint()", + "def outside_source(path):", + " try:", + " path.resolve().relative_to(repository)", + " except ValueError:", + " return True", + " return False", + "print(json.dumps({'error': error, 'privateViews': len(views) == 2 and all(outside_source(view) for view in views), 'residue': sorted(entry.name for entry in state.iterdir()), 'sourceUnchanged': before == after_success == after_failure, 'viewsRemoved': all(not view.exists() for view in views)}))", + ], + [repository, state, base, head], + state, + ); + + expect(result).toEqual({ + error: "synthetic snapshot failure", + privateViews: true, + residue: [], + sourceUnchanged: true, + viewsRemoved: true, + }); + }); + + test.each([ + ["a non-HEAD working-tree base", "working_tree"], + ["equal resolved refs", "range"], + ] as const)( + "accepts a CLI registration with %s behind a writer lock", + (_label, selection) => { + const { base, head, repository, root, state } = createRepository(); + const requestedBase = selection === "working_tree" ? "HEAD~1" : "HEAD~0"; + const expectedBase = selection === "working_tree" ? base : head; + const scanDirectory = join(root, "compatible-cli-scan"); + mkdirSync(scanDirectory, { mode: 0o700 }); + + const result = runPythonJson<{ + beginAttempted: boolean; + counts: { scans: number; workspaces: number }; + error: string | null; + inTransaction: boolean; + persisted: { + baseRevision: string; + contentDigest: string; + headRevision: string; + kind: string; + } | null; + started: boolean; + }>( + [ + "import argparse, json, threading", + "import workbench_db as workbench", + "selection, repository, scan_directory, selected_base, selected_head = sys.argv[2:7]", + "recipe_kind = 'working_tree' if selection == 'working_tree' else 'refs'", + "recipe = {'config': {}, 'mode': 'standard', 'repository': repository, 'target': {'kind': recipe_kind, 'paths': [], 'base': selected_base, 'head': selected_head}}", + "arguments = argparse.Namespace(repository=repository, scan_dir=scan_directory, registration_json_stdin=False, recipe_json_stdin=False, recipe_json=json.dumps(recipe), archive_existing=False, archived_scan_dir=None, parent_scan_id=None)", + "begin_attempted = threading.Event()", + "connection_ready = threading.Event()", + "start_worker = threading.Event()", + "outcome = {'error': None, 'inTransaction': None, 'started': False}", + "class TrackedConnection:", + " def __init__(self, delegate):", + " self.delegate = delegate", + " def execute(self, sql, *args):", + " if sql.strip().upper() == 'BEGIN IMMEDIATE':", + " begin_attempted.set()", + " return self.delegate.execute(sql, *args)", + " def __getattr__(self, name):", + " return getattr(self.delegate, name)", + "def worker():", + " with workbench.connect() as connection:", + " connection_ready.set()", + " if not start_worker.wait(5):", + " outcome['error'] = 'worker start timed out'", + " return", + " try:", + " workbench.register_cli_scan(TrackedConnection(connection), arguments)", + " except SystemExit as error:", + " outcome['error'] = str(error)", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = connection.in_transaction", + "thread = threading.Thread(target=worker)", + "thread.start()", + "if not connection_ready.wait(5):", + " raise RuntimeError('worker connection timed out')", + "with workbench.connect() as blocker:", + " blocker.execute('BEGIN IMMEDIATE')", + " start_worker.set()", + " if not begin_attempted.wait(5):", + " raise RuntimeError('registration did not reach writer lock')", + " blocker.commit()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('registration worker did not finish')", + "with workbench.connect() as connection:", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + " row = connection.execute('SELECT diff_target_kind, diff_base_revision, diff_head_revision, diff_content_digest FROM workspaces').fetchone()", + " persisted = None if row is None else {'kind': row['diff_target_kind'], 'baseRevision': row['diff_base_revision'], 'headRevision': row['diff_head_revision'], 'contentDigest': row['diff_content_digest']}", + "print(json.dumps({'beginAttempted': begin_attempted.is_set(), 'counts': counts, 'persisted': persisted, **outcome}))", + ], + [selection, repository, scanDirectory, requestedBase, "HEAD"], + state, + ); + + expect(result.beginAttempted).toBe(true); + expect(result.counts).toEqual({ scans: 1, workspaces: 1 }); + expect(result.error).toBeNull(); + expect(result.inTransaction).toBe(false); + expect(result.persisted).toEqual({ + baseRevision: expectedBase, + contentDigest: expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + headRevision: head, + kind: selection, + }); + expect(result.started).toBe(true); + }, + ); + + test.each([ + ["submitted", "progress"], + ["prompt", "progress"], + ["cli", "progress"], + ["prompt", "completion"], + ] as const)( + "does not hold the SQLite writer lock during a slow %s committed snapshot while an unrelated %s is written", + (operation, writeOperation) => { + const { base, head, repository, root, state } = createRepository(); + const result = runPythonJson<{ + identityTransactions: boolean[]; + scanCount: number; + unrelatedStatus: string; + writeError: string | null; + writeSucceeded: boolean; + snapshotCalls: number; + snapshotTransactions: boolean[]; + startError: string | null; + started: boolean; + }>( + [ + "import argparse, json, os, shutil, threading, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "operation, write_operation, repository, base, head, root, plugin_root = sys.argv[2:9]", + "root_path = Path(root)", + "unrelated_scan_root = root_path / 'unrelated-scans'", + "unrelated_scan_root.mkdir(mode=0o700)", + "unrelated_args = argparse.Namespace(thread_id=f'unrelated-{operation}', target_path=repository, scope='.', mode='standard', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind=None, diff_base_revision=None, diff_head_revision=None, diff_content_digest=None, scan_root=str(unrelated_scan_root), model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " unrelated = workbench.start_prompt_only_scan(connection, unrelated_args)", + " unrelated_scan_id = unrelated['scan']['scanId']", + "completion_args = argparse.Namespace(scan_id=unrelated_scan_id, claim_token=None, cost_json=None, thread_id=None)", + "if write_operation == 'completion':", + " with workbench.connect() as connection:", + " scan = workbench.require_scan(connection, unrelated_scan_id)", + " scan_dir = Path(scan['scan_dir'])", + " shutil.copytree(Path(plugin_root) / 'examples' / 'completed-scan', scan_dir, dirs_exist_ok=True)", + " if os.name != 'nt':", + " scan_dir.parent.chmod(0o700)", + " scan_dir.chmod(0o700)", + " manifest_path = scan_dir / 'scan-manifest.json'", + " manifest = json.loads(manifest_path.read_text())", + " manifest['scan']['id'] = unrelated_scan_id", + " manifest['scan']['target']['kind'] = workbench.expected_target_kinds(scan)[0]", + " manifest['scan'].pop('sealedAt', None)", + " manifest['scan'].pop('artifacts', None)", + " manifest_path.write_text(json.dumps(manifest))", + " for name in ('findings.json', 'coverage.json'):", + " path = scan_dir / name", + " document = json.loads(path.read_text())", + " document['scanId'] = unrelated_scan_id", + " path.write_text(json.dumps(document))", + " workbench.complete_scan(connection, completion_args, prepare_only=True)", + " prepared_completed_at = json.loads(manifest_path.read_text())['scan']['completedAt']", + " workbench.now = lambda: prepared_completed_at", + "workspace_id = str(uuid.uuid4())", + "if operation == 'submitted':", + " create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=None, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='standard', diff_target_kind=None, diff_base_revision=None, diff_head_revision=None, diff_content_digest=None)", + " save_args = argparse.Namespace(workspace_id=workspace_id, target_path=repository, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None)", + " with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " workbench.save_workspace(connection, save_args)", + "prompt_args = argparse.Namespace(thread_id=f'slow-{operation}', target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None, scan_root=str(root_path / 'prompt-scans'), model=None, reasoning_effort=None)", + "(root_path / 'prompt-scans').mkdir(mode=0o700)", + "scan_directory = root_path / 'cli-scan'", + "scan_directory.mkdir(mode=0o700)", + "recipe = {'config': {}, 'mode': 'standard', 'repository': repository, 'target': {'kind': 'refs', 'paths': [], 'base': base, 'head': head}}", + "cli_args = argparse.Namespace(repository=repository, scan_dir=str(scan_directory), registration_json_stdin=False, recipe_json_stdin=False, recipe_json=json.dumps(recipe), archive_existing=False, archived_scan_dir=None, parent_scan_id=None)", + "submitted_args = argparse.Namespace(workspace_id=workspace_id, scan_root=str(root_path / 'submitted-scans'), model=None, reasoning_effort=None)", + "original_snapshot = workbench.committed_diff_content_snapshot", + "original_identity = workbench.committed_diff_object_identity", + "snapshot_started = threading.Event()", + "release_snapshot = threading.Event()", + "worker_connection = None", + "identity_transactions = []", + "snapshot_calls = 0", + "snapshot_transactions = []", + "def slow_snapshot(*args):", + " global snapshot_calls", + " snapshot_calls += 1", + " snapshot_transactions.append(bool(worker_connection and worker_connection.in_transaction))", + " snapshot = original_snapshot(*args)", + " if snapshot_calls == 2:", + " snapshot_started.set()", + " if not release_snapshot.wait(5):", + " raise RuntimeError('slow snapshot release timed out')", + " return snapshot", + "def counted_identity(*args):", + " identity_transactions.append(bool(worker_connection and worker_connection.in_transaction))", + " return original_identity(*args)", + "workbench.committed_diff_content_snapshot = slow_snapshot", + "workbench.committed_diff_object_identity = counted_identity", + "outcome = {'startError': None, 'started': False}", + "def worker():", + " global worker_connection", + " with workbench.connect() as connection:", + " worker_connection = connection", + " try:", + " if operation == 'submitted':", + " workbench.start_scan(connection, submitted_args)", + " elif operation == 'prompt':", + " workbench.start_prompt_only_scan(connection, prompt_args)", + " else:", + " workbench.register_cli_scan(connection, cli_args)", + " except BaseException as error:", + " outcome['startError'] = f'{type(error).__name__}: {error}'", + " else:", + " outcome['started'] = True", + "progress_args = argparse.Namespace(scan_id=unrelated_scan_id, model=None, reasoning_effort=None, preflight_issues_json_stdin=False, preflight_issues_json=None, coordinator_generation=None, claim_token=None, deep_review_pass=None, phase=None, phase_items_total=None, phase_items_completed=None, phase_progress_unit=None, review_items_total=None, review_items_completed=None, reportable_findings_count=None)", + "thread = threading.Thread(target=worker)", + "with workbench.connect() as write_connection:", + " write_connection.execute('PRAGMA busy_timeout = 200')", + " thread.start()", + " if not snapshot_started.wait(5):", + " raise RuntimeError('slow snapshot did not start')", + " try:", + " if write_operation == 'progress':", + " workbench.progress.update_progress(write_connection, progress_args, now=workbench.now, require_scan=workbench.require_scan, scan_context=workbench.scan_context)", + " else:", + " workbench.complete_scan(write_connection, completion_args, prepare_only=False)", + " except BaseException as error:", + " write_error = f'{type(error).__name__}: {error}'", + " write_succeeded = False", + " else:", + " write_error = None", + " write_succeeded = True", + "release_snapshot.set()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('start worker did not finish')", + "with workbench.connect() as connection:", + " scan_count = connection.execute('SELECT COUNT(*) FROM scans').fetchone()[0]", + " unrelated_status = workbench.require_scan(connection, unrelated_scan_id)['status']", + "print(json.dumps({'identityTransactions': identity_transactions, 'scanCount': scan_count, 'snapshotCalls': snapshot_calls, 'snapshotTransactions': snapshot_transactions, 'unrelatedStatus': unrelated_status, 'writeError': write_error, 'writeSucceeded': write_succeeded, **outcome}))", + ], + [operation, writeOperation, repository, base, head, root, PLUGIN_ROOT], + state, + ); + + expect(result).toMatchObject({ + identityTransactions: [true], + scanCount: 2, + snapshotCalls: 2, + snapshotTransactions: [false, false], + startError: null, + started: true, + unrelatedStatus: + writeOperation === "completion" ? "complete" : "running", + writeError: null, + writeSucceeded: true, + }); + }, + ); + + test.each(["working_tree", "commit"] as const)( + "rejoins an active submitted %s scan before revalidating an unavailable target", + (kind) => { + const { base, head, repository, root, state } = createRepository(); + const result = runPythonJson<{ + activeMatchesCreated: boolean; + beginAttempted: boolean; + error: string | null; + inTransaction: boolean; + scanCount: number; + started: boolean; + targetExists: boolean; + }>( + [ + "import argparse, json, threading, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "kind, repository, base, head, root = sys.argv[2:7]", + "workspace_id = str(uuid.uuid4())", + "selected_base = head if kind == 'working_tree' else base", + "create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind=kind, diff_base_revision=selected_base, diff_head_revision=head, diff_content_digest=None)", + "start_args = argparse.Namespace(workspace_id=workspace_id, scan_root=str(Path(root) / 'submitted-scans'), model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " workbench.save_workspace(connection, create_args)", + "begin_attempted = threading.Event()", + "connection_ready = threading.Event()", + "start_worker = threading.Event()", + "outcome = {'error': None, 'inTransaction': None, 'started': False}", + "class TrackedConnection:", + " def __init__(self, delegate):", + " self.delegate = delegate", + " def execute(self, sql, *args):", + " if sql.strip().upper() == 'BEGIN IMMEDIATE':", + " begin_attempted.set()", + " return self.delegate.execute(sql, *args)", + " def __getattr__(self, name):", + " return getattr(self.delegate, name)", + "def worker():", + " with workbench.connect() as delegate:", + " connection_ready.set()", + " if not start_worker.wait(5):", + " outcome['error'] = 'worker start timed out'", + " return", + " try:", + " workbench.start_scan(TrackedConnection(delegate), start_args)", + " except BaseException as error:", + " outcome['error'] = f'{type(error).__name__}: {error}'", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = delegate.in_transaction", + "thread = threading.Thread(target=worker)", + "thread.start()", + "if not connection_ready.wait(5):", + " raise RuntimeError('worker connection timed out')", + "with workbench.connect() as blocker:", + " blocker.execute('BEGIN IMMEDIATE')", + " start_worker.set()", + " if not begin_attempted.wait(5):", + " raise RuntimeError('scan did not reach writer lock')", + " workbench.start_scan(blocker, start_args)", + " created_scan_id = blocker.execute('SELECT active_scan_id FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['active_scan_id']", + " Path(repository).rename(Path(root) / 'parked-repository')", + " blocker.commit()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('scan worker did not finish')", + "with workbench.connect() as connection:", + " active_scan_id = connection.execute('SELECT active_scan_id FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['active_scan_id']", + " scan_count = connection.execute('SELECT COUNT(*) FROM scans WHERE workspace_id = ?', (workspace_id,)).fetchone()[0]", + "print(json.dumps({'activeMatchesCreated': active_scan_id == created_scan_id, 'beginAttempted': begin_attempted.is_set(), 'scanCount': scan_count, 'targetExists': Path(repository).exists(), **outcome}))", + ], + [kind, repository, base, head, root], + state, + ); + + expect(result).toEqual({ + activeMatchesCreated: true, + beginAttempted: true, + error: null, + inTransaction: false, + scanCount: 1, + started: true, + targetExists: false, + }); + }, + ); + + test.each(["commit", "range"] as const)( + "rejoins an active submitted %s scan when external inspection fails after another start", + (kind) => { + const { base, head, repository, root, state } = createRepository(); + const result = runPythonJson<{ + activeMatchesCreated: boolean; + error: string | null; + inTransaction: boolean; + scanCount: number; + started: boolean; + targetExists: boolean; + workerSnapshotCalls: number; + }>( + [ + "import argparse, json, threading, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "kind, repository, base, head, root = sys.argv[2:7]", + "workspace_id = str(uuid.uuid4())", + "create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind=kind, diff_base_revision=base, diff_head_revision=head, diff_content_digest=None)", + "start_args = argparse.Namespace(workspace_id=workspace_id, scan_root=str(Path(root) / 'submitted-scans'), model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " workbench.save_workspace(connection, create_args)", + "inspection_started = threading.Event()", + "release_inspection = threading.Event()", + "worker_identifier = None", + "worker_snapshot_calls = 0", + "original_snapshot = workbench.committed_diff_content_snapshot", + "def delayed_snapshot(*args):", + " global worker_snapshot_calls", + " if threading.get_ident() == worker_identifier:", + " worker_snapshot_calls += 1", + " if worker_snapshot_calls == 2:", + " inspection_started.set()", + " if not release_inspection.wait(5):", + " raise RuntimeError('inspection release timed out')", + " return original_snapshot(*args)", + "workbench.committed_diff_content_snapshot = delayed_snapshot", + "outcome = {'error': None, 'inTransaction': None, 'started': False}", + "def worker():", + " global worker_identifier", + " worker_identifier = threading.get_ident()", + " with workbench.connect() as connection:", + " try:", + " workbench.start_scan(connection, start_args)", + " except BaseException as error:", + " outcome['error'] = f'{type(error).__name__}: {error}'", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = connection.in_transaction", + "thread = threading.Thread(target=worker)", + "thread.start()", + "if not inspection_started.wait(5):", + " raise RuntimeError('worker did not begin its second snapshot')", + "with workbench.connect() as creator:", + " workbench.start_scan(creator, start_args)", + " created_scan_id = creator.execute('SELECT active_scan_id FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['active_scan_id']", + " Path(repository).rename(Path(root) / 'parked-repository')", + "release_inspection.set()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('scan worker did not finish')", + "with workbench.connect() as connection:", + " active_scan_id = connection.execute('SELECT active_scan_id FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['active_scan_id']", + " scan_count = connection.execute('SELECT COUNT(*) FROM scans WHERE workspace_id = ?', (workspace_id,)).fetchone()[0]", + "print(json.dumps({'activeMatchesCreated': active_scan_id == created_scan_id, 'scanCount': scan_count, 'targetExists': Path(repository).exists(), 'workerSnapshotCalls': worker_snapshot_calls, **outcome}))", + ], + [kind, repository, base, head, root], + state, + ); + + expect(result).toEqual({ + activeMatchesCreated: true, + error: null, + inTransaction: false, + scanCount: 1, + started: true, + targetExists: false, + workerSnapshotCalls: 2, + }); + }, + ); + + test("rejoins an active submitted commit scan after waiting on post-inspection contention", () => { + const { base, head, repository, root, state } = createRepository(); + const result = runPythonJson<{ + activeMatchesCreated: boolean; + beginAttempts: number; + error: string | null; + inTransaction: boolean; + restoreTimeoutReached: boolean; + scanCount: number; + started: boolean; + targetExists: boolean; + zeroTimeoutReached: boolean; + }>( + [ + "import argparse, json, threading, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "repository, base, head, root = sys.argv[2:6]", + "workspace_id = str(uuid.uuid4())", + "create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='commit', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None)", + "start_args = argparse.Namespace(workspace_id=workspace_id, scan_root=str(Path(root) / 'submitted-scans'), model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " workbench.save_workspace(connection, create_args)", + "connection_ready = threading.Event()", + "zero_timeout_reached = threading.Event()", + "writer_ready = threading.Event()", + "restore_timeout_reached = threading.Event()", + "writer_committed = threading.Event()", + "outcome = {'beginAttempts': 0, 'error': None, 'inTransaction': None, 'started': False}", + "class TrackedConnection:", + " def __init__(self, delegate):", + " self.delegate = delegate", + " def execute(self, sql, *args):", + " normalized = sql.strip().upper()", + " if normalized == 'BEGIN IMMEDIATE':", + " outcome['beginAttempts'] += 1", + " elif normalized == 'PRAGMA BUSY_TIMEOUT = 0':", + " zero_timeout_reached.set()", + " if not writer_ready.wait(5):", + " raise RuntimeError('writer did not acquire the post-inspection lock')", + " elif normalized.startswith('PRAGMA BUSY_TIMEOUT = '):", + " restore_timeout_reached.set()", + " if not writer_committed.wait(5):", + " raise RuntimeError('writer did not commit before blocking retry')", + " return self.delegate.execute(sql, *args)", + " def __getattr__(self, name):", + " return getattr(self.delegate, name)", + "def worker():", + " with workbench.connect() as delegate:", + " connection_ready.set()", + " try:", + " workbench.start_scan(TrackedConnection(delegate), start_args)", + " except BaseException as error:", + " outcome['error'] = f'{type(error).__name__}: {error}'", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = delegate.in_transaction", + "thread = threading.Thread(target=worker)", + "thread.start()", + "if not connection_ready.wait(5):", + " raise RuntimeError('worker connection timed out')", + "if not zero_timeout_reached.wait(5):", + " raise RuntimeError('worker did not complete its external inspection')", + "with workbench.connect() as blocker:", + " blocker.execute('BEGIN IMMEDIATE')", + " workbench.start_scan(blocker, start_args)", + " created_scan_id = blocker.execute('SELECT active_scan_id FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['active_scan_id']", + " Path(repository).rename(Path(root) / 'parked-repository')", + " writer_ready.set()", + " if not restore_timeout_reached.wait(5):", + " raise RuntimeError('worker did not reach its blocking retry')", + " blocker.commit()", + " writer_committed.set()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('scan worker did not finish')", + "with workbench.connect() as connection:", + " active_scan_id = connection.execute('SELECT active_scan_id FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['active_scan_id']", + " scan_count = connection.execute('SELECT COUNT(*) FROM scans WHERE workspace_id = ?', (workspace_id,)).fetchone()[0]", + "print(json.dumps({'activeMatchesCreated': active_scan_id == created_scan_id, 'restoreTimeoutReached': restore_timeout_reached.is_set(), 'scanCount': scan_count, 'targetExists': Path(repository).exists(), 'zeroTimeoutReached': zero_timeout_reached.is_set(), **outcome}))", + ], + [repository, base, head, root], + state, + ); + + expect(result).toEqual({ + activeMatchesCreated: true, + beginAttempts: 3, + error: null, + inTransaction: false, + restoreTimeoutReached: true, + scanCount: 1, + started: true, + targetExists: false, + zeroTimeoutReached: true, + }); + }); + + test.each([ + ["submitted", "before-begin"], + ["prompt", "before-begin"], + ["cli", "before-begin"], + ["submitted", "after-digest"], + ["prompt", "after-digest"], + ["cli", "after-digest"], + ] as const)( + "rejects a %s committed target when a lock-only writer finishes %s", + (operation, timing) => { + const { base, head, repository, root, state } = createRepository(); + const selectedBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "changed in completed gap\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + + const result = runPythonJson<{ + counts: { scans: number; workspaces: number }; + currentDigest: string; + error: string | null; + identityCalls: number; + identityTransactions: boolean[]; + raceCommitted: boolean; + inTransaction: boolean; + snapshotCalls: number; + snapshotTransactions: boolean[]; + started: boolean; + storedDigest: string | null; + storedMatchesCurrent: boolean | null; + }>( + [ + "import argparse, json, sqlite3, subprocess, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "operation, timing, repository, base, head, root, selected_blob, replacement_blob = sys.argv[2:10]", + "root_path = Path(root)", + "workspace_id = str(uuid.uuid4())", + "if operation == 'submitted':", + " create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=None, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='standard', diff_target_kind=None, diff_base_revision=None, diff_head_revision=None, diff_content_digest=None)", + " save_args = argparse.Namespace(workspace_id=workspace_id, target_path=repository, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None)", + " with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " workbench.save_workspace(connection, save_args)", + "prompt_args = argparse.Namespace(thread_id='completed-gap-prompt', target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None, scan_root=str(root_path / 'prompt-scans'), model=None, reasoning_effort=None)", + "submitted_args = argparse.Namespace(workspace_id=workspace_id, scan_root=str(root_path / 'submitted-scans'), model=None, reasoning_effort=None)", + "scan_directory = root_path / 'cli-scan'", + "scan_directory.mkdir(mode=0o700)", + "recipe = {'config': {}, 'mode': 'standard', 'repository': repository, 'target': {'kind': 'refs', 'paths': [], 'base': base, 'head': head}}", + "cli_args = argparse.Namespace(repository=repository, scan_dir=str(scan_directory), registration_json_stdin=False, recipe_json_stdin=False, recipe_json=json.dumps(recipe), archive_existing=False, archived_scan_dir=None, parent_scan_id=None)", + "original_snapshot = workbench.committed_diff_content_snapshot", + "original_identity = workbench.committed_diff_object_identity", + "worker_connection = None", + "identity_calls = 0", + "identity_transactions = []", + "snapshot_calls = 0", + "snapshot_transactions = []", + "race_armed = False", + "race_committed = False", + "def commit_race():", + " global race_committed", + " if race_committed:", + " return", + " race_committed = True", + " with sqlite3.connect(workbench.database_path(), timeout=1) as writer:", + " writer.execute('BEGIN IMMEDIATE')", + " subprocess.run(['git', '-C', repository, 'replace', '-f', selected_blob, replacement_blob], check=True)", + " writer.commit()", + "class RacedConnection:", + " def __init__(self, delegate):", + " self.delegate = delegate", + " def execute(self, sql, *args):", + " global race_armed, race_committed", + " normalized = ' '.join(sql.upper().split())", + " if timing == 'before-begin' and normalized == 'PRAGMA BUSY_TIMEOUT = 0':", + " race_armed = True", + " elif normalized == 'BEGIN IMMEDIATE' and race_armed:", + " race_armed = False", + " commit_race()", + " return self.delegate.execute(sql, *args)", + " def __getattr__(self, name):", + " return getattr(self.delegate, name)", + "def raced_snapshot(*args):", + " global snapshot_calls", + " snapshot_calls += 1", + " snapshot_transactions.append(bool(worker_connection and worker_connection.in_transaction))", + " snapshot = original_snapshot(*args)", + " if timing == 'after-digest' and snapshot_calls == 2:", + " commit_race()", + " return snapshot", + "def raced_identity(*args):", + " global identity_calls", + " identity_calls += 1", + " identity_transactions.append(bool(worker_connection and worker_connection.in_transaction))", + " return original_identity(*args)", + "workbench.committed_diff_content_snapshot = raced_snapshot", + "workbench.committed_diff_object_identity = raced_identity", + "outcome = {'error': None, 'started': False}", + "with workbench.connect() as connection:", + " worker_connection = connection", + " raced_connection = RacedConnection(connection)", + " try:", + " if operation == 'submitted':", + " workbench.start_scan(raced_connection, submitted_args)", + " elif operation == 'prompt':", + " workbench.start_prompt_only_scan(raced_connection, prompt_args)", + " else:", + " workbench.register_cli_scan(raced_connection, cli_args)", + " except SystemExit as error:", + " outcome['error'] = str(error)", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = connection.in_transaction", + "current_digest = original_snapshot(Path(repository), base, head)[0]", + "with workbench.connect() as connection:", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + " row = connection.execute('SELECT diff_content_digest FROM scans ORDER BY created_at DESC LIMIT 1').fetchone()", + "stored_digest = None if row is None else row['diff_content_digest']", + "print(json.dumps({'counts': counts, 'currentDigest': current_digest, 'identityCalls': identity_calls, 'identityTransactions': identity_transactions, 'raceCommitted': race_committed, 'snapshotCalls': snapshot_calls, 'snapshotTransactions': snapshot_transactions, 'storedDigest': stored_digest, 'storedMatchesCurrent': None if stored_digest is None else stored_digest == current_digest, **outcome}))", + ], + [ + operation, + timing, + repository, + base, + head, + root, + selectedBlob, + replacement.stdout.trim(), + ], + state, + ); + + expect(result).toEqual({ + counts: + operation === "submitted" + ? { scans: 0, workspaces: 1 } + : { scans: 0, workspaces: 0 }, + currentDigest: expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + error: + "The selected scan target changed while the scan was starting. Try again.", + identityCalls: 1, + identityTransactions: [true], + inTransaction: false, + raceCommitted: true, + snapshotCalls: 2, + snapshotTransactions: [false, false], + started: false, + storedDigest: null, + storedMatchesCurrent: null, + }); + }, + ); + + test.each(["submitted", "prompt", "cli"] as const)( + "never accepts a stale %s digest when every snapshot is paired with a restored replacement view", + (operation) => { + const { base, head, repository, root, state } = createRepository(); + const selectedBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "repeatable replacement view\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + + const result = runPythonJson<{ + counts: { scans: number; workspaces: number }; + currentDigest: string; + error: string | null; + inTransaction: boolean; + mutationEpochs: number; + snapshotCalls: number; + snapshotTransactions: boolean[]; + started: boolean; + storedDigest: string | null; + storedMatchesCurrent: boolean | null; + }>( + [ + "import argparse, json, sqlite3, subprocess, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "operation, repository, base, head, root, selected_blob, replacement_blob = sys.argv[2:9]", + "root_path = Path(root)", + "workspace_id = str(uuid.uuid4())", + "if operation == 'submitted':", + " create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=None, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='standard', diff_target_kind=None, diff_base_revision=None, diff_head_revision=None, diff_content_digest=None)", + " save_args = argparse.Namespace(workspace_id=workspace_id, target_path=repository, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None)", + " with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " workbench.save_workspace(connection, save_args)", + "prompt_args = argparse.Namespace(thread_id='repeatable-pair-prompt', target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None, scan_root=str(root_path / 'prompt-scans'), model=None, reasoning_effort=None)", + "submitted_args = argparse.Namespace(workspace_id=workspace_id, scan_root=str(root_path / 'submitted-scans'), model=None, reasoning_effort=None)", + "scan_directory = root_path / 'cli-scan'", + "scan_directory.mkdir(mode=0o700)", + "recipe = {'config': {}, 'mode': 'standard', 'repository': repository, 'target': {'kind': 'refs', 'paths': [], 'base': base, 'head': head}}", + "cli_args = argparse.Namespace(repository=repository, scan_dir=str(scan_directory), registration_json_stdin=False, recipe_json_stdin=False, recipe_json=json.dumps(recipe), archive_existing=False, archived_scan_dir=None, parent_scan_id=None)", + "original_snapshot = workbench.committed_diff_content_snapshot", + "worker_connection = None", + "mutation_epochs = 0", + "snapshot_calls = 0", + "snapshot_transactions = []", + "subprocess.run(['git', '-C', repository, 'replace', '-f', selected_blob, replacement_blob], check=True)", + "def mutate_replacement(action):", + " global mutation_epochs", + " mutation_epochs += 1", + " with sqlite3.connect(workbench.database_path(), timeout=1) as writer:", + " writer.execute('BEGIN IMMEDIATE')", + " command = ['git', '-C', repository, 'replace']", + " if action == 'remove':", + " command.extend(['-d', selected_blob])", + " else:", + " command.extend(['-f', selected_blob, replacement_blob])", + " subprocess.run(command, check=True, stdout=subprocess.DEVNULL)", + " writer.commit()", + "def split_snapshot(snapshot, *args):", + " global snapshot_calls", + " snapshot_calls += 1", + " snapshot_transactions.append(bool(worker_connection and worker_connection.in_transaction))", + " mutate_replacement('remove')", + " try:", + " return snapshot(*args)", + " finally:", + " mutate_replacement('restore')", + "def raced_snapshot(*args):", + " return split_snapshot(original_snapshot, *args)", + "workbench.committed_diff_content_snapshot = raced_snapshot", + "outcome = {'error': None, 'started': False}", + "with workbench.connect() as connection:", + " worker_connection = connection", + " try:", + " if operation == 'submitted':", + " workbench.start_scan(connection, submitted_args)", + " elif operation == 'prompt':", + " workbench.start_prompt_only_scan(connection, prompt_args)", + " else:", + " workbench.register_cli_scan(connection, cli_args)", + " except SystemExit as error:", + " outcome['error'] = str(error)", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = connection.in_transaction", + "workbench.committed_diff_content_snapshot = original_snapshot", + "current_digest = original_snapshot(Path(repository), base, head)[0]", + "with workbench.connect() as connection:", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + " row = connection.execute('SELECT diff_content_digest FROM scans ORDER BY created_at DESC LIMIT 1').fetchone()", + "stored_digest = None if row is None else row['diff_content_digest']", + "print(json.dumps({'counts': counts, 'currentDigest': current_digest, 'mutationEpochs': mutation_epochs, 'snapshotCalls': snapshot_calls, 'snapshotTransactions': snapshot_transactions, 'storedDigest': stored_digest, 'storedMatchesCurrent': None if stored_digest is None else stored_digest == current_digest, **outcome}))", + ], + [ + operation, + repository, + base, + head, + root, + selectedBlob, + replacement.stdout.trim(), + ], + state, + ); + + expect(result).toEqual({ + counts: + operation === "submitted" + ? { scans: 0, workspaces: 1 } + : { scans: 0, workspaces: 0 }, + currentDigest: expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + error: + "The selected scan target changed while the scan was starting. Try again.", + inTransaction: false, + mutationEpochs: 4, + snapshotCalls: 2, + snapshotTransactions: [false, false], + started: false, + storedDigest: null, + storedMatchesCurrent: null, + }); + }, + ); + + test.each(["working_tree", "commit", "range"] as const)( + "rejects a %s CLI registration when the target changes behind a writer lock", + (selection) => { + const { base, head, repository, root, state } = createRepository(); + writeFileSync(join(repository, "fixture.txt"), "range head\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "range head"); + const rangeHead = git(repository, "rev-parse", "HEAD"); + const selectedBase = selection === "working_tree" ? rangeHead : base; + const selectedHead = selection === "commit" ? head : rangeHead; + const selectedBlob = git( + repository, + "rev-parse", + `${selectedHead}:fixture.txt`, + ); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "changed behind lock\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + const scanDirectory = join(root, "cli-scan"); + mkdirSync(scanDirectory, { mode: 0o700 }); + + const result = runPythonJson<{ + beginAttempted: boolean; + counts: { scans: number; workspaces: number }; + error: string | null; + inTransaction: boolean; + scanDirectoryEntries: string[]; + snapshotTransactions: boolean[]; + started: boolean; + }>( + [ + "import argparse, json, subprocess, threading", + "from pathlib import Path", + "import workbench_db as workbench", + "selection, repository, scan_directory, selected_base, selected_head, selected_blob, replacement_blob = sys.argv[2:9]", + "recipe_kind = 'working_tree' if selection == 'working_tree' else 'refs'", + "recipe = {'config': {}, 'mode': 'standard', 'repository': repository, 'target': {'kind': recipe_kind, 'paths': [], 'base': selected_base, 'head': selected_head}}", + "arguments = argparse.Namespace(repository=repository, scan_dir=scan_directory, registration_json_stdin=False, recipe_json_stdin=False, recipe_json=json.dumps(recipe), archive_existing=False, archived_scan_dir=None, parent_scan_id=None)", + "snapshot_name = 'worktree_content_digest' if selection == 'working_tree' else 'committed_diff_content_snapshot'", + "original_snapshot = getattr(workbench, snapshot_name)", + "snapshot_transactions = []", + "worker_connection = None", + "def counted_snapshot(*args, **kwargs):", + " snapshot_transactions.append(bool(worker_connection and worker_connection.in_transaction))", + " return original_snapshot(*args, **kwargs)", + "setattr(workbench, snapshot_name, counted_snapshot)", + "begin_attempted = threading.Event()", + "connection_ready = threading.Event()", + "start_worker = threading.Event()", + "outcome = {'error': None, 'inTransaction': None, 'started': False}", + "class TrackedConnection:", + " def __init__(self, delegate):", + " self.delegate = delegate", + " def execute(self, sql, *args):", + " if sql.strip().upper() == 'BEGIN IMMEDIATE':", + " begin_attempted.set()", + " return self.delegate.execute(sql, *args)", + " def __getattr__(self, name):", + " return getattr(self.delegate, name)", + "def worker():", + " global worker_connection", + " with workbench.connect() as delegate:", + " worker_connection = delegate", + " connection_ready.set()", + " if not start_worker.wait(5):", + " outcome['error'] = 'worker start timed out'", + " return", + " try:", + " workbench.register_cli_scan(TrackedConnection(delegate), arguments)", + " except SystemExit as error:", + " outcome['error'] = str(error)", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = delegate.in_transaction", + "thread = threading.Thread(target=worker)", + "thread.start()", + "if not connection_ready.wait(5):", + " raise RuntimeError('worker connection timed out')", + "with workbench.connect() as blocker:", + " blocker.execute('BEGIN IMMEDIATE')", + " start_worker.set()", + " if not begin_attempted.wait(5):", + " raise RuntimeError('registration did not reach writer lock')", + " if selection == 'working_tree':", + " (Path(repository) / 'fixture.txt').write_text('changed behind lock\\n')", + " else:", + " subprocess.run(['git', '-C', repository, 'replace', '-f', selected_blob, replacement_blob], check=True)", + " blocker.commit()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('registration worker did not finish')", + "with workbench.connect() as connection:", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + "print(json.dumps({'beginAttempted': begin_attempted.is_set(), 'counts': counts, 'scanDirectoryEntries': sorted(entry.name for entry in Path(scan_directory).iterdir()), 'snapshotTransactions': snapshot_transactions, **outcome}))", + ], + [ + selection, + repository, + scanDirectory, + selectedBase, + selectedHead, + selectedBlob, + replacement.stdout.trim(), + ], + state, + ); + + expect(result).toEqual({ + beginAttempted: true, + counts: { scans: 0, workspaces: 0 }, + error: + selection === "working_tree" + ? "Working-tree contents changed after they were selected. Select Uncommitted changes again." + : "The committed changes selected for review no longer produce the same diff. Select the changes to review again.", + inTransaction: false, + scanDirectoryEntries: [], + snapshotTransactions: + selection === "working_tree" ? [false, true] : [false, false], + started: false, + }); + }, + ); + + test("rejects a status-zero missing blob from an upgraded cache before insertion", async () => { + expect(python).not.toBeNull(); + const { base, head, repository, root, state } = createRepository(); + const installedRoot = await upgradeBundledPlugin(root); + const blob = git(repository, "rev-parse", `${head}:fixture.txt`); + const objectPath = join( + repository, + ".git", + "objects", + blob.slice(0, 2), + blob.slice(2), + ); + const backupPath = `${objectPath}.backup`; + const scanDirectory = join(root, "scan"); + mkdirSync(scanDirectory, { mode: 0o700 }); + renameSync(objectPath, backupPath); + try { + const missing = spawnSync("git", ["cat-file", "--batch", "-z"], { + cwd: repository, + input: Buffer.from(`${blob}\0`), + }); + expect(missing.status, missing.stderr.toString()).toBe(0); + expect(missing.stdout).toEqual(Buffer.from(`${blob} missing\n`)); + } finally { + renameSync(backupPath, objectPath); + } + + const probe = runPythonJson<{ + digestTransactions: boolean[]; + error: string | null; + inserted: { scans: number; workspaces: number }; + }>( + [ + "import argparse, json", + "from pathlib import Path", + "import workbench_db as workbench", + "repository, scan_directory, base, head = sys.argv[2:6]", + "object_path, backup_path = Path(sys.argv[6]), Path(sys.argv[7])", + "recipe = {'config': {}, 'mode': 'standard', 'repository': repository, 'target': {'kind': 'refs', 'paths': [], 'base': base, 'head': head}}", + "arguments = argparse.Namespace(repository=repository, scan_dir=scan_directory, registration_json_stdin=False, recipe_json_stdin=False, recipe_json=json.dumps(recipe), archive_existing=False, archived_scan_dir=None, parent_scan_id=None)", + "original_digest = workbench.committed_diff_content_snapshot", + "digest_transactions = []", + "def tracked_digest(*args):", + " digest_transactions.append(connection.in_transaction)", + " return original_digest(*args)", + "workbench.committed_diff_content_snapshot = tracked_digest", + "original_count = workbench.directory_snapshot_regular_file_count", + "def remove_blob_during_count(path):", + " count = original_count(path)", + " object_path.rename(backup_path)", + " return count", + "workbench.directory_snapshot_regular_file_count = remove_blob_during_count", + "with workbench.connect() as connection:", + " before = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + " try:", + " workbench.register_cli_scan(connection, arguments)", + " except SystemExit as error:", + " message = str(error)", + " else:", + " message = None", + " finally:", + " if backup_path.exists():", + " backup_path.rename(object_path)", + " after = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + "print(json.dumps({'digestTransactions': digest_transactions, 'error': message, 'inserted': {table: after[table] - before[table] for table in before}}))", + ], + [repository, scanDirectory, base, head, objectPath, backupPath], + state, + {}, + join(installedRoot, "scripts"), + ); + + expect(probe).toEqual({ + digestTransactions: [false, false], + error: "Could not snapshot the selected committed changes.", + inserted: { scans: 0, workspaces: 0 }, + }); + }); + + test("rejects substituted committed blob bytes during reselection", () => { + const { base, head, repository, state } = createRepository(); + const selectedDigest = committedDigest(repository, state, base, head); + const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "substituted\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + git(repository, "replace", "-f", originalBlob, replacement.stdout.trim()); + expect(committedDigest(repository, state, base, head)).not.toBe( + selectedDigest, + ); + expect( + runPython( + [ + "from workbench_db import inspect_setup_values", + "try:", + " inspect_setup_values(sys.argv[2], '.', 'diff', 'range', sys.argv[3], sys.argv[4], sys.argv[5])", + "except SystemExit as error:", + " print(error)", + ], + [repository, base, head, selectedDigest], + state, + ), + ).toBe( + "The committed changes selected for review no longer produce the same diff. " + + "Select the changes to review again.", + ); + }); + + test.each([ + ["commit", "symbolic"], + ["range", "symbolic"], + ["range", "abbreviated"], + ] as const)( + "binds a failed %s snapshot to its %s revision identity", + (kind, aliasStyle) => { + const { base, head, repository, state } = createRepository(); + const selectedBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const objectPath = join( + repository, + ".git", + "objects", + selectedBlob.slice(0, 2), + selectedBlob.slice(2), + ); + const backupPath = `${objectPath}.backup`; + const nextHead = git( + repository, + "-c", + "user.name=synthetic-test", + "-c", + "user.email=synthetic-test@example.invalid", + "commit-tree", + `${head}^{tree}`, + "-p", + head, + "-m", + "different clean selection", + ); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "substituted after recovery\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + renameSync(objectPath, backupPath); + + const result = runPythonJson<{ + afterRejectedSave: Record; + differentSelection: Record; + persistedAfterFailure: Record; + sameSelectionError: string | null; + setupValidation: { error: string | null; valid: boolean }; + }>( + [ + "import argparse, json, subprocess, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "kind, alias_style, repository, base, head, next_head, selected_blob, replacement_blob = sys.argv[2:10]", + "object_path, backup_path = Path(sys.argv[10]), Path(sys.argv[11])", + "requested_base = None if kind == 'commit' else ('HEAD~1' if alias_style == 'symbolic' else base[:8])", + "requested_head = 'HEAD' if alias_style == 'symbolic' else head[:8]", + "workspace_id = str(uuid.uuid4())", + "def arguments(base_revision, head_revision):", + " return argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind=kind, diff_base_revision=base_revision, diff_head_revision=head_revision, diff_content_digest=None)", + "with workbench.connect() as connection:", + " created = workbench.create_workspace(connection, arguments(requested_base, requested_head))", + " persisted_after_failure = dict(connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + " backup_path.rename(object_path)", + " if kind == 'range' and alias_style == 'symbolic':", + " subprocess.run(['git', '-C', repository, 'replace', '-f', selected_blob, replacement_blob], check=True)", + " try:", + " workbench.save_workspace(connection, arguments(None if kind == 'commit' else base, head))", + " except SystemExit as error:", + " same_selection_error = str(error)", + " else:", + " same_selection_error = None", + " after_rejected_save = dict(connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + " if kind == 'range' and alias_style == 'symbolic':", + " subprocess.run(['git', '-C', repository, 'replace', '-d', selected_blob], check=True, stdout=subprocess.DEVNULL)", + " workbench.save_workspace(connection, arguments(None if kind == 'commit' else head, next_head))", + " different_selection = dict(connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + "print(json.dumps({'setupValidation': created['setupValidation'], 'persistedAfterFailure': persisted_after_failure, 'sameSelectionError': same_selection_error, 'afterRejectedSave': after_rejected_save, 'differentSelection': different_selection}))", + ], + [ + kind, + aliasStyle, + repository, + base, + head, + nextHead, + selectedBlob, + replacement.stdout.trim(), + objectPath, + backupPath, + ], + state, + ); + + const failedSelection = { + diff_base_revision: kind === "commit" ? null : base, + diff_content_digest: null, + diff_head_revision: head, + submitted: 0, + }; + expect(result.setupValidation).toEqual({ + error: "Could not snapshot the selected committed changes.", + valid: false, + }); + expect(result.persistedAfterFailure).toEqual(failedSelection); + expect(result.sameSelectionError).toBe( + "The committed changes selected for review no longer produce the same " + + "diff. Select the changes to review again.", + ); + expect(result.afterRejectedSave).toEqual(failedSelection); + expect(result.differentSelection).toEqual({ + diff_base_revision: head, + diff_content_digest: expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + diff_head_revision: nextHead, + submitted: 1, + }); + }, + ); + + test.each(["commit", "range"] as const)( + "allows correcting an unresolved %s selection before submission", + (kind) => { + const { base, head, repository, state } = createRepository(); + const typoRef = "refs/heads/typoed-selection"; + + const result = runPythonJson<{ + correctedSelection: Record; + persistedAfterFailure: Record; + saveError: string | null; + setupValidation: { error: string | null; valid: boolean }; + }>( + [ + "import argparse, json, uuid", + "import workbench_db as workbench", + "kind, repository, base, head, typo_ref = sys.argv[2:7]", + "workspace_id = str(uuid.uuid4())", + "def arguments(base_revision, head_revision):", + " return argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind=kind, diff_base_revision=base_revision, diff_head_revision=head_revision, diff_content_digest=None)", + "initial_base = None if kind == 'commit' else 'HEAD~1'", + "corrected_base = None if kind == 'commit' else base", + "with workbench.connect() as connection:", + " created = workbench.create_workspace(connection, arguments(initial_base, typo_ref))", + " persisted_after_failure = dict(connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + " try:", + " workbench.save_workspace(connection, arguments(corrected_base, head))", + " except SystemExit as error:", + " save_error = str(error)", + " else:", + " save_error = None", + " corrected_selection = dict(connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + "print(json.dumps({'setupValidation': created['setupValidation'], 'persistedAfterFailure': persisted_after_failure, 'saveError': save_error, 'correctedSelection': corrected_selection}))", + ], + [kind, repository, base, head, typoRef], + state, + ); + + expect(result.setupValidation).toEqual({ + error: `${kind === "commit" ? "Commit" : "Head revision"} does not resolve to a local Git commit: ${typoRef}`, + valid: false, + }); + expect(result.persistedAfterFailure).toEqual({ + diff_base_revision: kind === "commit" ? null : "HEAD~1", + diff_content_digest: null, + diff_head_revision: typoRef, + submitted: 0, + }); + expect(result.saveError).toBeNull(); + expect(result.correctedSelection).toEqual({ + diff_base_revision: base, + diff_content_digest: expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + diff_head_revision: head, + submitted: 1, + }); + }, + ); + + test("rejects legacy same-commit initialization when its retained base changes", () => { + const { base, head, repository, state } = createRepository(); + const baseTree = git(repository, "rev-parse", `${base}^{tree}`); + const headTree = git(repository, "rev-parse", `${head}^{tree}`); + const alternateParent = git( + repository, + "-c", + "user.name=synthetic-test", + "-c", + "user.email=synthetic-test@example.invalid", + "commit-tree", + baseTree, + "-m", + "alternate same-tree parent", + ); + const replacementHead = git( + repository, + "-c", + "user.name=synthetic-test", + "-c", + "user.email=synthetic-test@example.invalid", + "commit-tree", + headTree, + "-p", + alternateParent, + "-m", + "replacement head", + ); + expect(git(repository, "rev-parse", `${alternateParent}^{tree}`)).toBe( + baseTree, + ); + expect(git(repository, "rev-parse", `${replacementHead}^{tree}`)).toBe( + headTree, + ); + + const result = runPythonJson<{ + after: Record; + before: Record; + currentDigest: string; + error: string | null; + observedHead: string; + observedParent: string; + }>( + [ + "import argparse, json, subprocess, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "repository, head, replacement_head = sys.argv[2:5]", + "workspace_id = str(uuid.uuid4())", + "create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='commit', diff_base_revision=None, diff_head_revision=head, diff_content_digest=None)", + "save_args = argparse.Namespace(workspace_id=workspace_id, target_path=repository, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='commit', diff_base_revision=None, diff_head_revision=head, diff_content_digest=None)", + "with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " connection.execute('UPDATE workspaces SET diff_content_digest = NULL WHERE id = ?', (workspace_id,))", + " connection.commit()", + " before = dict(connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + " subprocess.run(['git', '-C', repository, 'replace', '-f', head, replacement_head], check=True)", + " observed_head = subprocess.check_output(['git', '-C', repository, 'rev-parse', head], text=True).strip()", + " observed_parent = subprocess.check_output(['git', '-C', repository, 'rev-parse', f'{head}^'], text=True).strip()", + " current_digest = workbench.committed_diff_content_snapshot(Path(repository), observed_parent, observed_head)[0]", + " save_args.diff_content_digest = current_digest", + " try:", + " workbench.save_workspace(connection, save_args)", + " except SystemExit as error:", + " message = str(error)", + " else:", + " message = None", + " after = dict(connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + "print(json.dumps({'before': before, 'after': after, 'currentDigest': current_digest, 'error': message, 'observedHead': observed_head, 'observedParent': observed_parent}))", + ], + [repository, head, replacementHead], + state, + ); + + expect(result.observedHead).toBe(head); + expect(result.observedParent).toBe(alternateParent); + expect(result.currentDigest).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + expect(result.before).toEqual({ + diff_base_revision: base, + diff_content_digest: null, + diff_head_revision: head, + submitted: 0, + }); + expect(result.error).toBe( + "The committed changes selected for review no longer produce the same " + + "diff. Select the changes to review again.", + ); + expect(result.after).toEqual(result.before); + }); + + test("confines configured digest spools to one private directory", () => { + const { base, head, repository, state } = createRepository(); + const result = runPythonJson<{ + allConfined: boolean; + digest: string; + privateMode: boolean; + residue: string[]; + rootRemoved: boolean; + roots: number; + spools: number; + }>( + [ + "import json, os", + "from pathlib import Path", + "import workbench_target as target", + "temporary_directory = target.tempfile.TemporaryDirectory", + "temporary_file = target.tempfile.TemporaryFile", + "roots, modes, directories = [], [], []", + "class TrackedTemporaryDirectory:", + " def __init__(self, *args, **kwargs):", + " self.inner = temporary_directory(*args, **kwargs)", + " def __enter__(self):", + " directory = self.inner.__enter__()", + " root = Path(directory).resolve()", + " roots.append(root)", + " modes.append(root.stat().st_mode & 0o777)", + " return directory", + " def __exit__(self, *args):", + " return self.inner.__exit__(*args)", + "def tracked_temporary_file(*args, **kwargs):", + " directories.append(Path(kwargs['dir']).resolve())", + " return temporary_file(*args, **kwargs)", + "target.tempfile.TemporaryDirectory = TrackedTemporaryDirectory", + "target.tempfile.TemporaryFile = tracked_temporary_file", + "digest = target.committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4])", + "configured = Path(os.environ['CODEX_SECURITY_STATE_DIR']).resolve()", + "print(json.dumps({'allConfined': len(roots) == 1 and all(directory == roots[0] for directory in directories) and roots[0].parent == configured, 'digest': digest, 'privateMode': modes == [0o700], 'residue': [entry.name for entry in configured.iterdir()], 'rootRemoved': len(roots) == 1 and not roots[0].exists(), 'roots': len(roots), 'spools': len(directories)}))", + ], + [repository, base, head], + state, + ); + + expect(result).toMatchObject({ + allConfined: true, + privateMode: true, + residue: [], + rootRemoved: true, + roots: 1, + spools: 3, + }); + expect(result.digest).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + }); + + test("does not require the persistent state root for setup inspection", () => { + const { base, head, repository, root } = createRepository(); + const blockedHome = join(root, "codex-home-file"); + writeFileSync(blockedHome, "not a directory\n"); + + expect( + committedDigest(repository, undefined, base, head, { + CODEX_HOME: blockedHome, + }), + ).toMatch(/^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u); + expect(existsSync(join(blockedHome, "state"))).toBe(false); + }); + + test("confines state-free digest spools to one disposable directory", () => { + const { base, head, repository, root } = createRepository(); + const temporaryRoot = join(root, "temporary"); + mkdirSync(temporaryRoot, { mode: 0o700 }); + const result = runPythonJson<{ + allConfined: boolean; + digest: string; + residue: string[]; + rootRemoved: boolean; + roots: number; + spools: number; + }>( + [ + "import json", + "from pathlib import Path", + "import workbench_target as target", + "temporary_directory = target.tempfile.TemporaryDirectory", + "temporary_file = target.tempfile.TemporaryFile", + "roots, directories = [], []", + "class TrackedTemporaryDirectory:", + " def __init__(self, *args, **kwargs):", + " self.inner = temporary_directory(*args, **kwargs)", + " def __enter__(self):", + " directory = self.inner.__enter__()", + " roots.append(Path(directory).resolve())", + " return directory", + " def __exit__(self, *args):", + " return self.inner.__exit__(*args)", + "def tracked_temporary_file(*args, **kwargs):", + " directories.append(Path(kwargs['dir']).resolve())", + " return temporary_file(*args, **kwargs)", + "target.tempfile.TemporaryDirectory = TrackedTemporaryDirectory", + "target.tempfile.TemporaryFile = tracked_temporary_file", + "digest = target.committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4])", + "temporary_root = Path(sys.argv[5]).resolve()", + "print(json.dumps({'allConfined': len(roots) == 1 and all(directory == roots[0] for directory in directories) and roots[0].parent == temporary_root, 'digest': digest, 'residue': [entry.name for entry in temporary_root.iterdir() if entry.name.startswith('codex-security-committed-diff-')], 'rootRemoved': len(roots) == 1 and not roots[0].exists(), 'roots': len(roots), 'spools': len(directories)}))", + ], + [repository, base, head, temporaryRoot], + undefined, + { TEMP: temporaryRoot, TMP: temporaryRoot, TMPDIR: temporaryRoot }, + ); + + expect(result).toMatchObject({ + allConfined: true, + residue: [], + rootRemoved: true, + roots: 1, + spools: 3, + }); + expect(result.digest).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + }); + + test("removes the state-free spool directory after snapshot failure", () => { + const { base, head, repository, root } = createRepository(); + const temporaryRoot = join(root, "temporary-failure"); + mkdirSync(temporaryRoot, { mode: 0o700 }); + const blob = git(repository, "rev-parse", `${head}:fixture.txt`); + const objectPath = join( + repository, + ".git", + "objects", + blob.slice(0, 2), + blob.slice(2), + ); + const backupPath = `${objectPath}.backup`; + renameSync(objectPath, backupPath); + try { + expect( + runPython( + [ + "from pathlib import Path", + "from workbench_target import committed_diff_content_digest", + "try:", + " committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4])", + "except SystemExit as error:", + " print(error)", + ], + [repository, base, head], + undefined, + { TEMP: temporaryRoot, TMP: temporaryRoot, TMPDIR: temporaryRoot }, + ), + ).toBe("Could not snapshot the selected committed changes."); + } finally { + renameSync(backupPath, objectPath); + } + expect( + readdirSync(temporaryRoot).filter((entry) => + entry.startsWith("codex-security-committed-diff-"), + ), + ).toEqual([]); + }); + + test("keeps both batch helpers from launching repository promisor helpers", () => { + const { base, head, repository, root, state } = createRepository(); + const helper = join(root, "promisor-helper.mjs"); + const started = join(root, "promisor-started"); + const leaked = join(root, "promisor-environment"); + const blob = git(repository, "rev-parse", `${head}:fixture.txt`); + writeFileSync( + helper, + [ + 'import { writeFileSync } from "node:fs";', + `writeFileSync(${JSON.stringify(started)}, "started");`, + `if (process.env.GIT_CONFIG_VALUE_0) writeFileSync(${JSON.stringify(leaked)}, process.env.GIT_CONFIG_VALUE_0);`, + "process.exit(1);", + ].join("\n"), + { mode: 0o600 }, + ); + git(repository, "config", "extensions.partialClone", "unsafe"); + git(repository, "config", "remote.unsafe.promisor", "true"); + git(repository, "config", "protocol.ext.allow", "always"); + git( + repository, + "config", + "remote.unsafe.url", + `ext::${process.execPath.replaceAll("\\", "/")} ${helper.replaceAll("\\", "/")}`, + ); + const objectPath = join( + repository, + ".git", + "objects", + blob.slice(0, 2), + blob.slice(2), + ); + renameSync(objectPath, `${objectPath}.missing`); + + const result = runPythonJson<{ + blobMissing: boolean; + digestError: string | null; + }>( + [ + "import json", + "from pathlib import Path", + "import workbench_target as target", + "try:", + " target.committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4])", + "except SystemExit as error:", + " digest_error = str(error)", + "else:", + " digest_error = None", + "blobs = target.git_blob_bytes(Path(sys.argv[2]), [sys.argv[5]])", + "print(json.dumps({'blobMissing': blobs == [None], 'digestError': digest_error}))", + ], + [repository, base, head, blob], + state, + { + GIT_ALLOW_PROTOCOL: "ext", + GIT_CONFIG_COUNT: "1", + GIT_CONFIG_KEY_0: "http.extraHeader", + GIT_CONFIG_VALUE_0: "SYNTHETIC_GIT_CREDENTIAL", + }, + ); + + expect(result).toEqual({ + blobMissing: true, + digestError: "Could not snapshot the selected committed changes.", + }); + expect(existsSync(started)).toBe(false); + expect(existsSync(leaked)).toBe(false); + }); + + test("reuses the inspected committed digest when creating a workspace", () => { + const { base, head, repository, state } = createRepository(); + const result = runPythonJson<{ digestCalls: number; valid: boolean }>( + [ + "import argparse, json, uuid", + "import workbench_db as workbench", + "original_digest = workbench.committed_diff_content_snapshot", + "digest_calls = 0", + "def counted_digest(*args):", + " global digest_calls", + " digest_calls += 1", + " return original_digest(*args)", + "workbench.committed_diff_content_snapshot = counted_digest", + "arguments = argparse.Namespace(workspace_id=str(uuid.uuid4()), thread_id=None, target_path=sys.argv[2], target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=sys.argv[3], diff_head_revision=sys.argv[4], diff_content_digest=None)", + "with workbench.connect() as connection:", + " result = workbench.create_workspace(connection, arguments)", + "print(json.dumps({'digestCalls': digest_calls, 'valid': result['setupValidation']['valid']}))", + ], + [repository, base, head], + state, + ); + + expect(result).toEqual({ digestCalls: 1, valid: true }); + }); + + test("reuses the stored digest when saving the same committed selection", () => { + const { base, head, repository, state } = createRepository(); + const result = runPythonJson<{ + after: string; + before: string; + submitted: boolean; + }>( + [ + "import argparse, json, uuid", + "import workbench_db as workbench", + "workspace_id = str(uuid.uuid4())", + "create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=sys.argv[2], target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=sys.argv[3], diff_head_revision=sys.argv[4], diff_content_digest=None)", + "save_args = argparse.Namespace(workspace_id=workspace_id, target_path=sys.argv[2], target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=sys.argv[3], diff_head_revision=sys.argv[4], diff_content_digest=None)", + "with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " before = connection.execute('SELECT diff_content_digest FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['diff_content_digest']", + " workbench.save_workspace(connection, save_args)", + " row = connection.execute('SELECT diff_content_digest, submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()", + "print(json.dumps({'before': before, 'after': row['diff_content_digest'], 'submitted': bool(row['submitted'])}))", + ], + [repository, base, head], + state, + ); + + expect(result.after).toBe(result.before); + expect(result.before).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + expect(result.submitted).toBe(true); + }); + + test.each(["create", "save"] as const)( + "returns a %s response atomically despite a competing SQLite writer", + (operation) => { + const { base, head, repository, state } = createRepository(); + const result = runPythonJson<{ + blockerAcquired: boolean; + blockerAttempted: boolean; + error: string | null; + resultId: string | null; + rowCount: number; + submitted: boolean; + }>( + [ + "import argparse, json, threading, uuid", + "import workbench_db as workbench", + "operation, repository, base, head = sys.argv[2:6]", + "workspace_id = str(uuid.uuid4())", + "blank_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=None, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='standard', diff_target_kind=None, diff_base_revision=None, diff_head_revision=None, diff_content_digest=None)", + "selected_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None)", + "if operation == 'save':", + " with workbench.connect() as setup_connection:", + " workbench.create_workspace(setup_connection, blank_args)", + "blocker_ready = threading.Event()", + "start_blocker = threading.Event()", + "blocker_attempted = threading.Event()", + "blocker_acquired = threading.Event()", + "release_blocker = threading.Event()", + "def block_writer():", + " with workbench.connect() as blocker:", + " blocker_ready.set()", + " if not start_blocker.wait(5):", + " raise RuntimeError('blocker start timed out')", + " blocker_attempted.set()", + " blocker.execute('BEGIN IMMEDIATE')", + " blocker_acquired.set()", + " if not release_blocker.wait(5):", + " raise RuntimeError('blocker release timed out')", + " blocker.rollback()", + "thread = threading.Thread(target=block_writer)", + "thread.start()", + "if not blocker_ready.wait(5):", + " raise RuntimeError('blocker connection timed out')", + "original_inspected_state = workbench.inspected_workspace_state", + "def contended_inspected_state(connection, selected_workspace_id, **kwargs):", + " start_blocker.set()", + " expected_event = blocker_attempted if connection.in_transaction else blocker_acquired", + " if not expected_event.wait(5):", + " raise RuntimeError('blocker did not reach expected state')", + " return original_inspected_state(connection, selected_workspace_id, **kwargs)", + "workbench.inspected_workspace_state = contended_inspected_state", + "with workbench.connect() as connection:", + " connection.execute('PRAGMA busy_timeout = 200')", + " try:", + " response = workbench.create_workspace(connection, selected_args) if operation == 'create' else workbench.save_workspace(connection, selected_args)", + " except BaseException as error:", + " message = f'{type(error).__name__}: {error}'", + " result_id = None", + " else:", + " message = None", + " result_id = response['id']", + "if not blocker_acquired.wait(5):", + " raise RuntimeError('blocker did not acquire the writer lock')", + "release_blocker.set()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('blocker thread did not finish')", + "with workbench.connect() as connection:", + " row_count = connection.execute('SELECT COUNT(*) FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()[0]", + " submitted = bool(connection.execute('SELECT submitted FROM workspaces WHERE id = ?', (workspace_id,)).fetchone()['submitted'])", + "print(json.dumps({'blockerAcquired': blocker_acquired.is_set(), 'blockerAttempted': blocker_attempted.is_set(), 'error': message, 'resultId': result_id, 'rowCount': row_count, 'submitted': submitted}))", + ], + [operation, repository, base, head], + state, + ); + + expect(result).toEqual({ + blockerAcquired: true, + blockerAttempted: true, + error: null, + resultId: expect.any(String), + rowCount: 1, + submitted: operation === "save", + }); + }, + ); + + test("does not repeat a failed setup digest inside SQLite", () => { + const { base, head, repository, state } = createRepository(); + const selectedDigest = committedDigest(repository, state, base, head); + const selectedBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "substituted\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + git(repository, "replace", "-f", selectedBlob, replacement.stdout.trim()); + + const result = runPythonJson<{ + digestTransactions: boolean[]; + setupValidation: { error: string | null; valid: boolean }; + }>( + [ + "import argparse, json, uuid", + "import workbench_db as workbench", + "original_digest = workbench.committed_diff_content_snapshot", + "digest_transactions = []", + "with workbench.connect() as connection:", + " def tracked_digest(*args):", + " digest_transactions.append(connection.in_transaction)", + " return original_digest(*args)", + " workbench.committed_diff_content_snapshot = tracked_digest", + " arguments = argparse.Namespace(workspace_id=str(uuid.uuid4()), thread_id=None, target_path=sys.argv[2], target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=sys.argv[3], diff_head_revision=sys.argv[4], diff_content_digest=sys.argv[5])", + " result = workbench.create_workspace(connection, arguments)", + "print(json.dumps({'digestTransactions': digest_transactions, 'setupValidation': result['setupValidation']}))", + ], + [repository, base, head, selectedDigest], + state, + ); + + expect(result).toEqual({ + digestTransactions: [false], + setupValidation: { + error: + "The committed changes selected for review no longer produce the same diff. " + + "Select the changes to review again.", + valid: false, + }, + }); + }); + + test("rolls back a create rejected during rendering", () => { + const { base, head, repository, state } = createRepository(); + writeFileSync(join(repository, "fixture.txt"), "new head\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "new head"); + const newHead = git(repository, "rev-parse", "HEAD"); + const newDigest = committedDigest(repository, state, head, newHead); + + const result = runPythonJson<{ + digestCalls: number; + persisted: { + baseRevision: string; + contentDigest: string; + headRevision: string; + } | null; + error: string | null; + }>( + [ + "import argparse, json, uuid", + "import workbench_db as workbench", + "repository, base, head, new_head, new_digest = sys.argv[2:7]", + "original_digest = workbench.committed_diff_content_snapshot", + "digest_calls = 0", + "def counted_digest(*args):", + " global digest_calls", + " digest_calls += 1", + " return original_digest(*args)", + "workbench.committed_diff_content_snapshot = counted_digest", + "original_inspected_state = workbench.inspected_workspace_state", + "def raced_inspected_state(connection, workspace_id, **kwargs):", + " connection.execute('UPDATE workspaces SET diff_base_revision = ?, diff_head_revision = ?, diff_content_digest = ?, updated_at = ? WHERE id = ?', (head, new_head, new_digest, '2099-01-01T00:00:00Z', workspace_id))", + " return original_inspected_state(connection, workspace_id, **kwargs)", + "workbench.inspected_workspace_state = raced_inspected_state", + "arguments = argparse.Namespace(workspace_id=str(uuid.uuid4()), thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None)", + "with workbench.connect() as connection:", + " try:", + " workbench.create_workspace(connection, arguments)", + " except SystemExit as error:", + " message = str(error)", + " else:", + " message = None", + " persisted = connection.execute('SELECT diff_base_revision, diff_head_revision, diff_content_digest FROM workspaces WHERE id = ?', (arguments.workspace_id,)).fetchone()", + "persisted_json = None if persisted is None else {'baseRevision': persisted['diff_base_revision'], 'headRevision': persisted['diff_head_revision'], 'contentDigest': persisted['diff_content_digest']}", + "print(json.dumps({'digestCalls': digest_calls, 'error': message, 'persisted': persisted_json}))", + ], + [repository, base, head, newHead, newDigest], + state, + ); + + expect(result).toEqual({ + digestCalls: 1, + error: + "Codex Security setup changed while it was being saved. Try again.", + persisted: null, + }); + }); + + test("rolls back a save rejected during rendering", () => { + const { base, head, repository, state } = createRepository(); + const selectedDigest = committedDigest(repository, state, base, head); + const result = runPythonJson<{ + error: string | null; + unchanged: boolean; + }>( + [ + "import argparse, json, uuid", + "import workbench_db as workbench", + "workspace_id = str(uuid.uuid4())", + "create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=None, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='standard', diff_target_kind=None, diff_base_revision=None, diff_head_revision=None, diff_content_digest=None)", + "with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + "save_args = argparse.Namespace(workspace_id=workspace_id, target_path=sys.argv[2], target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind='range', diff_base_revision=sys.argv[3], diff_head_revision=sys.argv[4], diff_content_digest=sys.argv[5])", + "original_inspected_state = workbench.inspected_workspace_state", + "def raced_inspected_state(connection, selected_workspace_id, **kwargs):", + " connection.execute('UPDATE workspaces SET updated_at = ? WHERE id = ?', ('2099-01-01T00:00:00Z', selected_workspace_id))", + " return original_inspected_state(connection, selected_workspace_id, **kwargs)", + "workbench.inspected_workspace_state = raced_inspected_state", + "with workbench.connect() as connection:", + " before = dict(connection.execute('SELECT target_path, submitted, updated_at FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + " try:", + " workbench.save_workspace(connection, save_args)", + " except SystemExit as error:", + " message = str(error)", + " else:", + " message = None", + " after = dict(connection.execute('SELECT target_path, submitted, updated_at FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + "print(json.dumps({'error': message, 'unchanged': before == after}))", + ], + [repository, base, head, selectedDigest], + state, + ); + + expect(result).toEqual({ + error: + "Codex Security setup changed while it was being saved. Try again.", + unchanged: true, + }); + }); + + test.each(["working_tree", "commit", "range"] as const)( + "rejects a submitted %s start when the target changes behind a writer lock", + (kind) => { + const { base, head, repository, root, state } = createRepository(); + const selectedBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "changed behind lock\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + const replacementBlob = replacement.stdout.trim(); + + const result = runPythonJson<{ + after: { + activeScanId: string | null; + contentDigest: string; + submitted: number; + updatedAt: string; + }; + before: { + activeScanId: string | null; + contentDigest: string; + submitted: number; + updatedAt: string; + }; + beginAttempted: boolean; + error: string | null; + inTransaction: boolean; + scanCount: number; + snapshotCalls: number; + started: boolean; + }>( + [ + "import argparse, json, subprocess, threading, uuid", + "from pathlib import Path", + "import workbench_db as workbench", + "kind, repository, base, head, root, selected_blob, replacement_blob = sys.argv[2:9]", + "workspace_id = str(uuid.uuid4())", + "selected_base = head if kind == 'working_tree' else base", + "create_args = argparse.Namespace(workspace_id=workspace_id, thread_id=None, target_path=repository, target_title=None, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind=kind, diff_base_revision=selected_base, diff_head_revision=head, diff_content_digest=None)", + "save_args = argparse.Namespace(workspace_id=workspace_id, target_path=repository, target_summary=None, user_context=None, user_context_stdin=False, scope='.', mode='diff', diff_target_kind=kind, diff_base_revision=selected_base, diff_head_revision=head, diff_content_digest=None)", + "start_args = argparse.Namespace(workspace_id=workspace_id, scan_root=str(Path(root) / 'submitted-scans'), model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " workbench.create_workspace(connection, create_args)", + " workbench.save_workspace(connection, save_args)", + " before = dict(connection.execute('SELECT active_scan_id AS activeScanId, diff_content_digest AS contentDigest, submitted, updated_at AS updatedAt FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + "snapshot_name = 'worktree_content_digest' if kind == 'working_tree' else 'committed_diff_content_snapshot'", + "original_snapshot = getattr(workbench, snapshot_name)", + "snapshot_calls = 0", + "def counted_snapshot(*args, **kwargs):", + " global snapshot_calls", + " snapshot_calls += 1", + " return original_snapshot(*args, **kwargs)", + "setattr(workbench, snapshot_name, counted_snapshot)", + "begin_attempted = threading.Event()", + "connection_ready = threading.Event()", + "start_worker = threading.Event()", + "outcome = {'error': None, 'inTransaction': None, 'started': False}", + "class TrackedConnection:", + " def __init__(self, delegate):", + " self.delegate = delegate", + " def execute(self, sql, *args):", + " if sql.strip().upper() == 'BEGIN IMMEDIATE':", + " begin_attempted.set()", + " return self.delegate.execute(sql, *args)", + " def __getattr__(self, name):", + " return getattr(self.delegate, name)", + "def worker():", + " with workbench.connect() as delegate:", + " connection_ready.set()", + " if not start_worker.wait(5):", + " outcome['error'] = 'worker start timed out'", + " return", + " try:", + " workbench.start_scan(TrackedConnection(delegate), start_args)", + " except SystemExit as error:", + " outcome['error'] = str(error)", + " else:", + " outcome['started'] = True", + " outcome['inTransaction'] = delegate.in_transaction", + "thread = threading.Thread(target=worker)", + "thread.start()", + "if not connection_ready.wait(5):", + " raise RuntimeError('worker connection timed out')", + "with workbench.connect() as blocker:", + " blocker.execute('BEGIN IMMEDIATE')", + " start_worker.set()", + " if not begin_attempted.wait(5):", + " raise RuntimeError('scan did not reach writer lock')", + " if kind == 'working_tree':", + " (Path(repository) / 'fixture.txt').write_text('changed behind lock\\n')", + " else:", + " subprocess.run(['git', '-C', repository, 'replace', '-f', selected_blob, replacement_blob], check=True)", + " blocker.commit()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('scan worker did not finish')", + "with workbench.connect() as connection:", + " after = dict(connection.execute('SELECT active_scan_id AS activeScanId, diff_content_digest AS contentDigest, submitted, updated_at AS updatedAt FROM workspaces WHERE id = ?', (workspace_id,)).fetchone())", + " scan_count = connection.execute('SELECT COUNT(*) FROM scans WHERE workspace_id = ?', (workspace_id,)).fetchone()[0]", + "print(json.dumps({'after': after, 'before': before, 'beginAttempted': begin_attempted.is_set(), 'scanCount': scan_count, 'snapshotCalls': snapshot_calls, **outcome}))", + ], + [kind, repository, base, head, root, selectedBlob, replacementBlob], + state, + ); + + expect(result).toMatchObject({ + beginAttempted: true, + error: + kind === "working_tree" + ? "Working-tree contents changed after they were selected. Select Uncommitted changes again." + : "The committed changes selected for review no longer produce the same diff. Select the changes to review again.", + inTransaction: false, + scanCount: 0, + snapshotCalls: 2, + started: false, + }); + expect(result.after).toEqual(result.before); + expect(result.before).toMatchObject({ + activeScanId: null, + submitted: 1, + }); + expect(result.before.contentDigest).toMatch( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ); + }, + ); + + test.each([ + ["create", "working_tree"], + ["rejoin", "working_tree"], + ["create", "commit"], + ["rejoin", "commit"], + ] as const)( + "rejects a %s %s start when the target changes behind a writer lock", + (action, kind) => { + const { base, head, repository, root, state } = createRepository(); + const result = runPythonJson<{ + beginAttempted: boolean; + counts: { scans: number; workspaces: number }; + disposition: string | null; + error: string | null; + snapshotCalls: number; + }>( + [ + "import argparse, json, shutil, threading", + "from pathlib import Path", + "import workbench_db as workbench", + "action, kind, repository, base, head, root = sys.argv[2:8]", + "scan_root = Path(root) / 'locked-scans'", + "scan_root.mkdir(mode=0o700)", + "def arguments():", + " return argparse.Namespace(thread_id=f'locked-{action}-{kind}', target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind=kind, diff_base_revision=head if kind == 'working_tree' else base, diff_head_revision=head, diff_content_digest=None, scan_root=str(scan_root), model=None, reasoning_effort=None)", + "if action == 'rejoin':", + " with workbench.connect() as connection:", + " workbench.start_prompt_only_scan(connection, arguments())", + "original_require_diff_target = workbench.require_diff_target_snapshot", + "snapshot_calls = 0", + "def counted_require_diff_target(*args):", + " global snapshot_calls", + " snapshot_calls += 1", + " return original_require_diff_target(*args)", + "workbench.require_diff_target_snapshot = counted_require_diff_target", + "begin_attempted = threading.Event()", + "connection_ready = threading.Event()", + "start_worker = threading.Event()", + "outcome = {'disposition': None, 'error': None}", + "class TrackedConnection:", + " def __init__(self, delegate):", + " self.delegate = delegate", + " def execute(self, sql, *args):", + " if sql.strip().upper() == 'BEGIN IMMEDIATE':", + " begin_attempted.set()", + " return self.delegate.execute(sql, *args)", + " def __getattr__(self, name):", + " return getattr(self.delegate, name)", + "def worker():", + " with workbench.connect() as delegate:", + " connection_ready.set()", + " if not start_worker.wait(5):", + " outcome['error'] = 'worker start timed out'", + " return", + " try:", + " started = workbench.start_prompt_only_scan(TrackedConnection(delegate), arguments())", + " except SystemExit as error:", + " outcome['error'] = str(error)", + " else:", + " outcome['disposition'] = started['startDisposition']", + "thread = threading.Thread(target=worker)", + "thread.start()", + "if not connection_ready.wait(5):", + " raise RuntimeError('worker connection timed out')", + "with workbench.connect() as blocker:", + " blocker.execute('BEGIN IMMEDIATE')", + " start_worker.set()", + " if not begin_attempted.wait(5):", + " raise RuntimeError('scan did not reach writer lock')", + " target = Path(repository)", + " if kind == 'working_tree':", + " (target / 'fixture.txt').write_text('changed behind lock\\n')", + " else:", + " parked = Path(root) / 'parked-repository'", + " target.rename(parked)", + " shutil.copytree(parked, target)", + " blocker.commit()", + "thread.join(10)", + "if thread.is_alive():", + " raise RuntimeError('scan worker did not finish')", + "with workbench.connect() as connection:", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + "print(json.dumps({'beginAttempted': begin_attempted.is_set(), 'counts': counts, 'snapshotCalls': snapshot_calls, **outcome}))", + ], + [action, kind, repository, base, head, root], + state, + ); + + expect(result).toEqual({ + beginAttempted: true, + counts: { + scans: action === "rejoin" ? 1 : 0, + workspaces: action === "rejoin" ? 1 : 0, + }, + disposition: null, + error: + "The selected scan target changed while the scan was starting. Try again.", + snapshotCalls: 2, + }); + }, + ); + + test.each(["commit", "range"] as const)( + "rejoins a legacy active %s scan only when both stored digests are null", + (kind) => { + const { base, head, repository, root, state } = createRepository(); + const result = runPythonJson<{ + disposition: string; + scanCount: number; + scanDigest: string | null; + sameScan: boolean; + workspaceCount: number; + workspaceDigest: string | null; + }>( + [ + "import argparse, json", + "from pathlib import Path", + "import workbench_db as workbench", + "kind, repository, base, head, scan_root = sys.argv[2:7]", + "Path(scan_root).mkdir(mode=0o700)", + "def arguments():", + " return argparse.Namespace(thread_id=f'legacy-{kind}', target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind=kind, diff_base_revision=base, diff_head_revision=head, diff_content_digest=None, scan_root=scan_root, model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " first = workbench.start_prompt_only_scan(connection, arguments())", + " first_scan_id = first['scan']['scanId']", + " workspace_id = connection.execute('SELECT workspace_id FROM scans WHERE id = ?', (first_scan_id,)).fetchone()['workspace_id']", + " connection.execute('UPDATE workspaces SET diff_content_digest = NULL WHERE id = ?', (workspace_id,))", + " connection.execute('UPDATE scans SET diff_content_digest = NULL WHERE id = ?', (first_scan_id,))", + " connection.commit()", + " joined = workbench.start_prompt_only_scan(connection, arguments())", + " row = connection.execute('SELECT workspaces.diff_content_digest AS workspace_digest, scans.diff_content_digest AS scan_digest FROM scans JOIN workspaces ON workspaces.id = scans.workspace_id WHERE scans.id = ?', (first_scan_id,)).fetchone()", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + "print(json.dumps({'disposition': joined['startDisposition'], 'sameScan': joined['scan']['scanId'] == first_scan_id, 'workspaceDigest': row['workspace_digest'], 'scanDigest': row['scan_digest'], 'workspaceCount': counts['workspaces'], 'scanCount': counts['scans']}))", + ], + [kind, repository, base, head, join(root, "legacy-scans")], + state, + ); + + expect(result).toEqual({ + disposition: "joined", + sameScan: true, + workspaceDigest: null, + scanDigest: null, + workspaceCount: 1, + scanCount: 1, + }); + }, + ); + + test.each(["commit", "range"] as const)( + "does not rejoin a legacy active %s scan with an explicit digest", + (kind) => { + const { base, head, repository, root, state } = createRepository(); + const selectedDigest = committedDigest(repository, state, base, head); + const result = runPythonJson<{ + createdScanDigest: string | null; + createdWorkspaceDigest: string | null; + disposition: string; + legacyScanDigest: string | null; + legacyWorkspaceDigest: string | null; + sameScan: boolean; + scanCount: number; + workspaceCount: number; + }>( + [ + "import argparse, json", + "from pathlib import Path", + "import workbench_db as workbench", + "kind, repository, base, head, selected_digest, scan_root = sys.argv[2:8]", + "Path(scan_root).mkdir(mode=0o700)", + "def arguments(content_digest):", + " return argparse.Namespace(thread_id=f'explicit-legacy-{kind}', target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind=kind, diff_base_revision=base, diff_head_revision=head, diff_content_digest=content_digest, scan_root=scan_root, model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " legacy = workbench.start_prompt_only_scan(connection, arguments(None))", + " legacy_scan_id = legacy['scan']['scanId']", + " legacy_workspace_id = connection.execute('SELECT workspace_id FROM scans WHERE id = ?', (legacy_scan_id,)).fetchone()['workspace_id']", + " connection.execute('UPDATE workspaces SET diff_content_digest = NULL WHERE id = ?', (legacy_workspace_id,))", + " connection.execute('UPDATE scans SET diff_content_digest = NULL WHERE id = ?', (legacy_scan_id,))", + " connection.commit()", + " started = workbench.start_prompt_only_scan(connection, arguments(selected_digest))", + " created_scan_id = started['scan']['scanId']", + " created = connection.execute('SELECT workspaces.diff_content_digest AS workspace_digest, scans.diff_content_digest AS scan_digest FROM scans JOIN workspaces ON workspaces.id = scans.workspace_id WHERE scans.id = ?', (created_scan_id,)).fetchone()", + " legacy_row = connection.execute('SELECT workspaces.diff_content_digest AS workspace_digest, scans.diff_content_digest AS scan_digest FROM scans JOIN workspaces ON workspaces.id = scans.workspace_id WHERE scans.id = ?', (legacy_scan_id,)).fetchone()", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + "print(json.dumps({'disposition': started['startDisposition'], 'sameScan': created_scan_id == legacy_scan_id, 'createdWorkspaceDigest': created['workspace_digest'], 'createdScanDigest': created['scan_digest'], 'legacyWorkspaceDigest': legacy_row['workspace_digest'], 'legacyScanDigest': legacy_row['scan_digest'], 'workspaceCount': counts['workspaces'], 'scanCount': counts['scans']}))", + ], + [ + kind, + repository, + base, + head, + selectedDigest, + join(root, "explicit-legacy-scans"), + ], + state, + ); + + expect(result).toEqual({ + disposition: "created", + sameScan: false, + createdWorkspaceDigest: selectedDigest, + createdScanDigest: selectedDigest, + legacyWorkspaceDigest: null, + legacyScanDigest: null, + workspaceCount: 2, + scanCount: 2, + }); + }, + ); + + test("prefers an exact digested active scan over a newer legacy row", () => { + const { base, head, repository, root, state } = createRepository(); + const result = runPythonJson<{ + disposition: string; + exactSelected: boolean; + legacyScanDigest: string | null; + legacyWorkspaceDigest: string | null; + scanCount: number; + workspaceCount: number; + }>( + [ + "import argparse, json", + "from pathlib import Path", + "import workbench_db as workbench", + "repository, base, head, scan_root = sys.argv[2:6]", + "Path(scan_root).mkdir(mode=0o700)", + "thread_id = 'exact-digest-preference'", + "def arguments():", + " return argparse.Namespace(thread_id=thread_id, target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind='range', diff_base_revision=base, diff_head_revision=head, diff_content_digest=None, scan_root=scan_root, model=None, reasoning_effort=None)", + "with workbench.connect() as connection:", + " legacy = workbench.start_prompt_only_scan(connection, arguments())", + " legacy_scan_id = legacy['scan']['scanId']", + " legacy_workspace_id = connection.execute('SELECT workspace_id FROM scans WHERE id = ?', (legacy_scan_id,)).fetchone()['workspace_id']", + " connection.execute('UPDATE workspaces SET thread_id = ?, diff_content_digest = NULL WHERE id = ?', ('temporary-owner', legacy_workspace_id))", + " connection.execute('UPDATE scans SET diff_content_digest = NULL WHERE id = ?', (legacy_scan_id,))", + " connection.commit()", + " exact = workbench.start_prompt_only_scan(connection, arguments())", + " exact_scan_id = exact['scan']['scanId']", + " connection.execute('UPDATE workspaces SET thread_id = ? WHERE id = ?', (thread_id, legacy_workspace_id))", + " connection.execute(\"UPDATE scans SET updated_at = '2099-01-01T00:00:00Z' WHERE id = ?\", (legacy_scan_id,))", + " connection.commit()", + " joined = workbench.start_prompt_only_scan(connection, arguments())", + " legacy_row = connection.execute('SELECT workspaces.diff_content_digest AS workspace_digest, scans.diff_content_digest AS scan_digest FROM scans JOIN workspaces ON workspaces.id = scans.workspace_id WHERE scans.id = ?', (legacy_scan_id,)).fetchone()", + " counts = {table: connection.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] for table in ('workspaces', 'scans')}", + "print(json.dumps({'disposition': joined['startDisposition'], 'exactSelected': joined['scan']['scanId'] == exact_scan_id, 'legacyWorkspaceDigest': legacy_row['workspace_digest'], 'legacyScanDigest': legacy_row['scan_digest'], 'workspaceCount': counts['workspaces'], 'scanCount': counts['scans']}))", + ], + [repository, base, head, join(root, "preference-scans")], + state, + ); + + expect(result).toEqual({ + disposition: "joined", + exactSelected: true, + legacyWorkspaceDigest: null, + legacyScanDigest: null, + workspaceCount: 2, + scanCount: 2, + }); + }); + + test.each(["commit", "range"] as const)( + "hashes outside SQLite once per %s completion phase and warns on finalization drift", + (kind) => { + const { base, head, repository, root, state } = createRepository(); + const selectedBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "completion replacement\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + const result = runPythonJson<{ + completedWarnings: string[]; + completedTargetWarnings: string[]; + genericWarning: string; + phaseBatchCounts: number[]; + transactions: boolean[]; + preparedTargetWarnings: string[]; + }>( + [ + "import argparse, json, os, shutil, subprocess", + "from pathlib import Path", + "import workbench_db as workbench", + "import workbench_target as target", + "kind, repository, base, head, scan_root, plugin_root, selected_blob, replacement_blob = sys.argv[2:10]", + "Path(scan_root).mkdir(mode=0o700)", + "start_args = argparse.Namespace(thread_id=f'completion-{kind}', target_path=repository, scope='.', mode='diff', target_summary=None, user_context=None, user_context_stdin=False, diff_target_kind=kind, diff_base_revision=base, diff_head_revision=head, diff_content_digest=None, scan_root=scan_root, model=None, reasoning_effort=None)", + "completion_args = argparse.Namespace(scan_id=None, claim_token=None, cost_json=None, thread_id=None)", + "with workbench.connect() as connection:", + " started = workbench.start_prompt_only_scan(connection, start_args)", + " scan_id = started['scan']['scanId']", + " completion_args.scan_id = scan_id", + " scan = workbench.require_scan(connection, scan_id)", + " scan_dir = Path(scan['scan_dir'])", + " shutil.copytree(Path(plugin_root) / 'examples' / 'completed-scan', scan_dir, dirs_exist_ok=True)", + " if os.name != 'nt':", + " scan_dir.parent.chmod(0o700)", + " scan_dir.chmod(0o700)", + " manifest_path = scan_dir / 'scan-manifest.json'", + " manifest = json.loads(manifest_path.read_text())", + " manifest['scan']['id'] = scan_id", + " manifest['scan']['target']['kind'] = 'git_diff'", + " manifest['scan'].pop('sealedAt', None)", + " manifest['scan'].pop('artifacts', None)", + " manifest_path.write_text(json.dumps(manifest))", + " for name in ('findings.json', 'coverage.json'):", + " path = scan_dir / name", + " document = json.loads(path.read_text())", + " document['scanId'] = scan_id", + " if name == 'coverage.json': document['inventoryStrategy'] = 'diff'", + " path.write_text(json.dumps(document))", + " original_digest = target.committed_diff_content_digest", + " def unavailable(*args): raise SystemExit('synthetic failure')", + " target.committed_diff_content_digest = unavailable", + " generic_warning = workbench.scan_target_warning(scan)", + " target.committed_diff_content_digest = original_digest", + " original_git = target.git_command", + " transactions = []", + " def tracked_git_command(path, *args, **kwargs):", + " if args[:2] == ('cat-file', '--batch'): transactions.append(connection.in_transaction)", + " return original_git(path, *args, **kwargs)", + " target.git_command = tracked_git_command", + " original_prepare = workbench._prepare_scan_finalization", + " def prepare_then_replace(*args, **kwargs):", + " prepared = original_prepare(*args, **kwargs)", + " subprocess.run(['git', '-C', repository, 'replace', '-f', selected_blob, replacement_blob], check=True, stdout=subprocess.DEVNULL)", + " return prepared", + " workbench._prepare_scan_finalization = prepare_then_replace", + " prepared = workbench.complete_scan(connection, completion_args, prepare_only=True)", + " phase_batch_counts = [len(transactions)]", + " prepared_completed_at = json.loads(manifest_path.read_text())['scan']['completedAt']", + " subprocess.run(['git', '-C', repository, 'replace', '-d', selected_blob], check=True, stdout=subprocess.DEVNULL)", + " workbench._prepare_scan_finalization = original_prepare", + " workbench.now = lambda: prepared_completed_at", + " completed = workbench.complete_scan(connection, completion_args, prepare_only=False)", + " phase_batch_counts.append(len(transactions) - phase_batch_counts[0])", + "print(json.dumps({'genericWarning': generic_warning, 'preparedTargetWarnings': prepared['targetWarnings'], 'completedTargetWarnings': completed['targetWarnings'], 'completedWarnings': completed['scan']['warnings'], 'phaseBatchCounts': phase_batch_counts, 'transactions': transactions}))", + ], + [ + kind, + repository, + base, + head, + join(root, "completion-scans"), + PLUGIN_ROOT, + selectedBlob, + replacement.stdout.trim(), + ], + state, + ); + const driftWarning = + "Committed changes changed while the scan was running; results were saved for the original snapshot."; + + expect(result).toEqual({ + genericWarning: + "The scan target became unavailable while the scan was running; results were saved for the original revision or snapshot.", + preparedTargetWarnings: [driftWarning], + completedTargetWarnings: [], + completedWarnings: expect.arrayContaining([driftWarning]), + phaseBatchCounts: [1, 1], + transactions: [false, false], + }); + }, + ); + + test("selects root commits in SHA-1 and supported SHA-256 repositories", () => { + expect(python).not.toBeNull(); + const { root, state } = createRepository(); + const emptyTrees = { + sha1: "4b825dc642cb6eb9a060e54bf8d69288fbee4904", + sha256: + "6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321", + }; + + for (const objectFormat of ["sha1", "sha256"] as const) { + const repository = join(root, `root-${objectFormat}`); + const initialized = spawnSync( + "git", + ["init", "--quiet", `--object-format=${objectFormat}`, repository], + { encoding: "utf8" }, + ); + if (objectFormat === "sha256" && initialized.status !== 0) continue; + expect(initialized.status, initialized.stderr).toBe(0); + writeFileSync(join(repository, "source.txt"), "root fixture\n"); + git(repository, "add", "source.txt"); + commit(repository, "root"); + const head = git(repository, "rev-parse", "HEAD"); + const diffTarget = runPythonJson<{ + baseRevision: string; + contentDigest: string; + headRevision: string; + kind: string; + }>( + [ + "import json", + "from workbench_db import inspect_setup_values", + "result = inspect_setup_values(sys.argv[2], '.', 'diff', 'commit', sys.argv[3], sys.argv[4], None)", + "print(json.dumps(result['diffTarget']))", + ], + [repository, emptyTrees[objectFormat], head], + state, + ); + + expect(diffTarget).toEqual({ + kind: "commit", + baseRevision: emptyTrees[objectFormat], + headRevision: head, + contentDigest: expect.stringMatching( + /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, + ), + }); + } + }); +}); diff --git a/sdk/typescript/tests-ts/prompt-only-start-timeout.test.ts b/sdk/typescript/tests-ts/prompt-only-start-timeout.test.ts index 324fd9635..351019ab8 100644 --- a/sdk/typescript/tests-ts/prompt-only-start-timeout.test.ts +++ b/sdk/typescript/tests-ts/prompt-only-start-timeout.test.ts @@ -1,7 +1,7 @@ import { expect, test } from "bun:test"; import { loadBundledRuntime, PLUGIN_ROOT } from "./plugin-root.js"; -test("gives prompt-only scan startup the five-minute scan timeout", async () => { +test("gives long workbench operations the five-minute timeout", async () => { const runtime = await loadBundledRuntime(); const source = /async function executeWorkbench\([^\n]*\) \{[\s\S]*?\n\}/u.exec( @@ -34,7 +34,176 @@ test("gives prompt-only scan startup the five-minute scan timeout", async () => expect(await executeWorkbench("python", ["start-scan"])).toEqual({ timeout: 300_000, }); + expect(await executeWorkbench("python", ["create-workspace"])).toEqual({ + timeout: 300_000, + }); + expect(await executeWorkbench("python", ["prepare-scan-completion"])).toEqual( + { timeout: 300_000 }, + ); expect(await executeWorkbench("python", ["other-operation"])).toEqual({ timeout: 30_000, }); }); + +test("state-free inspection reuses but does not create a fallback", async () => { + const runtime = await loadBundledRuntime(); + const source = + /async function executeWorkbenchWithStateSelection\([^\n]*\) \{[\s\S]*?\n\}/u.exec( + runtime, + )?.[0]; + expect(source).toBeDefined(); + + function selector(fallback: Promise | undefined) { + let pinCalls = 0; + const executeWorkbenchWithStateSelection = new Function( + "WORKBENCH_COMMANDS_WITHOUT_DATABASE", + "CONFIGURED_WORKBENCH_STATE_DIR", + "fallbackWorkbenchStateDir", + "persistentWorkbenchStateSucceeded", + "withWorkbenchStateSelectionLock", + "executeWorkbench", + "isUnwritableSqliteOpenError", + "pinFallbackWorkbenchStateDir", + "logWorkbenchStateFallback", + `${source}\nreturn executeWorkbenchWithStateSelection;`, + )( + new Set(["inspect-target", "inspect-setup"]), + undefined, + fallback, + false, + async (operation: () => Promise) => await operation(), + async (_command: string, _args: string[], stateDir?: string) => ({ + stateDir, + }), + () => false, + async () => { + pinCalls += 1; + return "/new-fallback"; + }, + () => undefined, + ) as (command: string, args: string[]) => Promise<{ stateDir?: string }>; + return { executeWorkbenchWithStateSelection, pinCalls: () => pinCalls }; + } + + const withoutFallback = selector(undefined); + expect( + await withoutFallback.executeWorkbenchWithStateSelection("python", [ + "inspect-setup", + ]), + ).toEqual({ stateDir: undefined }); + expect(withoutFallback.pinCalls()).toBe(0); + + const withFallback = selector(Promise.resolve("/pinned-fallback")); + expect( + await withFallback.executeWorkbenchWithStateSelection("python", [ + "inspect-setup", + ]), + ).toEqual({ stateDir: "/pinned-fallback" }); + expect(withFallback.pinCalls()).toBe(0); +}); + +test("a rejected pending fallback pin does not fail state-free inspection", async () => { + const runtime = await loadBundledRuntime(); + const pinSource = + /async function pinFallbackWorkbenchStateDir\(\) \{[\s\S]*?\n\}/u.exec( + runtime, + )?.[0]; + const selectionSource = + /async function executeWorkbenchWithStateSelection\([^\n]*\) \{[\s\S]*?\n\}/u.exec( + runtime, + )?.[0]; + expect(pinSource).toBeDefined(); + expect(selectionSource).toBeDefined(); + const pathModule = /\b(import_node_path\d+)\.join\b/u.exec( + pinSource ?? "", + )?.[1]; + const fsModule = /\b(import_node_fs\d+)\.promises\b/u.exec( + pinSource ?? "", + )?.[1]; + expect(pathModule).toBeDefined(); + expect(fsModule).toBeDefined(); + + let mkdirCalls = 0; + let rejectFirstMkdir: ((reason: Error) => void) | undefined; + let resolveMkdirStarted: (() => void) | undefined; + const firstMkdir = new Promise((_resolve, reject) => { + rejectFirstMkdir = reject; + }); + const mkdirStarted = new Promise((resolve) => { + resolveMkdirStarted = resolve; + }); + const bundled = new Function( + pathModule!, + fsModule!, + "scanRoot", + "WORKBENCH_COMMANDS_WITHOUT_DATABASE", + "CONFIGURED_WORKBENCH_STATE_DIR", + "fallbackWorkbenchStateDir", + "persistentWorkbenchStateSucceeded", + "withWorkbenchStateSelectionLock", + "executeWorkbench", + "isUnwritableSqliteOpenError", + "logWorkbenchStateFallback", + `${pinSource}\n${selectionSource}\nreturn { pinFallbackWorkbenchStateDir, executeWorkbenchWithStateSelection };`, + )( + { join: (left: string, right: string) => `${left}/${right}` }, + { + promises: { + mkdir: async () => { + mkdirCalls += 1; + if (mkdirCalls === 1) { + resolveMkdirStarted!(); + await firstMkdir; + } + }, + }, + }, + async () => "/fallback", + new Set(["inspect-target", "inspect-setup"]), + undefined, + undefined, + false, + async (operation: () => Promise) => await operation(), + async (_command: string, _args: string[], stateDir?: string) => ({ + stateDir, + }), + () => false, + () => undefined, + ) as { + executeWorkbenchWithStateSelection: ( + command: string, + args: string[], + ) => Promise<{ stateDir?: string }>; + pinFallbackWorkbenchStateDir: () => Promise; + }; + + const pin = bundled.pinFallbackWorkbenchStateDir(); + await mkdirStarted; + const inspection = bundled.executeWorkbenchWithStateSelection("python", [ + "inspect-setup", + ]); + const outcomes = Promise.allSettled([pin, inspection]); + rejectFirstMkdir!(new Error("synthetic fallback failure")); + const [pinOutcome, inspectionOutcome] = await outcomes; + expect(pinOutcome).toMatchObject({ + status: "rejected", + reason: expect.objectContaining({ + message: "synthetic fallback failure", + }), + }); + expect(inspectionOutcome).toEqual({ + status: "fulfilled", + value: { stateDir: undefined }, + }); + expect(mkdirCalls).toBe(1); + + await expect(bundled.pinFallbackWorkbenchStateDir()).resolves.toBe( + "/fallback/workbench-state", + ); + expect(mkdirCalls).toBe(2); + expect( + await bundled.executeWorkbenchWithStateSelection("python", [ + "inspect-setup", + ]), + ).toEqual({ stateDir: "/fallback/workbench-state" }); +}); From 287cdfcca4e578620a93e904476be0a139bc1cd1 Mon Sep 17 00:00:00 2001 From: mldangelo-oai <269034524+mldangelo-oai@users.noreply.github.com> Date: Mon, 24 Aug 2026 00:56:51 +0000 Subject: [PATCH 2/5] fix(plugin): preserve packed replacement refs --- .../scripts/workbench_target.py | 15 ++- .../git-batch-object-validation.test.ts | 106 ++++++++++++++++++ 2 files changed, 115 insertions(+), 6 deletions(-) diff --git a/sdk/typescript/_bundled_plugin/scripts/workbench_target.py b/sdk/typescript/_bundled_plugin/scripts/workbench_target.py index 9968991ee..f7a96f56c 100644 --- a/sdk/typescript/_bundled_plugin/scripts/workbench_target.py +++ b/sdk/typescript/_bundled_plugin/scripts/workbench_target.py @@ -386,7 +386,7 @@ def _create_committed_diff_view(repository: Path, view: Path) -> Path: object_id_length=object_id_length, ) replacements_enabled = _replacement_refs_enabled(repository) - parsed_replacements: list[tuple[list[str], bytes]] = [] + parsed_replacements: list[tuple[bytes, bytes]] = [] for record in replacements.splitlines(): fields = record.split(b"\0") if ( @@ -404,7 +404,7 @@ def _create_committed_diff_view(repository: Path, view: Path) -> Path: or any(part in {"", ".", ".."} for part in parts) ): raise SystemExit("Could not snapshot the selected committed changes.") - parsed_replacements.append((parts, fields[1])) + parsed_replacements.append((fields[0], fields[1])) try: view.mkdir(mode=0o700) @@ -426,10 +426,13 @@ def _create_committed_diff_view(repository: Path, view: Path) -> Path: ) (view / "config").write_bytes(config) (view / "HEAD").write_bytes(b"ref: refs/heads/codex-security-snapshot\n") - for parts, object_id in parsed_replacements: - ref = view.joinpath(*parts) - ref.parent.mkdir(parents=True, exist_ok=True) - ref.write_bytes(object_id + b"\n") + packed_refs = bytearray(b"# pack-refs with: sorted\n") + for refname, object_id in parsed_replacements: + packed_refs.extend(object_id) + packed_refs.extend(b" ") + packed_refs.extend(refname) + packed_refs.extend(b"\n") + (view / "packed-refs").write_bytes(packed_refs) except OSError as exc: raise SystemExit("Could not snapshot the selected committed changes.") from exc return object_directory diff --git a/sdk/typescript/tests-ts/git-batch-object-validation.test.ts b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts index ce7a66daa..919b59386 100644 --- a/sdk/typescript/tests-ts/git-batch-object-validation.test.ts +++ b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts @@ -768,6 +768,112 @@ describe("committed diff Git batch validation", () => { } }); + test("freezes packed replacement refs without Windows-reserved loose paths", () => { + const { root, state } = createRepository(); + const replacementRefBase = "refs/replace/AUX/"; + const environment = { GIT_REPLACE_REF_BASE: replacementRefBase }; + + for (const objectFormat of ["sha1", "sha256"] as const) { + const repository = join(root, `packed-replacement-${objectFormat}`); + const initialized = spawnSync( + "git", + ["init", "--quiet", `--object-format=${objectFormat}`, repository], + { encoding: "utf8" }, + ); + if (objectFormat === "sha256" && initialized.status !== 0) continue; + expect(initialized.status, initialized.stderr).toBe(0); + writeFileSync(join(repository, "fixture.txt"), "base\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "base"); + const base = git(repository, "rev-parse", "HEAD"); + writeFileSync(join(repository, "fixture.txt"), "head\n"); + git(repository, "add", "fixture.txt"); + commit(repository, "head"); + const head = git(repository, "rev-parse", "HEAD"); + const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const originalDigest = committedDigest( + repository, + state, + base, + head, + environment, + ); + const replacement = spawnSync( + "git", + ["-C", repository, "hash-object", "-w", "--stdin"], + { encoding: "utf8", input: "packed replacement\n" }, + ); + expect(replacement.status, replacement.stderr).toBe(0); + const replacementBlob = replacement.stdout.trim(); + const replacementRef = `${replacementRefBase}${originalBlob}`; + const gitDirectory = git(repository, "rev-parse", "--absolute-git-dir"); + const packedRefs = join(gitDirectory, "packed-refs"); + expect(existsSync(packedRefs)).toBeFalse(); + writeFileSync( + packedRefs, + `# pack-refs with: sorted\n${replacementBlob} ${replacementRef}\n`, + ); + expect( + existsSync(join(gitDirectory, ...replacementRef.split("/"))), + ).toBeFalse(); + expect(readFileSync(packedRefs, "utf8")).toContain( + `${replacementBlob} ${replacementRef}\n`, + ); + + const selected = spawnSync( + "git", + ["-C", repository, "cat-file", "blob", originalBlob], + { + encoding: "utf8", + env: { ...process.env, ...environment }, + }, + ); + expect(selected.status, selected.stderr).toBe(0); + expect(selected.stdout).toBe("packed replacement\n"); + const expectedDigest = committedDigest( + repository, + state, + base, + head, + environment, + ); + expect(expectedDigest).not.toBe(originalDigest); + + const result = runPythonJson<{ digest: string }>( + [ + "import json", + "from pathlib import Path", + "import workbench_target as target", + "reserved = {'CON', 'PRN', 'AUX', 'NUL', *(f'COM{i}' for i in range(1, 10)), *(f'LPT{i}' for i in range(1, 10))}", + "original_mkdir = Path.mkdir", + "original_write_bytes = Path.write_bytes", + "def reject_reserved(path):", + " for part in path.parts:", + " if part.rstrip(' .').split('.', 1)[0].upper() in reserved:", + " raise OSError('synthetic Windows-reserved path')", + "def windows_mkdir(path, *args, **kwargs):", + " reject_reserved(path)", + " return original_mkdir(path, *args, **kwargs)", + "def windows_write_bytes(path, data):", + " reject_reserved(path)", + " return original_write_bytes(path, data)", + "Path.mkdir = windows_mkdir", + "Path.write_bytes = windows_write_bytes", + "try:", + " digest = target.committed_diff_content_digest(Path(sys.argv[2]), sys.argv[3], sys.argv[4])", + "finally:", + " Path.mkdir = original_mkdir", + " Path.write_bytes = original_write_bytes", + "print(json.dumps({'digest': digest}))", + ], + [repository, base, head], + state, + environment, + ); + expect(result.digest).toBe(expectedDigest); + } + }); + test.each([ ["a repository-local disable", false, false], ["a repository-local enable over a global disable", true, true], From 0a841a6d038bd59fb8738713f452d959ab429994 Mon Sep 17 00:00:00 2001 From: mldangelo-oai <269034524+mldangelo-oai@users.noreply.github.com> Date: Mon, 24 Aug 2026 01:47:33 +0000 Subject: [PATCH 3/5] fix(plugin): open frozen Git views explicitly --- .../scripts/workbench_target.py | 25 ++++++++++++++++--- .../git-batch-object-validation.test.ts | 13 ++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/sdk/typescript/_bundled_plugin/scripts/workbench_target.py b/sdk/typescript/_bundled_plugin/scripts/workbench_target.py index f7a96f56c..e198d463c 100644 --- a/sdk/typescript/_bundled_plugin/scripts/workbench_target.py +++ b/sdk/typescript/_bundled_plugin/scripts/workbench_target.py @@ -221,8 +221,8 @@ def git_command( local_objects_only: bool = False, object_directory: Path | None = None, ) -> subprocess.CompletedProcess[str] | subprocess.CompletedProcess[bytes]: - if (git_dir is None) != (work_tree is None): - raise ValueError("git_dir and work_tree must be provided together") + if work_tree is not None and git_dir is None: + raise ValueError("work_tree requires git_dir") environment = os.environ.copy() for name in GIT_REPOSITORY_ENVIRONMENT: environment.pop(name, None) @@ -242,8 +242,10 @@ def git_command( "-C", str(target), ] - if git_dir is not None and work_tree is not None: - command.extend(["--git-dir", str(git_dir), "--work-tree", str(work_tree)]) + if git_dir is not None: + command.extend(["--git-dir", str(git_dir)]) + if work_tree is not None: + command.extend(["--work-tree", str(work_tree)]) full_command = [*command, *args] try: return subprocess.run( @@ -297,6 +299,7 @@ def _replacement_refs( repository: Path, *, object_id_length: int, + git_dir: Path | None = None, object_directory: Path | None = None, ) -> bytes: replacement_ref_base = os.fsencode( @@ -309,6 +312,7 @@ def _replacement_refs( "--format=%(refname)%00%(objectname)", text=False, local_objects_only=True, + git_dir=git_dir, object_directory=object_directory, ) if replacements.returncode != 0: @@ -337,6 +341,7 @@ def _replacement_refs( def _replacement_refs_enabled( repository: Path, *, + git_dir: Path | None = None, object_directory: Path | None = None, ) -> bool: if "GIT_NO_REPLACE_OBJECTS" in os.environ: @@ -349,6 +354,7 @@ def _replacement_refs_enabled( "core.useReplaceRefs", text=False, local_objects_only=True, + git_dir=git_dir, object_directory=object_directory, ) value = configured.stdout.strip() @@ -481,6 +487,7 @@ def _committed_diff_object_identity( base: str, head: str, *, + git_dir: Path | None = None, object_directory: Path | None = None, ) -> str: digest = hashlib.sha256() @@ -501,6 +508,7 @@ def _committed_diff_object_identity( "--end-of-options", f"{revision}^{{tree}}", local_objects_only=True, + git_dir=git_dir, object_directory=object_directory, ) if tree is None: @@ -514,17 +522,20 @@ def _committed_diff_object_identity( "rev-parse", "--show-object-format", local_objects_only=True, + git_dir=git_dir, object_directory=object_directory, ) if object_format not in {"sha1", "sha256"}: raise SystemExit("Could not inspect the selected committed changes.") replacements_enabled = _replacement_refs_enabled( repository, + git_dir=git_dir, object_directory=object_directory, ) replacements = _replacement_refs( repository, object_id_length=40 if object_format == "sha1" else 64, + git_dir=git_dir, object_directory=object_directory, ) update_digest_field( @@ -566,6 +577,7 @@ def _committed_diff_content_snapshot( pathspec, base, head, + git_dir=view, object_directory=object_directory, ) content_digest = _committed_diff_content_digest( @@ -574,6 +586,7 @@ def _committed_diff_content_snapshot( base, head, operation_directory, + git_dir=view, object_directory=object_directory, ) after = _committed_diff_object_identity( @@ -581,6 +594,7 @@ def _committed_diff_content_snapshot( pathspec, base, head, + git_dir=view, object_directory=object_directory, ) if before != after: @@ -595,6 +609,7 @@ def _committed_diff_content_digest( head: str, state_directory: Path, *, + git_dir: Path | None = None, object_directory: Path | None = None, ) -> str: digest = hashlib.sha256() @@ -625,6 +640,7 @@ def _committed_diff_content_digest( text=False, stdout=metadata, local_objects_only=True, + git_dir=git_dir, object_directory=object_directory, ) if diff.returncode != 0: @@ -648,6 +664,7 @@ def _committed_diff_content_digest( stdin=requests, stdout=objects, local_objects_only=True, + git_dir=git_dir, object_directory=object_directory, ) if batch.returncode != 0: diff --git a/sdk/typescript/tests-ts/git-batch-object-validation.test.ts b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts index 919b59386..3f6c4d47a 100644 --- a/sdk/typescript/tests-ts/git-batch-object-validation.test.ts +++ b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts @@ -911,6 +911,19 @@ describe("committed diff Git batch validation", () => { }, ); + test("opens frozen committed views explicitly", () => { + const { base, head, repository, root, state } = createRepository(); + const globalConfig = join(root, "global.gitconfig"); + writeFileSync(globalConfig, "[safe]\n\tbareRepository = explicit\n"); + + expect( + committedDigest(repository, state, base, head, { + GIT_CONFIG_GLOBAL: globalConfig, + GIT_CONFIG_NOSYSTEM: "1", + }), + ).toMatch(/^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u); + }); + test.skipIf(process.platform === "win32")( "supports line-break-bearing quoted repository paths", () => { From 4e478501a9283fa0aed4e1e99ab55db00529d134 Mon Sep 17 00:00:00 2001 From: mldangelo-oai <269034524+mldangelo-oai@users.noreply.github.com> Date: Mon, 24 Aug 2026 03:11:08 +0000 Subject: [PATCH 4/5] test(plugin): make Git fixtures portable --- .../git-batch-object-validation.test.ts | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/sdk/typescript/tests-ts/git-batch-object-validation.test.ts b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts index 3f6c4d47a..d5a07dd4d 100644 --- a/sdk/typescript/tests-ts/git-batch-object-validation.test.ts +++ b/sdk/typescript/tests-ts/git-batch-object-validation.test.ts @@ -341,16 +341,32 @@ describe("committed diff Git batch validation", () => { { encoding: "utf8", input: payload }, ); expect(hashed.status, hashed.stderr).toBe(0); - git( - repository, - "update-index", - "--add", - "--cacheinfo", - `100644,${hashed.stdout.trim()},${path}`, + const tree = spawnSync( + "git", + ["-C", repository, "hash-object", "-t", "tree", "-w", "--stdin"], + { + encoding: "utf8", + input: Buffer.concat([ + Buffer.from(`100644 ${path}\0`), + Buffer.from(hashed.stdout.trim(), "hex"), + ]), + }, ); + expect(tree.status, tree.stderr).toBe(0); expect(existsSync(join(repository, path))).toBe(false); - commit(repository, "binary path"); - const revision = git(repository, "rev-parse", "HEAD"); + const revision = git( + repository, + "-c", + "user.name=synthetic-test", + "-c", + "user.email=synthetic-test@example.invalid", + "commit-tree", + tree.stdout.trim(), + "-p", + head, + "-m", + "binary path", + ); const result = runPythonJson<{ blobs: Array; empty: unknown[]; @@ -668,6 +684,22 @@ describe("committed diff Git batch validation", () => { commit(repository, "head"); const head = git(repository, "rev-parse", "HEAD"); const originalBlob = git(repository, "rev-parse", `${head}:fixture.txt`); + const rawPrefixProbe = spawnSync( + "git", + ["-C", repository, "cat-file", "blob", originalBlob], + { + encoding: "utf8", + env: { ...process.env, ...environment }, + }, + ); + if (rawPrefixProbe.status !== 0) { + expect(rawPrefixProbe.stdout).toBe(""); + expect(rawPrefixProbe.stderr).toMatch( + /BUG: refs\.c:\d+: ref pattern must end in a trailing slash when trimming/u, + ); + continue; + } + expect(rawPrefixProbe.stdout).toBe("head\n"); const before = [ committedDigest(repository, state, base, head, environment), committedObjectIdentity(repository, base, head, environment), @@ -2512,12 +2544,14 @@ describe("committed diff Git batch validation", () => { expect(result).toMatchObject({ allConfined: true, - privateMode: true, residue: [], rootRemoved: true, roots: 1, spools: 3, }); + if (process.platform !== "win32") { + expect(result.privateMode).toBeTrue(); + } expect(result.digest).toMatch( /^codex-security-snapshot\/v1:sha256:[a-f0-9]{64}$/u, ); From f5ca13647d427b1e4230674978c59dba2d79cf76 Mon Sep 17 00:00:00 2001 From: Michael D'Angelo Date: Mon, 24 Aug 2026 14:56:30 -0700 Subject: [PATCH 5/5] fix(plugin): assign a unique committed-diff cache version --- sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json | 2 +- sdk/typescript/src/version.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json b/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json index 93934fc55..d4447d0bb 100644 --- a/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json +++ b/sdk/typescript/_bundled_plugin/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "codex-security", - "version": "0.1.23", + "version": "0.1.43", "description": "Codex Security workflows for security scans, analysis, and investigation.", "author": { "name": "OpenAI" diff --git a/sdk/typescript/src/version.ts b/sdk/typescript/src/version.ts index a6165b5ac..ac5adba9f 100644 --- a/sdk/typescript/src/version.ts +++ b/sdk/typescript/src/version.ts @@ -9,7 +9,7 @@ const PACKAGE_VERSIONS = packageVersions( export const VERSION = PACKAGE_VERSIONS.package; export const CODEX_SDK_VERSION = PACKAGE_VERSIONS.sdk; export const CODEX_EXECUTABLE_VERSION = PACKAGE_VERSIONS.executable; -export const BUNDLED_PLUGIN_VERSION = "0.1.23" as const; +export const BUNDLED_PLUGIN_VERSION = "0.1.43" as const; const PACKAGE_NAME = "@openai/codex-security";