fix(security): scope memory tools to session userId — prevent LLM parameter injection
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful

M2-003: Audited PreferencesRepo — all five functions (findByUser, findByUserAndKey,
findByUserAndCategory, upsert, remove) already enforce userId filtering at the DB
WHERE clause level. No gaps found.

M2-004: Fixed agent memory tools (memory_search, memory_save_preference,
memory_save_insight, memory_get_preferences) — removed userId from all tool
parameter schemas so the LLM cannot inject an arbitrary user ID. The userId is
now bound from the authenticated session at tool-creation time via the new
sessionUserId parameter on createMemoryTools(). buildToolsForSandbox() and the
doCreateSession() call site are updated to thread the session userId through.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-21 15:17:20 -05:00
parent 36095ad80f
commit 0044481b4c
2 changed files with 49 additions and 21 deletions

View File

@@ -106,17 +106,22 @@ export class AgentService implements OnModuleDestroy {
) {}
/**
* Build the full set of custom tools scoped to the given sandbox directory.
* Build the full set of custom tools scoped to the given sandbox directory and session user.
* Brain/coord/memory/web tools are stateless with respect to cwd; file/git/shell
* tools receive the resolved sandboxDir so they operate within the sandbox.
* Memory tools are bound to sessionUserId so the LLM cannot access another user's data.
*/
private buildToolsForSandbox(sandboxDir: string): ToolDefinition[] {
private buildToolsForSandbox(
sandboxDir: string,
sessionUserId: string | undefined,
): ToolDefinition[] {
return [
...createBrainTools(this.brain),
...createCoordTools(this.coordService),
...createMemoryTools(
this.memory,
this.embeddingService.available ? this.embeddingService : null,
sessionUserId,
),
...createFileTools(sandboxDir),
...createGitTools(sandboxDir),
@@ -216,8 +221,8 @@ export class AgentService implements OnModuleDestroy {
);
}
// Build per-session tools scoped to the sandbox directory
const sandboxTools = this.buildToolsForSandbox(sandboxDir);
// Build per-session tools scoped to the sandbox directory and authenticated user
const sandboxTools = this.buildToolsForSandbox(sandboxDir, mergedOptions?.userId);
// Combine static tools with dynamically discovered MCP client tools and skill tools
const mcpTools = this.mcpClientService.getToolDefinitions();