@@ -20,6 +20,7 @@ import { debounce } from 'throttle-debounce';
2020
2121import { sendSupportTicketExitEvent } from 'src/utilities/analytics/customEventAnalytics' ;
2222import { getErrorStringOrDefault } from 'src/utilities/errorUtils' ;
23+ import { sanitizeHTML } from 'src/utilities/sanitizeHTML' ;
2324import { storage , supportTicketStorageDefaults } from 'src/utilities/storage' ;
2425
2526import { AttachFileForm } from '../AttachFileForm' ;
@@ -139,6 +140,30 @@ export const getInitialValue = (
139140 return fromProps ?? fromStorage ?? '' ;
140141} ;
141142
143+ /**
144+ * Sanitizes user input to prevent HTML injection attacks
145+ * Uses the centralized sanitizeHTML utility with strict settings
146+ *
147+ * @param input - The user input string to sanitize
148+ * @returns Sanitized plain text string with all HTML removed
149+ */
150+ const sanitizeInput = ( input : string ) : string => {
151+ if ( ! input ) return '' ;
152+
153+ // Use strict sanitization: no HTML tags allowed
154+ const sanitized = sanitizeHTML ( {
155+ sanitizingTier : 'strict' ,
156+ text : input ,
157+ sanitizeOptions : {
158+ ALLOWED_TAGS : [ ] , // Strip all HTML tags
159+ ALLOWED_ATTR : [ ] , // Strip all attributes
160+ KEEP_CONTENT : true , // Keep text content
161+ } ,
162+ } ) ;
163+
164+ return sanitized ;
165+ } ;
166+
142167export const SupportTicketDialog = ( props : SupportTicketDialogProps ) => {
143168 const {
144169 open,
@@ -349,13 +374,22 @@ export const SupportTicketDialog = (props: SupportTicketDialogProps) => {
349374 const handleSubmit = form . handleSubmit ( async ( values ) => {
350375 const { onSuccess } = props ;
351376
352- const _description = formatDescription ( values , ticketType ) ;
377+ // Sanitize all string fields to prevent HTML injection
378+ const sanitizedValues = Object . fromEntries (
379+ Object . entries ( values ) . map ( ( [ key , value ] ) => [
380+ key ,
381+ typeof value === 'string' ? sanitizeInput ( value ) : value ,
382+ ] )
383+ ) as typeof values ;
384+
385+ const _description = formatDescription ( sanitizedValues , ticketType ) ;
353386
354387 // If this is an account limit ticket, we needed the entity type but won't actually send a valid entity selection.
355388 // Reset the entity type and id back to defaults.
356389 const _entityType =
357- ticketType === 'accountLimit' ? 'general' : values . entityType ;
358- const _entityId = ticketType === 'accountLimit' ? '' : values . entityId ;
390+ ticketType === 'accountLimit' ? 'general' : sanitizedValues . entityType ;
391+ const _entityId =
392+ ticketType === 'accountLimit' ? '' : sanitizedValues . entityId ;
359393
360394 if ( ! [ 'general' , 'none' ] . includes ( _entityType ) && ! _entityId ) {
361395 form . setError ( 'entityId' , {
@@ -369,12 +403,12 @@ export const SupportTicketDialog = (props: SupportTicketDialogProps) => {
369403 const baseRequestPayload = {
370404 description : _description ,
371405 severity : selectedSeverity ,
372- summary,
406+ summary : sanitizedValues . summary ,
373407 } ;
374408
375409 let requestPayload ;
376410 if ( entityType === 'bucket' ) {
377- const bucketLabel = values . entityInputValue ;
411+ const bucketLabel = sanitizedValues . entityInputValue ;
378412 requestPayload = {
379413 bucket : bucketLabel ,
380414 region : _entityId ,
0 commit comments