You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
4.8 KiB
Go

package security
// Tests for input sanitization utilities and validation helpers.
import (
"regexp"
"strings"
"testing"
"unicode/utf8"
"github.com/stretchr/testify/require"
)
// TestSanitize_Options ensures sanitize options behavior is handled correctly.
func TestSanitize_Options(t *testing.T) {
opts := SanitizeOptions{
TrimWhitespace: true,
RemoveMultipleSpaces: true,
HTMLEscape: true,
MaxLength: 0,
AllowedPattern: nil,
}
result := Sanitize(" Hello <b>World</b> ", opts)
require.Equal(t, "Hello &lt;b&gt;World&lt;/b&gt;", result)
opts.MaxLength = 5
require.Equal(t, "Hello", Sanitize("Hello World", opts))
opts.AllowedPattern = regexp.MustCompile(`^[a-z]+$`)
require.Equal(t, "", Sanitize("Hello123", opts))
}
// TestSanitizePlayerName ensures sanitize player name behavior is handled correctly.
func TestSanitizePlayerName(t *testing.T) {
require.Equal(t, "Alice Bob", SanitizePlayerName(" Alice Bob "))
require.Equal(t, "", SanitizePlayerName("Alice <"))
}
// TestSanitizeAnswer ensures sanitize answer behavior is handled correctly.
func TestSanitizeAnswer(t *testing.T) {
require.Equal(t, "hello", SanitizeAnswer(" HeLLo "))
}
// TestSanitizeQuestionText ensures sanitize question text behavior is handled correctly.
func TestSanitizeQuestionText(t *testing.T) {
result := SanitizeQuestionText("<script>alert(1)</script> Question")
require.NotContains(t, result, "<script")
}
// TestSanitizeTheme ensures sanitize theme behavior is handled correctly.
func TestSanitizeTheme(t *testing.T) {
require.Equal(t, "Science Fiction", SanitizeTheme(" science fiction "))
}
// TestSanitizeLengthBoundaries ensures sanitize length boundaries behavior is handled correctly.
func TestSanitizeLengthBoundaries(t *testing.T) {
playerExact := strings.Repeat("a", PlayerNameMaxLength)
playerOver := strings.Repeat("a", PlayerNameMaxLength+1)
require.Equal(t, PlayerNameMaxLength, len(SanitizePlayerName(playerExact)))
require.Equal(t, PlayerNameMaxLength, len(SanitizePlayerName(playerOver)))
answerExact := strings.Repeat("x", AnswerMaxLength)
answerOver := strings.Repeat("x", AnswerMaxLength+1)
require.Equal(t, AnswerMaxLength, len(SanitizeAnswer(answerExact)))
require.Equal(t, AnswerMaxLength, len(SanitizeAnswer(answerOver)))
questionExact := strings.Repeat("q", QuestionTextMaxLength)
questionOver := strings.Repeat("q", QuestionTextMaxLength+1)
require.Equal(t, QuestionTextMaxLength, len(SanitizeQuestionText(questionExact)))
require.Equal(t, QuestionTextMaxLength, len(SanitizeQuestionText(questionOver)))
themeExact := strings.Repeat("z", ThemeMaxLength)
themeOver := strings.Repeat("z", ThemeMaxLength+1)
require.Equal(t, ThemeMaxLength, len(SanitizeTheme(themeExact)))
require.Equal(t, ThemeMaxLength, len(SanitizeTheme(themeOver)))
}
// TestRemoveHTMLTags ensures remove html tags behavior is handled correctly.
func TestRemoveHTMLTags(t *testing.T) {
require.Equal(t, "Hi", RemoveHTMLTags("<b>Hi</b>"))
}
// TestContainsDangerousPatterns ensures contains dangerous patterns behavior is handled correctly.
func TestContainsDangerousPatterns(t *testing.T) {
cases := []struct {
name string
input string
expected bool
}{
{name: "javascript", input: "javascript:alert(1)", expected: true},
{name: "mixed_case_javascript", input: "JaVaScRiPt:alert(1)", expected: true},
{name: "data", input: "data:text/html;base64,abc", expected: true},
{name: "vbscript", input: "vbscript:msgbox(1)", expected: true},
{name: "onerror", input: `<img src=x onerror="alert(1)">`, expected: true},
{name: "onload", input: `<body onload="x()">`, expected: true},
{name: "onclick", input: `<a onclick="x()">link</a>`, expected: true},
{name: "onmouseover", input: `<div onmouseover="x()">`, expected: true},
{name: "benign", input: "hello", expected: false},
{name: "benign_near_miss_1", input: "onboarding flow", expected: false},
{name: "benign_near_miss_2", input: "scripture reference", expected: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
require.Equal(t, tc.expected, ContainsDangerousPatterns(tc.input))
})
}
}
// TestIsValidEmail ensures is valid email behavior is handled correctly.
func TestIsValidEmail(t *testing.T) {
require.True(t, IsValidEmail("a@b.com"))
require.False(t, IsValidEmail("bad@"))
}
// TestSanitizeRuneSafeClamping ensures sanitize rune safe clamping behavior is handled correctly.
func TestSanitizeRuneSafeClamping(t *testing.T) {
input := strings.Repeat("é", 5)
opts := SanitizeOptions{
TrimWhitespace: false,
RemoveMultipleSpaces: false,
HTMLEscape: false,
MaxLength: 3,
}
result := Sanitize(input, opts)
require.True(t, utf8.ValidString(result))
require.Equal(t, 3, utf8.RuneCountInString(result))
require.Equal(t, "ééé", result)
}