Skip to content
This repository was archived by the owner on May 4, 2026. It is now read-only.

TCK-00613: FAC gates architecture alignment + security hardening (throughput-profile model)#708

Merged
Anveio merged 9 commits into
mainfrom
ticket/RFC-0019/TCK-00613
Feb 17, 2026
Merged

TCK-00613: FAC gates architecture alignment + security hardening (throughput-profile model)#708
Anveio merged 9 commits into
mainfrom
ticket/RFC-0019/TCK-00613

Conversation

@Anveio

@Anveio Anveio commented Feb 17, 2026

Copy link
Copy Markdown
Collaborator
ticket_meta:
  schema_version: 2026-01-29
  template_version: 2026-01-29
  ticket:
    id: TCK-00613
    title: FAC gates architecture alignment + security hardening (throughput-profile model)
    status: OPEN
  binds:
    prd_id: PRD-PLACEHOLDER
    rfc_id: RFC-0019
    requirements: []
    evidence_artifacts: []
  custody:
    agent_roles:
    - AGENT_IMPLEMENTER
    responsibility_domains:
    - DOMAIN_RUNTIME
    - DOMAIN_SECURITY
    - DOMAIN_DOCUMENTATION
  dependencies:
    tickets:
    - ticket_id: TCK-00612
      reason: Defines the throughput-profile model (`throughput`/`balanced`/`conservative`) and host-aware parallelism contract used by fac gates.
    - ticket_id: TCK-00605
      reason: Defines bounded test execution constraints and containment policy used by FAC gates.
    - ticket_id: TCK-00563
      reason: Canonicalizer tuple pinning and receipt integrity remain required invariants in worker/broker admission flows.
  root_cause_analysis:
    summary: |
      The prior revision of this ticket mixed two incompatible directions:
      - A new trait/registry gate engine with gate-set `--profile`.
      - The already-adopted command-centric FAC gates runtime with throughput
        profiles and typed gate checks.

      In parallel, PR review surfaced concrete security and correctness gaps:
      - Signing key TOCTOU and duplicated key-handling paths.
      - Unbounded file reads in gates/preflight paths.
      - Worker workspace-root trust boundary ambiguity.
      - Process-global CWD mutation in worker execution path.
      - workflow_dispatch authorization trust override via env var.
      - test_safety_guard misses on top-level `src/*.rs` and unbounded traversal.

      This ticket update formalizes the architecture actually in use and binds
      DoD to hardened, fail-closed behavior across FAC gates and preflight.
  scope:
    in_scope:
    - 'Architecture contract: command-centric gates execution remains authoritative (`fac_review/gates.rs` orchestration + typed checks in `fac_review/gate_checks.rs`).'
    - 'Gate selection semantics: keep `--quick` as gate-set selector (fast subset) and full mode as default behavior.'
    - 'Throughput semantics: keep `--gate-profile` (`throughput`/`balanced`/`conservative`) for resource/concurrency policy, independent of gate-set selection.'
    - Introduce shared hardened signer-key utility (`fac_key_material`) and remove duplicated key creation/loading logic across queue submit, worker, and broker paths.
    - Introduce shared fail-closed bounded-read utility (`fac_secure_io`) and replace raw unbounded reads in FAC review gate checks, FAC preflight, FAC broker, queue submit, and worker-adjacent read sites.
    - Enforce fail-closed handling for oversized/unreadable inputs in security-sensitive paths (no skip-on-error behavior for authorization/gate enforcement inputs).
    - Remove process-global CWD mutation from worker execution path; pass explicit workspace root through the gates call chain.
    - 'Define and enforce workspace-root admission policy in worker gates execution: canonical dir, git toplevel equality, repo identity binding, and explicit deny for FAC-internal roots.'
    - 'Strengthen preflight trust binding: no env override for actor permission, validated repository/actor normalization, bounded event/policy/PR JSON parsing, and explicit deny on permission lookup failure.'
    - 'Harden test_safety_guard determinism and coverage: tracked-file-first targeting, top-level `src/lib.rs` and `src/main.rs` coverage under `#[cfg(test)]`, and bounded fail-closed file reads.'
    - Add regression tests for key creation race, workflow_dispatch permission checks, oversized payload denial, workspace-root policy denial, and top-level Rust test-safety detection.
    out_of_scope:
    - Mandating a `gates_engine/` trait/registry abstraction (`Gate`, `GateRegistry`, `GateRunner`) in this ticket.
    - Replacing current gate-set semantics with a new `--profile <gate-set>` CLI contract in this ticket.
    - Repository-wide deletion of all shell scripts outside the FAC gates/preflight hardening scope.
    - Backward-compatibility shims for superseded ticket language.
    - Global scheduler redesign or distributed queue architecture changes.
  plan:
    steps:
    - id: STEP_01
      title: Codify architecture and CLI contract
      detail: |
        Lock the canonical model for this ticket:
        - `fac_review/gates.rs` orchestrates execution.
        - `--quick` controls gate-set shape.
        - `--gate-profile` controls throughput/resource policy only.
    - id: STEP_02
      title: Centralize hardened key material handling
      detail: |
        Add shared signer utility for secure create/load semantics:
        - create with owner-only mode at open time
        - nofollow safeguards
        - fsync of file and parent dir
        - race-safe concurrent creator convergence
        Replace all duplicate key handling in queue submit/worker/broker.
    - id: STEP_03
      title: Centralize bounded fail-closed file reads
      detail: |
        Add shared bounded I/O helper and migrate targeted paths off raw
        `fs::read` / `fs::read_to_string` for security-sensitive inputs.
    - id: STEP_04
      title: Harden worker execution boundary
      detail: |
        Remove ambient CWD dependency and enforce explicit workspace-root
        admission checks (canonicalize + git root + repo bind + FAC-internal
        deny rules).
    - id: STEP_05
      title: Harden preflight trust binding
      detail: |
        Remove env-based actor-permission override from authorization path,
        enforce repository/actor normalization, and deny on oversized/invalid
        preflight payloads or permission lookup failures.
    - id: STEP_06
      title: Fix gate correctness regressions
      detail: |
        Ensure test_safety_guard covers top-level `src/*.rs` test regions and
        uses bounded deterministic file targeting/read behavior.
    - id: STEP_07
      title: Regression suite and verification
      detail: |
        Run targeted security/correctness regressions and strict quality gates:
        - `cargo fmt --all`
        - `cargo clippy -p apm2-cli --all-targets --all-features -- -D warnings`
        - `cargo test -p apm2-cli`
  definition_of_done:
    evidence_ids: []
    criteria:
    - 'Ticket language is internally consistent with implemented architecture: command-centric gates orchestration + throughput profiles.'
    - Signer key lifecycle is centralized; queue submit, worker, and broker use shared hardened key material helpers.
    - No production path creates signing keys via write-then-chmod TOCTOU sequence.
    - Bounded read helper is shared and used across targeted FAC gates/preflight/broker/queue paths; oversized inputs are denied fail-closed.
    - Worker gates execution path does not mutate process-global CWD.
    - Worker workspace_root admission denies FAC-internal roots and repo-identity mismatches; git toplevel binding is enforced.
    - workflow_dispatch authorization does not trust env permission overrides and denies on lookup failure or insufficient permission.
    - Preflight event/policy payload reads are bounded and oversized payloads fail closed.
    - test_safety_guard evaluates top-level `src/lib.rs` and `src/main.rs` test regions and fails closed on oversized targets.
    - Regression tests exist for signer concurrency, workflow_dispatch permission checks, oversized payload denial, and workspace-root policy denial.
    - '`cargo fmt --all` passes.'
    - '`cargo clippy -p apm2-cli --all-targets --all-features -- -D warnings` passes.'
    - '`cargo test -p apm2-cli` passes.'
  notes:
    context: |
      This amendment aligns TCK-00613 with the architecture currently used by
      FAC gates in this repository branch:
      - command-centric orchestration in `fac_review/gates.rs`
      - typed gate checks and evidence checks under `fac_review/*`
      - throughput profile model from TCK-00612

      It intentionally removes conflicting requirements that assumed this ticket
      was also the migration vehicle for a trait/registry gate engine and
      gate-set profile CLI redesign.
    amendments:
    - amendment_id: AMD-2026-02-17-ARCH-REALIGNMENT
      summary: Replace conflicting gate-engine/profile requirements with branch-aligned architecture and hardening scope.
      supersedes:
      - Requirement that TCK-00613 must introduce `gates_engine/` with `Gate` trait, `GateRegistry`, and `GateRunner`.
      - Requirement that TCK-00613 must replace `--quick` with gate-set `--profile` semantics.
      - Requirement that TCK-00613 must be the single vehicle for repository-wide script eradication.
      replacement:
      - TCK-00613 defines and hardens the existing command-centric FAC gates model with explicit fail-closed security guarantees.
      - Gate-set profile CLI redesign and trait/registry abstraction, if still desired, are follow-on architecture work and not blockers for this ticket.
    security: default-deny, least privilege, fail-closed
fac_push_metadata:
  commit_history:
  - short_sha: a1243893
    message: TCK-00613 add unified gate engine ticket, close 5 merged TCKs
  - short_sha: be3acbb2
    message: cut over FAC CI preflight/gates to Rust and remove shell scripts
  - short_sha: 667de9a9
    message: stabilize FAC test home isolation and env-mutating test locks
  - short_sha: 8fb26f32
    message: Harden FAC admission binding and stabilize gate execution
  - short_sha: 04a10c79
    message: Update TCK-00613 with stabilization fixes and FAC doctor findings
  - short_sha: a302f44d
    message: Fix FAC doctor registry-integrity recovery and convergence
  - short_sha: d110dbb8
    message: Harden FAC gates/preflight security paths and realign TCK-00613 architecture
  - short_sha: 8942f3c8
    message: Harden FAC preflight trust binding and gate/workspace admission
  - short_sha: 847f5226
    message: Make fac gates wait-by-default and self-process queue

FAC Gate Status

# apm2-gate-status:v2
sha: 847f5226e76863728706248036fd772f6f4721b0
short_sha: 847f5226
timestamp: '2026-02-17T02:22:33Z'
all_passed: true
gates:
  - name: 'merge_conflict_main'
    status: PASS
    duration_secs: 0
  - name: 'rustfmt'
    status: PASS
    duration_secs: 4
  - name: 'clippy'
    status: PASS
    duration_secs: 46
  - name: 'doc'
    status: PASS
    duration_secs: 36
  - name: 'test_safety_guard'
    status: PASS
    duration_secs: 2
  - name: 'test'
    status: PASS
    duration_secs: 79
  - name: 'workspace_integrity'
    status: PASS
    duration_secs: 0
  - name: 'review_artifact_lint'
    status: PASS
    duration_secs: 0

Test added 4 commits February 16, 2026 13:56
Create TCK-00613: migrate all CI from shell scripts to unified Rust
gate engine under apm2 fac gates with profile-based gate selection
(local-full, quick, workflow-preflight, drift-audit).

Close merged tickets: TCK-00534, TCK-00544, TCK-00596, TCK-00597,
TCK-00612.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

TCK-00613 close merged TCK-00532 and TCK-00549

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

TCK-00613: squash-prep aggregate branch + working tree
@Anveio Anveio enabled auto-merge February 17, 2026 00:04
@Anveio

Anveio commented Feb 17, 2026

Copy link
Copy Markdown
Collaborator Author
# apm2-review-verdict:v1
schema: apm2.review.verdict.v1
pr: 708
sha: 04a10c79e9da2966ded1139911c5b8f8ab206ff8
updated_at: 2026-02-17T00:59:34Z
dimensions:
  code-quality:
    decision: deny
    reason: 'FAIL: 2 blocker, 2 major findings. Significant architecture divergence (missing Gate Engine, missing Profiles) and security risks (DoS, Path Traversal).'
    set_by: ubuntu
    set_at: 2026-02-17T00:59:34Z
  security:
    decision: deny
    reason: 'FAIL: 0 blocker, 2 major findings'
    set_by: ubuntu
    set_at: 2026-02-17T00:58:57Z
findings:
- finding_id: f-708-code_quality-1771289937612561-0
  type: code-quality
  severity: BLOCKER
  summary: 'Missing requirement: S1 Gate Engine architecture (Trait/Registry/Runner)'
  risk: Architecture divergence from approved design creates hardcoded maintenance burden and prevents profile-based extensibility.
  impact: Violates TCK-00613 Scope S1. The PR implements ad-hoc matching in evidence.rs instead of the required gates_engine module with Gate trait and GateRegistry.
  location: crates/apm2-cli/src/commands/fac_review/evidence.rs
  body: The ticket explicitly requires a gates_engine/ module with a Gate trait, GateRegistry, and GateRunner. The PR implements gate_checks.rs with standalone functions (run_test_safety_guard) manually matched in evidence.rs. This fails the requirement for a unified gate registry and dynamic profile resolution.
  evidence_digest: ccbb073937f827d45b94a540160b7e3b9dee5d03ac87fa55afba0132c949de9d
  evidence_pointer: none
  timestamp: 2026-02-17T00:58:57Z
- finding_id: f-708-code_quality-1771289942753069-0
  type: code-quality
  severity: BLOCKER
  summary: 'Missing requirement: S2 --profile CLI argument for gate sets'
  risk: Inconsistent user experience and failure to deliver requested CI profile capability.
  impact: Violates TCK-00613 Scope S2. The PR retains --quick flag and repurposes gate_profile for throughput (concurrency) instead of gate sets (local-full, workflow-preflight).
  location: crates/apm2-cli/src/commands/fac_review/gates.rs
  body: The ticket requires apm2 fac gates --profile <local-full|quick|...> to control WHICH gates run. The PR implements GateThroughputProfile (Throughput/Balanced/Conservative) which controls parallelism, and retains the boolean --quick flag. The requested gate-set profile logic is missing.
  evidence_digest: 6d97b8a4834becea5fb4cff53ee36b9f0778e171ae6723e06a976f8f29eeb5a3
  evidence_pointer: none
  timestamp: 2026-02-17T00:59:02Z
- finding_id: f-708-code_quality-1771289950328986-0
  type: code-quality
  severity: MAJOR
  summary: Unbounded file read in gate_checks.rs and fac_preflight.rs
  risk: Denial of Service (DoS) via OOM if large files are encountered during scanning.
  impact: Violates CTR-1603 (Bounded Reads). Processing large files (e.g. accidentally committed binaries or huge logs) will crash the process.
  location: crates/apm2-cli/src/commands/fac_review/gate_checks.rs
  body: Functions run_test_safety_guard and run_review_artifact_lint call fs::read on all walked files without a size check. Similarly, fac_preflight.rs:scan_regex_matches uses fs::read_to_string on scan paths. Implement read_bounded or check file size before reading.
  evidence_digest: cd2d8bae39004184983f03d262783c6c358dbb2a2573e6e631a9818b36925837
  evidence_pointer: none
  timestamp: 2026-02-17T00:59:10Z
- finding_id: f-708-code_quality-1771289964239148-0
  type: code-quality
  severity: MAJOR
  summary: Arbitrary workspace execution root in fac_worker
  risk: Security boundary violation; worker execution in unauthorized paths.
  impact: Violates SP-RUNTIME-001 (Sandbox Isolation). fac_worker accepts workspace_root from the job payload and chdirs into it without validation.
  location: crates/apm2-cli/src/commands/fac_worker.rs
  body: 'resolve_workspace_root accepts any directory path. An attacker could submit a gates job with workspace_root: /etc or other sensitive paths, causing the worker to execute commands in that context. Validate that workspace_root is within APM2_HOME, the repo root, or a specific allowlisted lane directory.'
  evidence_digest: 7f4044d1f12ab0eec9cf728d77129b0310f8da1b6faf58d58f1d9584510c27dc
  evidence_pointer: none
  timestamp: 2026-02-17T00:59:24Z
- finding_id: f-708-code_quality-1771289969529967-0
  type: code-quality
  severity: MINOR
  summary: Missing validation for repository variable in fac_preflight.rs
  risk: Potential URL injection or malformed API calls.
  impact: Weakens robustness of GitHub API integration.
  location: crates/apm2-cli/src/commands/fac_preflight.rs
  body: The repository variable used in fetch_pr_json_via_gh is not explicitly validated to match owner/repo format before being used in the gh api URL. Ensure it matches a strict regex.
  evidence_digest: bdbc1ae852b986cc90776830f563dcfa0fd99e6f061ae8cec8568054380d641b
  evidence_pointer: none
  timestamp: 2026-02-17T00:59:29Z
- finding_id: f-708-security-1771289883531374-0
  type: security
  severity: MAJOR
  summary: workflow_dispatch permission can be overridden by env var
  risk: Any actor can set APM2_PREFLIGHT_ACTOR_PERMISSION (e.g., workflow code, environment injection in a malicious PR workflow dispatch path, or compromised workflow step) and bypass GitHub permission lookup. The override is trusted before GH API verification and directly drives the dispatch_actor authorization check, creating a privilege bypass path from untrusted workflow input to trusted workflow_dispatch execution.
  impact: Attackers can make the pipeline treat a non-admin actor as admin/maintain/write for workflow_dispatch events, potentially skipping intended workflow trust controls and enabling unauthorized high-trust FAC actions.
  location: crates/apm2-cli/src/commands/fac_preflight.rs:843
  body: Remove env-based permission override from production authorization path. If an override is needed for tests, gate it to test-only builds or explicit debug mode, require signed runtime configuration for overrides, and retain GH permission lookup as the sole source of truth in normal runs.
  evidence_digest: cd06401db7689b0c67980a4ba1b950f1e2db4e24a22a1640737006bfcb6db0ef
  evidence_pointer: none
  timestamp: 2026-02-17T00:58:03Z
- finding_id: f-708-security-1771289888656750-0
  type: security
  severity: MAJOR
  summary: Signing key file permissions are applied after key material is written
  risk: When FAC queue state is initialized for the first time, the signing key is written with default process umask and filesystem permissions, then restricted to 0o600. A pre-existing symlink or permissive umask widens exposure/corruption between write and chmod, enabling local adversaries with write access to APM2_HOME to read/replace signing key during initialization.
  impact: Compromise of fac/private/fac/signing_key allows forging FAC job signatures or authority tokens, undermining queue admission and trusted dispatch in the FAC runtime.
  location: crates/apm2-cli/src/commands/fac_queue_submit.rs:319
  body: Create the key file atomically with owner-only permissions from the start (e.g., secure temp/file-open flags or O_NOFOLLOW-compatible helpers), refuse symlink targets, and avoid separate write+chmod step. Then fsync and fsync directory to prevent TOCTOU and residual permission leaks.
  evidence_digest: a2104c118028047e12a03c35c1e93787f8a3ec9ad7f1470f451a38902dbc261f
  evidence_pointer: none
  timestamp: 2026-02-17T00:58:08Z

@Anveio

Anveio commented Feb 17, 2026

Copy link
Copy Markdown
Collaborator Author
# apm2-review-verdict:v1
schema: apm2.review.verdict.v1
pr: 708
sha: a302f44d9c0239d4e148e5d98cb1ddaaa20df107
updated_at: 2026-02-17T01:14:18Z
dimensions:
  code-quality:
    decision: deny
    reason: 'FAIL: 1 blocker, 0 major findings'
    set_by: ubuntu
    set_at: 2026-02-17T01:14:18Z
  security:
    decision: deny
    reason: 'FAIL: 1 blocker, 2 major findings. Critical thread-safety violation in worker CWD handling (process-global state mutation), credential permission race (TOCTOU), and DoS risk via unbounded file reads.'
    set_by: ubuntu
    set_at: 2026-02-17T01:08:46Z
findings:
- finding_id: f-708-code_quality-1771290844500912-0
  type: code-quality
  severity: BLOCKER
  summary: 'Missing requirement: test_safety_guard correctly evaluates top-level src/*.rs paths'
  risk: Top-level Rust modules under src are excluded from test-safety scanning, so test-only unsafe constructs can be missed in production modules with cfg(test) regions.
  impact: Security and compliance checks can silently miss prohibited command patterns in , , etc., violating TCK-00613 DoD requirement on top-level test-safety correctness.
  location: crates/apm2-cli/src/commands/fac_review/gate_checks.rs:216
  body: The  predicate requires  for Rust source checks, but top-level crate files use  (no leading slash) and are skipped. This is a direct violation of the ticket’s acceptance criterion that  correctly evaluates top-level  paths. Update the path match to include  prefix explicitly (for example ), and add a regression test covering  with cfg(test)-scoped command-literal content.
  evidence_digest: 1eb0a8a64f33454cf6864c4904f209b45fa6607554f126b269fa88fa886cea02
  evidence_pointer: none
  timestamp: 2026-02-17T01:14:04Z
- finding_id: f-708-code_quality-1771290851574533-0
  type: code-quality
  severity: MINOR
  summary: test_safety_guard loads entire workspace files without size or directory caps
  risk: Workspace scans read every matched file fully into memory, including large artifacts in generated directories, which can cause CI resource spikes and non-deterministic timeouts.
  impact: In large repositories or adversarial inputs, gate execution can exceed memory/time budgets, producing false failures and masking true violations.
  location: crates/apm2-cli/src/commands/fac_review/gate_checks.rs:145
  body: The new test-safety gate scans all non-git entries under workspace and reads entire files with , but there are no path allowlist caps or file-size limits. Without excluding large generated trees (, , caches) or enforcing max file size, one oversized file can allocate large memory and make gate execution flaky for CI. Add bounded traversal + bounded reads (or streamed regex scanning) and explicit exclusion of non-source artifact directories before enforcement.
  evidence_digest: 180ac758c3650bfb7850b4bf0b81c4fcc952f7c37d05bd8f30c7ce208c044dfb
  evidence_pointer: none
  timestamp: 2026-02-17T01:14:11Z
- finding_id: f-708-security-1771290491971095-0
  type: security
  severity: MAJOR
  summary: Race condition in signing key permission restriction
  risk: The signing key file is created with default permissions (potentially world-readable depending on umask) before being restricted to 0600. This TOCTOU window allows other users on the system to read the private key.
  impact: Compromise of the FAC broker/worker identity, allowing an attacker to forge receipts or impersonate the node.
  location: crates/apm2-cli/src/commands/fac_queue_submit.rs:load_or_generate_persistent_signer
  body: Use `fs::OpenOptions` with `.mode(0o600)` (via `std::os::unix::fs::OpenOptionsExt`) to create the file with restricted permissions atomically at the filesystem level. Do not use `fs::write` followed by `set_permissions`.
  evidence_digest: 4cd9ff58e3801973373da546778b1b3d2dc1f0526c3a60f0f853938c7129f620
  evidence_pointer: none
  timestamp: 2026-02-17T01:08:11Z
- finding_id: f-708-security-1771290497095485-0
  type: security
  severity: BLOCKER
  summary: Thread-unsafe process-global CWD modification
  risk: The worker modifies the process-global Current Working Directory (CWD) using `std::env::set_current_dir` via `CurrentDirGuard`. In a multi-threaded runtime (like Tokio, used by apm2-daemon/worker), this affects all threads simultaneously, causing race conditions for any other file I/O, logging, or process spawning occurring in parallel.
  impact: Unpredictable failure of concurrent operations, log misplacement, or incorrect path resolution in parallel tasks. Violates Rust safety expectations for multi-threaded processes.
  location: crates/apm2-cli/src/commands/fac_worker.rs:run_gates_in_workspace
  body: Remove `CurrentDirGuard` and the call to `std::env::set_current_dir`. Refactor `run_gates_local_worker` and downstream gate logic to accept an explicit `workspace_root` path and resolve all file operations relative to that root. Do not rely on ambient CWD.
  evidence_digest: 76d226ad9adf3fac026834bb3ae9dbe37b0b7ec84a1602a7c35c726b87aa1eba
  evidence_pointer: none
  timestamp: 2026-02-17T01:08:17Z
- finding_id: f-708-security-1771290502218266-0
  type: security
  severity: MAJOR
  summary: Unbounded memory consumption in gate checks
  risk: The `run_test_safety_guard` and `run_review_artifact_lint` functions read entire files into memory strings using `fs::read` and `String::from_utf8_lossy` without size limits. Encountering a large file (e.g., generated artifact, large fixture) will cause an OOM crash (DoS).
  impact: Denial of Service of the CI/review process. An attacker could commit a large file to crash the review gate.
  location: crates/apm2-cli/src/commands/fac_review/gate_checks.rs
  body: Enforce a strict file size limit (e.g., 10MB) before reading files. Skip files exceeding the limit or process them in bounded chunks (though regex matching on chunks is harder). For source code and review artifacts, a size limit is appropriate and safe.
  evidence_digest: f1ac07c8772794a3396a9de4b4b5edda6ab59c8f79e25cd0cd201070d9d3b398
  evidence_pointer: none
  timestamp: 2026-02-17T01:08:22Z
- finding_id: f-708-security-1771290507341295-0
  type: security
  severity: MINOR
  summary: Secrets stored in weakly-typed Strings
  risk: Credentials (GITHUB_TOKEN) are stored in standard `String` types in `fac_preflight.rs`. This keeps secrets in memory longer than necessary (no zeroize on drop) and risks accidental exposure via `Debug` or panic dumps.
  impact: Increased risk of credential leakage in dumps or logs.
  location: crates/apm2-cli/src/commands/fac_preflight.rs
  body: Use `secrecy::SecretString` for credential variables to ensure redaction in Debug and best-effort zeroization on Drop. Conforms to CTR-2604.
  evidence_digest: 65065885ed6badfeaaf7087831516a9b49b801f6bccf0868b8d695a2c8282695
  evidence_pointer: none
  timestamp: 2026-02-17T01:08:27Z

@Anveio Anveio changed the title TCK-00613: Unified Rust gate engine: migrate all CI from shell scripts to apm2 fac gates profiles TCK-00613: FAC gates architecture alignment + security hardening (throughput-profile model) Feb 17, 2026
@Anveio

Anveio commented Feb 17, 2026

Copy link
Copy Markdown
Collaborator Author
# apm2-review-verdict:v1
schema: apm2.review.verdict.v1
pr: 708
sha: 847f5226e76863728706248036fd772f6f4721b0
updated_at: 2026-02-17T02:32:21Z
dimensions:
  code-quality:
    decision: approve
    reason: 'PASS: no blocker or major findings'
    set_by: ubuntu
    set_at: 2026-02-17T02:32:21Z
  security:
    decision: approve
    reason: 'PASS: no blocker or major findings (2 minor hardening findings recorded)'
    set_by: ubuntu
    set_at: 2026-02-17T02:31:00Z
findings:
- finding_id: f-708-security-1771295438921770-0
  type: security
  severity: MINOR
  summary: Gate checks can miss non-UTF8 tracked paths
  risk: A malicious contributor can use file names with non-UTF8 bytes so tracked path decoding becomes lossy before path resolution. Those entries may be skipped during safety and integrity scans.
  impact: Security gate coverage can be incomplete while reports still look successful, weakening confidence in destructive-pattern detection and workspace integrity checks.
  location: crates/apm2-cli/src/commands/fac_review/gate_checks.rs:1017
  body: Preserve raw path bytes for NUL-delimited git entries and fail closed when a tracked entry cannot be represented safely. Add a regression test using a non-UTF8 filename to prove the checker scans it or denies the run.
  evidence_digest: d203354df78751829b20d1accbf0296419617b6a17cb3d442f74f8e112a21140
  evidence_pointer: none
  timestamp: 2026-02-17T02:30:38Z
- finding_id: f-708-security-1771295451055879-0
  type: security
  severity: MINOR
  summary: Signing-key parent bootstrap uses create-then-chmod
  risk: When the signer parent path is created, directory permissions are tightened after creation. A local attacker with concurrent filesystem access to that parent hierarchy can race this window to interfere with bootstrap state.
  impact: This weakens the hard fail-closed posture around key material initialization and can enable local tampering or denial of service during first-time setup.
  location: crates/apm2-cli/src/commands/fac_key_material.rs:54
  body: Create sensitive directories with restrictive mode at creation time instead of create-and-fix. Reuse the existing FAC permission helper that uses create-time 0700 semantics, and add a regression test that asserts parent directory mode at first creation.
  evidence_digest: d42a6016bffb040cb480410e10a681ae6aca85fa59796a47324051c1d17a59dc
  evidence_pointer: none
  timestamp: 2026-02-17T02:30:51Z

@Anveio Anveio merged commit 4002520 into main Feb 17, 2026
3 checks passed
@Anveio Anveio deleted the ticket/RFC-0019/TCK-00613 branch February 17, 2026 02:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant