-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
gate-reviewRequires human gate review before proceedingRequires human gate review before proceedingsecuritySecurity and access control enforcementSecurity and access control enforcement
Description
GITHUB_TRIPLE_LOCK_INVARIANT v0.1 — LOCK 2: INTEGRITY
Part of: GITHUB_TRIPLE_LOCK_INVARIANT
Related: #33 (LOCK 1: Authority)
Source: Security audit by Comet (Perplexity browser agent), 2026-03-08
Question this lock answers
Is the change set exact, bounded, and tamper-evident?
Required checks
- Signed commits required on protected branches
- Stale approvals dismissed on new push
- Changed files match declared scope
- Rulesets / decision artefacts / workflows schema-validated
- Canonical hash or digest emitted for sensitive artefacts
- Empty or wildcard scope cannot expand authority
- No mutable primitive regression introduced
Audit issues addressed
Issue cluster A — StopMachine mutable / reset loop / subclass override:
StopMachine._statecan be overwritten directly bypassing terminal REDreset()allows AMBER->GREEN loops contradicting forward-only invariant- No subclassing guard (
__init_subclass__,__slots__,final) - Fix: Make StopMachine
@dataclass(frozen=True)withevolve()per existing spec
Issue cluster B — AuthorityGate mutable / Evidence extension / empty scope / drift bypass:
AuthorityGate._requiredcan be overwritten (gate._required = Evidence.NONE)Evidence(999)via IntEnum compares higher than ADMIN_scope_matcheswith emptyscope_match: {}matches every requestacknowledge_expansion=Truebypasses drift detection- Fix: Freeze AuthorityGate, add
__slots__, validate Evidence membership
Issue cluster C — plain dict ruleset / no hash verification:
evaluate()accepts any dict as ruleset with no schema validation- Modified rulesets with extra allowlist entries accepted silently
- Fix: Schema-validate rulesets, emit canonical hash at load time
Issue cluster E — DecisionRecord incomplete canonical bytes:
canonical_bytesonly hashes 5 of 10+ fieldsactor_id,tenant_id,timestamp,gate_version,context_hashexcluded- Two decisions with different actors produce identical hashes
- Fix: Include all identity-bearing fields in canonical hash
Concrete actions
- Implement immutable StopMachine (
@dataclass(frozen=True)+evolve()) - Freeze AuthorityGate with
__slots__+__setattr__guard - Add schema validation for ruleset JSON before
evaluate()accepts it - Fix
_scope_matchesto reject empty scope as universal match - Fix
DecisionRecord.canonical_bytesto include all audit-trail fields - Enable "Require signed commits" in branch protection
- Add CI check that blocks mutable-primitive regressions on governance paths
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
gate-reviewRequires human gate review before proceedingRequires human gate review before proceedingsecuritySecurity and access control enforcementSecurity and access control enforcement