fix(memory): scope InsightsRepo operations to userId — M2-001/002 #290

Merged
jason.woltje merged 1 commits from fix/m2-insights-user-scope into main 2026-03-21 20:34:43 +00:00
Owner

Summary

Security audit and fix for InsightsRepo to prevent cross-user data leakage.

M2-001 — searchByEmbedding: Confirmed already user-scoped via WHERE user_id filter. No change needed.

M2-002 — findByUser: Confirmed already user-scoped. No change needed.

M2-002 — decayOldInsights: Was global (no userId filter). Fixed by requiring userId param and scoping to eq(insights.userId, userId). Added decayAllInsights for system cron tier-management.

Additional fixes found during audit:

  • findById: added userId param + AND eq(userId) to prevent cross-user read
  • update: added userId param + AND eq(userId) to prevent cross-user write
  • remove: added userId param + AND eq(userId) to prevent cross-user delete
  • memory.controller getInsight/removeInsight: now pass user.id for ownership
  • summarization.service: switched cron to decayAllInsights

Test plan

  • typecheck passes
  • lint passes
  • format:check passes
  • GET /api/memory/insights/:id returns 404 for another user's insight
  • DELETE /api/memory/insights/:id returns 404 for another user's insight
## Summary Security audit and fix for InsightsRepo to prevent cross-user data leakage. **M2-001 — searchByEmbedding**: Confirmed already user-scoped via WHERE user_id filter. No change needed. **M2-002 — findByUser**: Confirmed already user-scoped. No change needed. **M2-002 — decayOldInsights**: Was global (no userId filter). Fixed by requiring userId param and scoping to eq(insights.userId, userId). Added decayAllInsights for system cron tier-management. **Additional fixes found during audit:** - findById: added userId param + AND eq(userId) to prevent cross-user read - update: added userId param + AND eq(userId) to prevent cross-user write - remove: added userId param + AND eq(userId) to prevent cross-user delete - memory.controller getInsight/removeInsight: now pass user.id for ownership - summarization.service: switched cron to decayAllInsights ## Test plan - [x] typecheck passes - [x] lint passes - [x] format:check passes - [ ] GET /api/memory/insights/:id returns 404 for another user's insight - [ ] DELETE /api/memory/insights/:id returns 404 for another user's insight
jason.woltje added 1 commit 2026-03-21 20:17:13 +00:00
fix(memory): scope InsightsRepo operations to userId — M2-001/002
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
b5d600e39b
Security audit findings and fixes:

M2-001 — searchByEmbedding: confirmed already user-scoped via WHERE user_id
M2-002 — findByUser: confirmed already user-scoped
M2-002 — decayOldInsights: was global (no userId filter); now requires userId
  param and scopes UPDATE to eq(insights.userId, userId). Added decayAllInsights
  as a separate system-only method for cron tier management.

Additional unscoped operations fixed:
- findById: added userId param + AND eq(userId) to prevent cross-user read
- update: added userId param + AND eq(userId) to prevent cross-user write
- remove: added userId param + AND eq(userId) to prevent cross-user delete
- memory.controller getInsight/removeInsight: now pass user.id for ownership
- summarization.service: switched tier-management cron to decayAllInsights

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jason.woltje merged commit 05a805eeca into main 2026-03-21 20:34:43 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#290