diff --git a/AGENTS.md b/AGENTS.md index c7ada46..517e2dd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -152,10 +152,13 @@ All three P1 items are fixed and committed; suite is green at 57 tests (was 47). ### Known debt — P2 (accepted for now; fix opportunistically) -- Path traversal on internal-meetings `:id` (admin-gated): validate `^[A-Za-z0-9_-]+$` before `path.join` — `routes/internal-meetings.js:84,91,242` (`output-store.js:52` shows the pattern). *(security-auditor + exerciser)* -- Non-constant-time operator-key compare (`!==`) on `relay_cloud_operator_key` — `server/identity.js:43,84`; use `timingSafeEqual` like the admin path. *(evaluator + security-auditor)* +**Done 2026-06-13** (commits `cbd9748`/`da1bba2`/`693d724`; suite green at 60 tests): +- ✅ Path traversal on internal-meetings `:id` — centralized `meetingPath()` in `routes/internal-meetings.js` sanitizes to `[A-Za-z0-9_-]` (mirrors `output-store.js`); `saveMeeting`/`loadMeeting`/`deleteMeeting` all route through it. Test: `test/meeting-path.test.js`. +- ✅ Non-constant-time operator-key compare — `identity.js` now uses a `timingSafeEqual`-based `constantTimeEqual` in `resolveIdentity` + `verifyOperatorKey`. +- ✅ Malformed-body stack-trace leak — added a final error-handling middleware in `index.js` (JSON 400 for `entity.parse.failed`, 413 for too-large, generic 500 otherwise). Verified end-to-end: the exerciser's repro now returns `{"error":"invalid JSON body"}` with no stack. + +Still open: - In-memory webhook dedup Set lost on restart → double-credit/double-extend — `routes/credits.js:63`, `zaprite-webhook.js:27`; persist processed invoice/order ids. *(security-auditor)* -- Malformed JSON body → full Node stack trace (FS paths) — add an Express `entity.parse.failed` → JSON-400 handler. *(exerciser)* - BTCPay declared `optional:false`/`kind:'running'` despite "optional" comments → StartOS won't start the relay without BTCPay co-installed — `startos/manifest/index.ts:38-49`, `startos/dependencies.ts`. Decide, then make manifest + dependencies + comment agree. *(start9-spec-checker)* - No money-path unit tests (`commitCredit`/`refundCredit`/`applyTierPromotion`/`planBackend`/grant handlers) — why the P1 billing bug ships green. *(evaluator)* - `routes/internal-meetings.js` is 2225 lines; extract the MD/HTML formatters + storage/backfill layer. *(evaluator)*