Several tool helpers return error.message verbatim for BAD_REQUEST/CONFLICT cases. Prisma errors embed column names, FK relations, and offending values. An attacker can craft inputs that force these messages into the chat reply → schema enumeration, email-existence check, etc.
Information disclosure via AI channel: DB schema, column names, relation structure, existing email enumeration.
Proposed Fix
Whitelist user-safe error strings per error code. Map Prisma errors to fixed texts (e.g., USER_ALREADY_EXISTS, INVALID_INPUT). Never return raw error.message through AI.
Acceptance Criteria
All toAssistant*Error helpers return from whitelist only
Unit test: injected Prisma P2002 error → generic text
## Problem
Several tool helpers return `error.message` verbatim for BAD_REQUEST/CONFLICT cases. Prisma errors embed column names, FK relations, and offending values. An attacker can craft inputs that force these messages into the chat reply → schema enumeration, email-existence check, etc.
## Evidence
- `packages/api/src/router/assistant-tools/helpers.ts:297,373,615,922,1222,1304 — return { error: error.message }`
- `helpers.ts:997 — toAssistantUserMutationError surfaces CONFLICT email-exists`
## Impact
Information disclosure via AI channel: DB schema, column names, relation structure, existing email enumeration.
## Proposed Fix
Whitelist user-safe error strings per error code. Map Prisma errors to fixed texts (e.g., `USER_ALREADY_EXISTS`, `INVALID_INPUT`). Never return raw `error.message` through AI.
## Acceptance Criteria
- [ ] All toAssistant*Error helpers return from whitelist only
- [ ] Unit test: injected Prisma P2002 error → generic text
- [ ] Server log still retains full detail
---
Parent Epic: #1
Source: Full-Codebase Security Audit 2026-04-16 (C-2)
Fixed in commit 23c6e0e on branch security/audit-2026-04-17.
Approach. Added sanitizeAssistantErrorMessage() in packages/api/src/router/assistant-tools/helpers.ts (lines 22-55). The helper regex-detects Prisma + raw Postgres error signatures and replaces them with a generic "Invalid input" fallback:
Invalid \prisma.XXX.YYY()`` invocations
Unique constraint failed on the fields: … (P2002)
Foreign key constraint failed on the field: … (P2003)
An operation failed because it depends on … (P2025)
duplicate key value violates unique constraint (raw pg)
Plus a 500-char length cap against stack-trace-like payloads.
Call-sites fixed. All five raw passthroughs (lines 297, 373, 615, 773, 1222 per the ticket) now call sanitizeAssistantErrorMessage(error.message). The AssistantVisibleError branch in normalizeAssistantExecutionError is left as-is because its strings are developer-constructed.
Coverage.
11 new unit tests in packages/api/src/__tests__/assistant-tools-error-sanitiser.test.ts — including the acceptance-criterion P2002 case
12 existing error tests across vacation, task-action, resource-creation, project-creation error paths all remain green → no regression in hand-crafted router messages.
Short hand-crafted router messages ("Vacation cannot be approved …") pass through unchanged
Stack-trace-like payloads capped
Closing.
Fixed in commit `23c6e0e` on branch `security/audit-2026-04-17`.
**Approach.** Added `sanitizeAssistantErrorMessage()` in `packages/api/src/router/assistant-tools/helpers.ts` (lines 22-55). The helper regex-detects Prisma + raw Postgres error signatures and replaces them with a generic `"Invalid input"` fallback:
- `Invalid \`prisma.XXX.YYY()\`` invocations
- `Unique constraint failed on the fields: …` (P2002)
- `Foreign key constraint failed on the field: …` (P2003)
- `An operation failed because it depends on …` (P2025)
- `duplicate key value violates unique constraint` (raw pg)
- `null value in column "x" of relation "Y"` (raw pg)
- `violates (check|not-null|foreign key) constraint` (raw pg)
- Plus a 500-char length cap against stack-trace-like payloads.
**Call-sites fixed.** All five raw passthroughs (lines 297, 373, 615, 773, 1222 per the ticket) now call `sanitizeAssistantErrorMessage(error.message)`. The `AssistantVisibleError` branch in `normalizeAssistantExecutionError` is left as-is because its strings are developer-constructed.
**Coverage.**
- 11 new unit tests in `packages/api/src/__tests__/assistant-tools-error-sanitiser.test.ts` — including the acceptance-criterion P2002 case
- 12 existing error tests across vacation, task-action, resource-creation, project-creation error paths all remain green → no regression in hand-crafted router messages.
Acceptance:
- [x] Injected Prisma P2002-shaped error → generic "Invalid input"
- [x] Short hand-crafted router messages (`"Vacation cannot be approved …"`) pass through unchanged
- [x] Stack-trace-like payloads capped
Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
Several tool helpers return
error.messageverbatim for BAD_REQUEST/CONFLICT cases. Prisma errors embed column names, FK relations, and offending values. An attacker can craft inputs that force these messages into the chat reply → schema enumeration, email-existence check, etc.Evidence
packages/api/src/router/assistant-tools/helpers.ts:297,373,615,922,1222,1304 — return { error: error.message }helpers.ts:997 — toAssistantUserMutationError surfaces CONFLICT email-existsImpact
Information disclosure via AI channel: DB schema, column names, relation structure, existing email enumeration.
Proposed Fix
Whitelist user-safe error strings per error code. Map Prisma errors to fixed texts (e.g.,
USER_ALREADY_EXISTS,INVALID_INPUT). Never return rawerror.messagethrough AI.Acceptance Criteria
Parent Epic: #1
Source: Full-Codebase Security Audit 2026-04-16 (C-2)
Fixed in commit
23c6e0eon branchsecurity/audit-2026-04-17.Approach. Added
sanitizeAssistantErrorMessage()inpackages/api/src/router/assistant-tools/helpers.ts(lines 22-55). The helper regex-detects Prisma + raw Postgres error signatures and replaces them with a generic"Invalid input"fallback:Invalid \prisma.XXX.YYY()`` invocationsUnique constraint failed on the fields: …(P2002)Foreign key constraint failed on the field: …(P2003)An operation failed because it depends on …(P2025)duplicate key value violates unique constraint(raw pg)null value in column "x" of relation "Y"(raw pg)violates (check|not-null|foreign key) constraint(raw pg)Call-sites fixed. All five raw passthroughs (lines 297, 373, 615, 773, 1222 per the ticket) now call
sanitizeAssistantErrorMessage(error.message). TheAssistantVisibleErrorbranch innormalizeAssistantExecutionErroris left as-is because its strings are developer-constructed.Coverage.
packages/api/src/__tests__/assistant-tools-error-sanitiser.test.ts— including the acceptance-criterion P2002 caseAcceptance:
"Vacation cannot be approved …") pass through unchangedClosing.