the-custodian/docs/changes/netkingdom-target-2026-10-16/scanner-batch-r1/probe_configured_hooks.py
codex 7a3632ffcc
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Reject generated-only commits / generated-commit-guard (push) Successful in 11s
docs: preserve netkingdom-target-2026-10-16 session evidence (batch 6)
2026-11-01 22:16:29 +01:00

204 lines
10 KiB
Python

#!/usr/bin/env python3
"""Reviewed-fixture-only probes of two actual hooks; never opens a real index.
No hook/scanner/source/config or Git commit/ref mutation, network/provider calls,
real credential reads, or unavailable-scanner injection. The only persistent
write is the requested fixed-metadata receipt in this review packet.
"""
from __future__ import annotations
import functools
import hashlib
import json
import os
from pathlib import Path
import signal
import stat
import subprocess
import sys
import types
SOURCE = Path('/home/worsch/repo-manager/src/repo_manager/secret_scan.py')
SOURCE_SHA = 'e709c658f779534fcab093207b0a78e49d54fc584c515fdf7ac535ce75f6c400'
BINARY = Path('/home/worsch/.local/lib/repo-manager/gitleaks/8.30.1/gitleaks')
BINARY_SHA = '88f91962aa2f93ac6ab281d553b9e125f5197bbbce38f9f2437f7299c32e5509'
HOOK_SHA = 'd50cf763dc9814383c6886e30b6650bbbdcb49ddd78889082e3fda3626a2cbfd'
ROOTS = (
(Path('/home/worsch/repo-manager'), Path('/home/worsch/repo-manager/.githooks/pre-commit')),
(Path('/home/worsch/the-custodian'), Path('/home/worsch/the-custodian/.git/hooks/pre-commit')),
)
HERE = Path(__file__).resolve().parent
class Refused(Exception):
pass
def digest(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def info(path):
try:
item = path.lstat()
except FileNotFoundError:
return None
return (item.st_dev, item.st_ino, item.st_size, item.st_mtime_ns, item.st_mode)
def fixed_env():
return {'PATH': '/usr/bin:/bin', 'HOME': '/home/worsch', 'LANG': 'C',
'GIT_CONFIG_NOSYSTEM': '1', 'GIT_NO_REPLACE_OBJECTS': '1'}
def run(argv, root, env, *, data=None, adapter=None):
kwargs = {}
if adapter is not None:
kwargs['preexec_fn'] = functools.partial(adapter.child_limits, 16 * 1024**2, os.getpid())
result = subprocess.run(argv, cwd=root, env=env, input=data, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, timeout=20, check=False, **kwargs)
if result.returncode:
raise Refused('fixture-command-failed')
return result.stdout
def git(root, env, *args, data=None, adapter=None):
return run(['/usr/bin/git', '-C', str(root), *args], root, env, data=data, adapter=adapter)
def precheck():
if digest(SOURCE) != SOURCE_SHA or digest(BINARY) != BINARY_SHA:
raise Refused('source-or-scanner-drift')
binary_info = BINARY.lstat()
if (not stat.S_ISREG(binary_info.st_mode) or binary_info.st_mode & 0o022
or not binary_info.st_mode & 0o111 or binary_info.st_uid not in (0, os.getuid())):
raise Refused('scanner-mode-refused')
records = []
for root, hook in ROOTS:
env = fixed_env()
raw = git(root, env, 'rev-parse', '--git-path', 'hooks/pre-commit').decode().strip()
routed = Path(raw)
if not routed.is_absolute():
routed = root / routed
if routed.resolve() != hook.resolve() or digest(hook) != HOOK_SHA:
raise Refused('hook-routing-drift')
raw_index = git(root, env, 'rev-parse', '--git-path', 'index').decode().strip()
index = Path(raw_index)
if not index.is_absolute():
index = root / index
objects = git(root, env, 'rev-parse', '--git-path', 'objects').decode().strip()
if not Path(objects).is_absolute():
objects = str(root / objects)
records.append({'root': root, 'hook': hook, 'index': index,
'index_stat': info(index), 'head': git(root, env, 'rev-parse', 'HEAD').strip(),
'objects': objects})
return records
def main():
receipt = {'status': 'unverified', 'scope': 'actual configured shared and Custodian hooks; generated alternate-index fixtures only',
'source_sha256': SOURCE_SHA, 'scanner_sha256': BINARY_SHA, 'hook_sha256': HOOK_SHA,
'provider_calls': 0, 'real_credentials_read': False, 'real_index_opened': False,
'actual_hook_unavailable_scanner': 'pending; no host scanner mutation performed'}
fixture = None
observations = []
try:
records = precheck()
# Execute only the hash-bound module bytes already reviewed. This module
# provides the reviewed tmpfs/watchdog/child-death lifecycle primitives.
source_bytes = SOURCE.read_bytes()
if hashlib.sha256(source_bytes).hexdigest() != SOURCE_SHA:
raise Refused('source-drift')
adapter = types.ModuleType('reviewed_scanner_probe_storage')
exec(compile(source_bytes, str(SOURCE), 'exec'), adapter.__dict__)
prior_storage = set(Path('/dev/shm').glob('rmgr-secret-scan-*'))
with adapter.private_storage() as (fixture, watcher):
env = fixed_env()
env['GIT_CONFIG_GLOBAL'] = '/dev/null'
# Temporary-index reads must not invoke a configured fsmonitor or
# create split-index auxiliaries in the real repository directory.
overrides = [('core.fsmonitor', 'false'), ('core.splitIndex', 'false'),
('core.sparseCheckout', 'false'), ('core.untrackedCache', 'false')]
env['GIT_CONFIG_COUNT'] = str(len(overrides))
for number, (name, value) in enumerate(overrides):
env[f'GIT_CONFIG_KEY_{number}'] = name
env[f'GIT_CONFIG_VALUE_{number}'] = value
key_path = fixture / 'generated-fixture-key'
run(['/usr/bin/ssh-keygen', '-q', '-t', 'ed25519', '-N', '',
'-C', 'public-generated-hook-probe', '-f', str(key_path)], fixture, env,
adapter=adapter)
key = key_path.read_bytes()
for number, record in enumerate(records):
root = record['root']; hook = record['hook']
local = fixture / str(number); local.mkdir(mode=0o700)
objects = local / 'objects'; objects.mkdir(mode=0o700)
probe_env = dict(env, GIT_INDEX_FILE=str(local / 'index'),
GIT_OBJECT_DIRECTORY=str(objects),
GIT_ALTERNATE_OBJECT_DIRECTORIES=record['objects'])
name = '__rmgr_scanner_batch_generated_fixture__.txt'
if git(root, probe_env, 'ls-tree', '--name-only', 'HEAD', '--', name, adapter=adapter):
raise Refused('fixture-name-collision')
row = {'repo': root.name, 'cases': []}
for case, payload, expected, expected_exit in [
('clean', b'public generated clean hook probe\n', 'clean', 0),
('generated-private-key', key, 'blocked', 1),
]:
if watcher.poll() is not None:
raise Refused('fixture-watchdog-lost')
# HEAD metadata seeds only the temporary index. No worktree
# files, existing blob contents, real index or refs are read.
git(root, probe_env, 'read-tree', 'HEAD', adapter=adapter)
oid = git(root, probe_env, 'hash-object', '-w', '--stdin', data=payload,
adapter=adapter).decode().strip()
git(root, probe_env, 'update-index', '--add', '--cacheinfo',
'100644,' + oid + ',' + name, adapter=adapter)
changed = git(root, probe_env, 'diff', '--cached', '--name-only', '-z',
'--no-renames', '--no-ext-diff', '--no-textconv', adapter=adapter)
if changed != name.encode() + b'\0':
raise Refused('fixture-changed-object-scope-refused')
result = subprocess.run([str(hook)], cwd=root, env=probe_env,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30,
check=False, preexec_fn=functools.partial(adapter.child_limits,
64 * 1024**2, os.getpid()))
if result.stderr or key.strip() in result.stdout:
raise Refused('hook-output-refused')
body = json.loads(result.stdout)
if set(body) != {'status', 'scope', 'scanner_version', 'scanner_sha256',
'scanned_blobs', 'blocked_blob_ids'}:
raise Refused('hook-summary-schema-refused')
if (result.returncode != expected_exit or body['status'] != expected
or body['scope'] != 'changed-staged-blobs'
or body['scanner_version'] != '8.30.1'
or body['scanner_sha256'] != BINARY_SHA or body['scanned_blobs'] != 1
or body['blocked_blob_ids'] != ([oid] if expected == 'blocked' else [])):
raise Refused('hook-result-refused')
row['cases'].append({'case': case, 'status': expected,
'exit_code': expected_exit, 'scanned_blobs': 1})
observations.append(row)
# Watcher normal completion, source children and fixture directory cleanup
# have all completed before these postconditions are evaluated.
if fixture.exists() or set(Path('/dev/shm').glob('rmgr-secret-scan-*')) - prior_storage:
raise Refused('fixture-cleanup-unverified')
again = precheck()
for before, after in zip(records, again):
if before['index_stat'] != after['index_stat'] or before['head'] != after['head']:
raise Refused('real-repository-state-changed')
receipt.update(status='verified', cases=observations, fixture_removed=True,
new_scan_storage_absent=True, real_index_stat_unchanged=True,
real_head_unchanged=True, routing_and_artifacts_unchanged=True)
except Refused as error:
receipt['reason'] = error.args[0]
except (OSError, ValueError, subprocess.SubprocessError, adapter.Unverified if 'adapter' in locals() else OSError):
receipt['reason'] = 'probe-unavailable'
receipt['fixture_removed'] = fixture is None or not fixture.exists()
receipt['driver_sha256'] = digest(Path(__file__))
(HERE / 'configured-hook-results.json').write_text(json.dumps(receipt, indent=2) + '\n')
print(json.dumps({'status': receipt['status'], 'fixture_removed': receipt['fixture_removed'],
'cases': sum(len(row['cases']) for row in observations)}))
return 0 if receipt['status'] == 'verified' else 2
if __name__ == '__main__':
for signum in (signal.SIGTERM, signal.SIGINT, signal.SIGHUP):
signal.signal(signum, lambda *_: (_ for _ in ()).throw(Refused('probe-interrupted')))
raise SystemExit(main())