Files
stack/apps/api/src/federation/dto/command.dto.ts
Jason Woltje 01639fff95 feat(#285): Add input sanitization for XSS prevention
Security improvements:
- Create sanitization utility using sanitize-html library
- Add @Sanitize() and @SanitizeObject() decorators for DTOs
- Apply sanitization to vulnerable fields:
  - Connection rejection/disconnection reasons
  - Connection metadata
  - Identity linking metadata
  - Command payloads
- Remove script tags, event handlers, javascript: URLs
- Prevent data exfiltration, CSS-based XSS, SVG-based XSS

Changes:
- Add sanitize.util.ts with recursive sanitization functions
- Add sanitize.decorator.ts for class-transformer integration
- Update connection.dto.ts with sanitization decorators
- Update identity-linking.dto.ts with sanitization decorators
- Update command.dto.ts with sanitization decorators
- Add comprehensive test coverage including attack vectors

Part of M7.1 Remediation Sprint P1 security fixes.

Fixes #285

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 21:47:32 -06:00

58 lines
1.0 KiB
TypeScript

/**
* Command DTOs
*
* Data Transfer Objects for command message operations.
*/
import { IsString, IsObject, IsNotEmpty, IsNumber } from "class-validator";
import type { CommandMessage } from "../types/message.types";
import { SanitizeObject } from "../../common/decorators/sanitize.decorator";
/**
* DTO for sending a command to a remote instance
*/
export class SendCommandDto {
@IsString()
@IsNotEmpty()
connectionId!: string;
@IsString()
@IsNotEmpty()
commandType!: string;
@IsObject()
@IsNotEmpty()
@SanitizeObject()
payload!: Record<string, unknown>;
}
/**
* DTO for incoming command request from remote instance
*/
export class IncomingCommandDto implements CommandMessage {
@IsString()
@IsNotEmpty()
messageId!: string;
@IsString()
@IsNotEmpty()
instanceId!: string;
@IsString()
@IsNotEmpty()
commandType!: string;
@IsObject()
@IsNotEmpty()
@SanitizeObject()
payload!: Record<string, unknown>;
@IsNumber()
@IsNotEmpty()
timestamp!: number;
@IsString()
@IsNotEmpty()
signature!: string;
}