moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
# Tier 3 Steal Arc — Adversarial Verification Verdict (2026-07-15)
Branch `feat/steals-tier3` (commits `2d4b0ca2..f322cc2c` + fix commit below).
Verifier fleet: 6 agents (workflow `wf_ac6e9d94-dd9`); 4 completed, 2 (verify:17, verify:cross)
died on API safeguard false-positives — **those two audits were re-executed inline by the
orchestrator** (findings below marked [inline]).
## Verdicts
| Item | Fleet verdict | After fixes |
|---|---|---|
| S1 sanitizer | APPROVE (0 C/H) | APPROVE |
| #13 automation gate | **BLOCK — 1 HIGH** | fixed → APPROVE |
| #15 skill badges | APPROVE (0 C/H) | APPROVE |
| #12 compaction persist | **BLOCK — 1 HIGH + 1 MEDIUM** | fixed → APPROVE |
| #17 ai_task | [inline] **2 findings (1 HIGH-class SEC, 1 MEDIUM)** | fixed → APPROVE |
| cross-cutting | [inline] no blocking findings | APPROVE |
## Fixed in the post-verdict commit
1. **#13 HIGH — error-path transcript dump (chat.ts:2160).** The #3 launch-blocker raw-turn
persistence in the outer catch was not gated: an automated review turn failing on
context_length (likeliest failure for transcript-embedding turns) persisted the ENTIRE
review instruction + session transcript as a `user_stated` frame, then memory-lane cron
would LLM-amplify it. Fix: `&& !isAutomatedTurn`.
2. **#12 HIGH — cross-mind destructive overwrite (orchestrator.ts).** `compactionFrameIds` is
keyed by sessionId while persist routes by active mind; after a workspace switch the same
rowid can be an unrelated user frame in the new mind, and `frames.update()` overwrote it.
Verifier demonstrated with a repro test. Fix: update-in-place only when the existing frame's
content starts with this session's `[Session summary — <key>]` marker; else create fresh.
Regression test added (foreign frame with colliding id survives untouched).
3. **#12 MEDIUM — sign-gate over-trigger.** `isSelfIncapacityAssertion` over the whole
multi-section summary downgraded the entire session gist to `temporary` (recall-invisible)
whenever one boilerplate "you'll need to run X" line appeared — silently no-op'ing the
feature for long sessions. Fix: no sign-gate on compaction summaries (importance always
`normal`, provenance `source='system'`); D1 ruling amended.
4. **#12 LOW — seam consistency.** Persist now also gated `!hasCustomRunner` like every sibling
write-back seam.
5. **[inline] #17 SEC — deliverTo smuggling via job_data.** `create_schedule`'s free-form
`job_data` JSON could set `mode:'ai_task'` + `deliverTo:{platform,chatId}` (with or without
the `prompt` param), routing scheduled agent output to an arbitrary, unpaired chat — bypassing
the trusted-origin-snapshot design. Fix: `mode`/`deliverTo`/`once` are always stripped from
parsed job_data (settable only via the typed param path). Test added.
6. **[inline] #17 MEDIUM — firesTooOften bypass.** Range (`1-59 * * * *`) and step-on-range
(`0-59/2`) minute fields passed the guard. Fix: allowlist (fixed minute | `*/N` N≥5 | ≤12-item
fixed list); everything else rejected. Bypass exprs added to the test matrix. (Damage was
already bounded by the daily cap — verified ALIVE, not dead code: `executeJob`/`tick`
`onJobComplete``makeRecordExecutionCallback``cronStore.recordExecution` fires for every
run mode-agnostically, filling exactly the table `countExecutionsToday` reads; the
cron-ai-task test seeds that table and observes the skip.)
## Residual findings — documented, NO action (LOW/NIT)
- **S1 MEDIUM (pre-existing, out of scope):** 4th legacy sanitizer copy in
`packages/server/src/local/routes/memory.ts:102` (`scope=global` UI search) still zeroes
Cyrillic/diacritic queries — pre-existing (blame 2026-04-12), not benchmark-affecting.
**Backlog: 3-line swap to `buildFtsOrQuery` (needs barrel export from hive-mind-core).**
- S1 LOW ×3: mixed CJK+stopword queries reach LIKE fallback with stopword noise (narrow trigger,
fusion dampens); CJK terms silently dropped from mixed queries when ASCII tokens survive
(documented tradeoff, vector lane compensates, v2 = per-token LIKE augmentation); pure-CJK
still `[]` in MultiMind.ftsSearch / raw-detail-lane (per spec, not a regression).
- #13 LOW: `NOT LIKE '[Loop:%'` is ASCII case-insensitive in SQLite — a user frame starting
`[loop:` is also excluded from lane amplification (stays recallable; bounded).
- #13 NIT ×2: `origin` is self-inflicted opt-out only (localhost+auth, no escalation); auto
skill-capture heuristic (`sessionToolSequences`) not gated for automated turns.
- #15 LOW ×2: vault-POST cache invalidation is a near-no-op today (env/vault checks are uncached;
only bin lookups cache) — harmless, kept as forward-compat; YAML sequence form (`- KEY`) under
`requires:` not parsed (only inline `[a, b]` / comma form) — document the supported grammar.
- #15 NIT: `k in process.env` walks the prototype chain (cosmetic false-positive edge).
- #12 LOW/NIT: `frames.update()` leaves stale `memory_frame_chunks` rows under
`WAGGLE_CHUNK_RETRIEVAL=1` (off by default); injection scan threshold 0.7 lets single-category
signals through (tool-output provenance is `source='system'`, not user-trusted).
## Gate status after fixes
agent tsc 0 · server tsc clean via paths-harness · fix-affected suites 36/36
(cron-tools incl. new SEC + range-bypass cases, compaction-persist incl. cross-mind guard +
no-downgrade cases, cron-ai-task daily-cap alive). Full suites re-run pre-push.
**FINAL: APPROVE** — all HIGH resolved, 0 CRITICAL, residuals are LOW/NIT/pre-existing.