Skip to content

Commit d0406e9

Browse files
committed
refactor: extract reusable sanitizeInput util
expand sanitization matches
1 parent e7a3313 commit d0406e9

File tree

3 files changed

+48
-19
lines changed

3 files changed

+48
-19
lines changed

app/[locale]/enterprise/_components/ContactForm/index.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Spinner } from "@/components/ui/spinner"
99
import { Textarea } from "@/components/ui/textarea"
1010

1111
import { cn } from "@/lib/utils/cn"
12+
import { sanitizeInput } from "@/lib/utils/sanitize"
1213

1314
import { MAX_EMAIL_LENGTH, MAX_MESSAGE_LENGTH } from "../../constants"
1415

@@ -79,15 +80,6 @@ const CONSUMER_DOMAINS = [
7980
"guerrillamail.com",
8081
]
8182

82-
const sanitizeInput = (input: string): string =>
83-
input
84-
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")
85-
.replace(/javascript:/gi, "")
86-
.replace(/on\w+\s*=/gi, "")
87-
.replace(/&lt;script/gi, "")
88-
.replace(/&lt;\/script/gi, "")
89-
.trim()
90-
9183
const EnterpriseContactForm = ({ strings }: EnterpriseContactFormProps) => {
9284
const getCharacterCountClasses = (currentLength: number, maxLength: number) =>
9385
cn(

app/api/enterprise-contact/route.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { NextRequest, NextResponse } from "next/server"
22
import { SendRawEmailCommand, SESClient } from "@aws-sdk/client-ses"
33

4+
import { sanitizeInput } from "@/lib/utils/sanitize"
5+
46
const ENTERPRISE_EMAIL = "[email protected]"
57
const SES_FROM_EMAIL = "[email protected]"
68

@@ -13,16 +15,6 @@ const sesClient = new SESClient({
1315
},
1416
})
1517

16-
function sanitizeInput(input: string): string {
17-
return input
18-
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")
19-
.replace(/javascript:/gi, "")
20-
.replace(/on\w+\s*=/gi, "")
21-
.replace(/&lt;script/gi, "")
22-
.replace(/&lt;\/script/gi, "")
23-
.trim()
24-
}
25-
2618
function validateEmail(email: string): boolean {
2719
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
2820
return emailRegex.test(email)

src/lib/utils/sanitize.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Lightweight sanitizer for user input to prevent XSS attacks
3+
* Specifically designed for plain text content
4+
*
5+
* @param input - The string to sanitize
6+
* @returns Sanitized string with dangerous content removed
7+
*/
8+
export function sanitizeInput(input: string): string {
9+
return (
10+
input
11+
// Remove script tags (any variation)
12+
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")
13+
.replace(
14+
/&lt;script\b[^<]*(?:(?!&lt;\/script&gt;)[^<]*)*&lt;\/script&gt;/gi,
15+
""
16+
)
17+
18+
// Remove iframe tags
19+
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, "")
20+
.replace(
21+
/&lt;iframe\b[^<]*(?:(?!&lt;\/iframe&gt;)[^<]*)*&lt;\/iframe&gt;/gi,
22+
""
23+
)
24+
25+
// Remove object and embed tags
26+
.replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi, "")
27+
.replace(/<embed\b[^<]*(?:(?!\/>)[^<]*)*\/?>/gi, "")
28+
29+
// Remove javascript: protocols
30+
.replace(/javascript:/gi, "")
31+
.replace(/vbscript:/gi, "")
32+
.replace(/data:/gi, "")
33+
34+
// Remove event handlers
35+
.replace(/on\w+\s*=/gi, "")
36+
37+
// Remove any remaining HTML-like tags (aggressive cleanup for plain text)
38+
.replace(/<[^>]*>/g, "")
39+
.replace(/&lt;[^&]*&gt;/g, "")
40+
41+
// Clean up whitespace
42+
.trim()
43+
.replace(/\s+/g, " ")
44+
)
45+
}

0 commit comments

Comments
 (0)