feat(inquiries): sanitize HTML in inquiry message at application layer (TEC-2929)

- Add SanitizeHtmlService (whitelist: b, i, br, p, a) using sanitize-html.
- Force rel="noopener noreferrer nofollow" and target="_blank" on anchors.
- Restrict URL schemes to http/https/mailto/tel; drop javascript: links.
- Wire sanitizer into CreateInquiryHandler before InquiryEntity.createNew.
- Register provider in InquiriesModule.
- Add unit tests: 7 for the service + 2 handler-level XSS payload tests
  (<script>...</script> and <img onerror=...> stripped).

Defense-in-depth complement to global SanitizeInputMiddleware so internal
command paths bypassing HTTP middleware (queues, imports) stay safe.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-20 10:47:22 +07:00
parent 69d37c4e77
commit 3287298592
5 changed files with 154 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ import { CreateInquiryHandler } from './application/commands/create-inquiry/crea
import { MarkInquiryReadHandler } from './application/commands/mark-inquiry-read/mark-inquiry-read.handler';
import { GetInquiriesByAgentHandler } from './application/queries/get-inquiries-by-agent/get-inquiries-by-agent.handler';
import { GetInquiriesByListingHandler } from './application/queries/get-inquiries-by-listing/get-inquiries-by-listing.handler';
import { SanitizeHtmlService } from './application/services/sanitize-html.service';
import { INQUIRY_REPOSITORY } from './domain/repositories/inquiry.repository';
import { PrismaInquiryRepository } from './infrastructure/repositories/prisma-inquiry.repository';
import { InquiriesController } from './presentation/controllers/inquiries.controller';
@@ -20,6 +21,7 @@ const QueryHandlers = [
controllers: [InquiriesController],
providers: [
{ provide: INQUIRY_REPOSITORY, useClass: PrismaInquiryRepository },
SanitizeHtmlService,
...CommandHandlers,
...QueryHandlers,
],