Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-13404-fixed-1771343065083.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Fixed
---

Fix html injection vuln in open Support Ticket and Quotas Increase Form ([#13404](https://github.com/linode/manager/pull/13404))
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as React from 'react';
import { Controller, FormProvider, useForm } from 'react-hook-form';

import { Markdown } from 'src/components/Markdown/Markdown';
import { SUPPORT_TICKET_SANITIZE_OPTIONS } from 'src/features/Support/sanitizeOptions';

import { getQuotaIncreaseFormSchema, getQuotaIncreaseMessage } from './utils';

Expand Down Expand Up @@ -254,7 +255,10 @@ export const QuotasIncreaseForm = (props: QuotasIncreaseFormProps) => {
{summary}
</Typography>
<Markdown textOrMarkdown={quotaIncreaseDescription} />{' '}
<Markdown textOrMarkdown={notes ?? ''} />
<Markdown
sanitizeOptions={SUPPORT_TICKET_SANITIZE_OPTIONS}
textOrMarkdown={notes ?? ''}
/>
</Stack>
</Accordion>
<ActionsPanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { makeStyles } from 'tss-react/mui';

import { Markdown } from 'src/components/Markdown/Markdown';

import { SUPPORT_TICKET_SANITIZE_OPTIONS } from './sanitizeOptions';

import type { Theme } from '@mui/material/styles';

const useStyles = makeStyles()((theme: Theme) => ({
Expand Down Expand Up @@ -52,7 +54,10 @@ export const TicketDetailText = (props: Props) => {
return (
<Grid className={classes.root} container spacing={2}>
<Grid style={{ width: '100%' }}>
<Markdown textOrMarkdown={ticketReplyBody} />
<Markdown
sanitizeOptions={SUPPORT_TICKET_SANITIZE_OPTIONS}
textOrMarkdown={ticketReplyBody}
/>
</Grid>
{truncatedText !== text && (
<IconButton
Expand Down
61 changes: 61 additions & 0 deletions packages/manager/src/features/Support/sanitizeOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { SanitizeOptions } from 'src/utilities/sanitizeHTML';

/**
* Centralized sanitization configuration for support ticket content
*
* This configuration is used when rendering user-submitted support ticket descriptions
* and replies via the Markdown component. It allows safe Markdown formatting while
* blocking dangerous HTML that could be used for phishing attacks.
*
* Security Policy:
* - Allows: Bold, italic, lists, code blocks, headers, tables, etc. (safe formatting)
* - Blocks: <a> tags and other potentially dangerous HTML elements
* - Preserves: Text content when removing disallowed tags
*
* Rationale:
* - Users expect Markdown formatting support for better readability
* - Links are blocked to prevent phishing/social engineering attacks
* - Sanitization happens at render time (not on submit) to preserve original content
*/
export const SUPPORT_TICKET_SANITIZE_OPTIONS: SanitizeOptions = {
ALLOWED_TAGS: [
// Text formatting
'strong',
'b',
'em',
'i',
'u',
'del',
's',
// Code blocks
'code',
'pre',
'span',
// Lists
'ul',
'ol',
'li',
// Structure
'p',
'br',
'hr',
'blockquote',
// Headers
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
// Tables
'table',
'thead',
'tbody',
'tr',
'th',
'td',
// NO <a> tags - links are blocked to prevent phishing
],
ALLOWED_ATTR: ['class', 'style'], // Only for syntax highlighting in code blocks
KEEP_CONTENT: true, // Preserve text when removing disallowed tags
};