fix(#377): remediate code review and security findings
- Fix sendThreadMessage room mismatch: use channelId from options instead of hardcoded controlRoomId - Add .catch() to fire-and-forget handleRoomMessage to prevent silent error swallowing - Wrap dispatchJob in try-catch for user-visible error reporting in handleFixCommand - Add MATRIX_BOT_USER_ID validation in connect() to prevent infinite message loops - Fix streamResponse error masking: wrap finally/catch side-effects in try-catch - Replace unsafe type assertion with public getClient() in MatrixRoomService - Add orphaned room warning in provisionRoom on DB failure - Add provider identity to Herald error logs - Add channelId to ThreadMessageOptions interface and all callers - Add missing env var warnings in BridgeModule factory - Fix JSON injection in setup-bot.sh: use jq for safe JSON construction Fixes #377 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -64,10 +64,17 @@ export class MatrixRoomService {
|
||||
const roomId = await client.createRoom(roomOptions);
|
||||
|
||||
// Store the room mapping
|
||||
await this.prisma.workspace.update({
|
||||
where: { id: workspaceId },
|
||||
data: { matrixRoomId: roomId },
|
||||
});
|
||||
try {
|
||||
await this.prisma.workspace.update({
|
||||
where: { id: workspaceId },
|
||||
data: { matrixRoomId: roomId },
|
||||
});
|
||||
} catch (dbError: unknown) {
|
||||
this.logger.error(
|
||||
`Failed to store room mapping for workspace ${workspaceId}, room ${roomId} may be orphaned: ${dbError instanceof Error ? dbError.message : "unknown"}`
|
||||
);
|
||||
throw dbError;
|
||||
}
|
||||
|
||||
this.logger.log(`Matrix room ${roomId} provisioned and linked to workspace ${workspaceId}`);
|
||||
|
||||
@@ -134,19 +141,11 @@ export class MatrixRoomService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the underlying MatrixClient from the MatrixService.
|
||||
*
|
||||
* The MatrixService stores the client as a private field, so we
|
||||
* access it via a known private property name. This is intentional
|
||||
* to avoid exposing the client publicly on the service interface.
|
||||
* Access the underlying MatrixClient from the MatrixService
|
||||
* via the public getClient() accessor.
|
||||
*/
|
||||
private getMatrixClient(): MatrixClient | null {
|
||||
if (!this.matrixService) return null;
|
||||
|
||||
// Access the private client field from MatrixService.
|
||||
// MatrixService stores `client` as a private property; we use a type assertion
|
||||
// to access it since exposing it publicly is not appropriate for the service API.
|
||||
const service = this.matrixService as unknown as { client: MatrixClient | null };
|
||||
return service.client;
|
||||
return this.matrixService.getClient();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user