-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Validate the user invitation HTML templates (#4835)
* Validate the user invitation HTML templates Signed-off-by: Radoslav Dimitrov <[email protected]> * Add email validation for the authz service Signed-off-by: Radoslav Dimitrov <[email protected]> * Add an additional validation for the template data source Signed-off-by: Radoslav Dimitrov <[email protected]> * Simplify the data template validation Signed-off-by: Radoslav Dimitrov <[email protected]> * Add error handling for getting the generated text body Signed-off-by: Radoslav Dimitrov <[email protected]> * Fix unit tests, remove unnecessary empty string check Signed-off-by: Radoslav Dimitrov <[email protected]> * Add length validation checks and remove duplicated error logs Signed-off-by: Radoslav Dimitrov <[email protected]> * Reformat code and remove email check in favour of upcomming proto validation Signed-off-by: Radoslav Dimitrov <[email protected]> --------- Signed-off-by: Radoslav Dimitrov <[email protected]>
- Loading branch information
Showing
5 changed files
with
312 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
// SPDX-FileCopyrightText: Copyright 2024 The Minder Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package email | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
func TestIsValidField(t *testing.T) { | ||
t.Parallel() | ||
|
||
tests := []struct { | ||
input string | ||
expectedErrMsg string | ||
}{ | ||
// Test case 1: Valid plain text | ||
{"Just plain text", ""}, | ||
|
||
// Test case 2: String with HTML tags | ||
{"<b>Bold Text</b>", "string <b>Bold Text</b> contains HTML injection"}, | ||
|
||
// Test case 3: String with HTML entity | ||
{"This is a test & example.", "string This is a test & example. contains HTML injection"}, | ||
|
||
// Test case 4: String with multiple HTML entities | ||
{"This & that < should > work.", "string This & that < should > work. contains HTML injection"}, | ||
|
||
// Test case 5: Valid URL (no HTML or JavaScript injection) | ||
{"https://example.com", ""}, | ||
|
||
// Test case 6: Mixed content with HTML and JS | ||
{"Hello <b>World</b> onload=alert('test');", "string Hello <b>World</b> onload=alert('test'); contains HTML injection"}, | ||
|
||
// Test case 7: HTML-style comment | ||
{"<!-- This is a comment -->", "string <!-- This is a comment --> contains HTML injection"}, | ||
|
||
// Test case 8: ensure allowed length is less than 200 characters | ||
{strings.Repeat("a", MaxFieldLength+1), fmt.Sprintf("field value %s is more than %d characters", strings.Repeat("a", MaxFieldLength+1), MaxFieldLength)}, | ||
} | ||
|
||
for _, tt := range tests { | ||
tt := tt // capture range variable for parallel execution | ||
t.Run(tt.input, func(t *testing.T) { | ||
t.Parallel() | ||
err := isValidField(tt.input) | ||
if err != nil && err.Error() != tt.expectedErrMsg { | ||
t.Errorf("isValidField(%q) got error message: %v, expected message: %v", tt.input, err.Error(), tt.expectedErrMsg) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestValidateDataSourceTemplate(t *testing.T) { | ||
t.Parallel() | ||
|
||
tests := []struct { | ||
input bodyData | ||
expectedErrMsg string | ||
}{ | ||
// Test case 1: All fields are valid plain text | ||
{ | ||
bodyData{ | ||
AdminName: "John Doe", | ||
OrganizationName: "Acme Corp", | ||
InvitationURL: "https://invitation.com", | ||
RecipientEmail: "[email protected]", | ||
MinderURL: "https://minder.com", | ||
TermsURL: "https://terms.com", | ||
PrivacyURL: "https://privacy.com", | ||
SignInURL: "https://signin.com", | ||
RoleName: "Administrator", | ||
RoleVerb: "manage", | ||
}, | ||
"", | ||
}, | ||
|
||
// Test case 2: AdminName contains HTML tags | ||
{ | ||
bodyData{ | ||
AdminName: "John <b>Doe</b>", | ||
OrganizationName: "Acme Corp", | ||
InvitationURL: "https://invitation.com", | ||
RecipientEmail: "[email protected]", | ||
MinderURL: "https://minder.com", | ||
TermsURL: "https://terms.com", | ||
PrivacyURL: "https://privacy.com", | ||
SignInURL: "https://signin.com", | ||
RoleName: "Administrator", | ||
RoleVerb: "manage", | ||
}, | ||
"field AdminName failed validation - John <b>Doe</b>", | ||
}, | ||
|
||
// Test case 3: OrganizationName contains HTML content | ||
{ | ||
bodyData{ | ||
AdminName: "John Doe", | ||
OrganizationName: "<script>alert('Hack');</script>", | ||
InvitationURL: "https://invitation.com", | ||
RecipientEmail: "[email protected]", | ||
MinderURL: "https://minder.com", | ||
TermsURL: "https://terms.com", | ||
PrivacyURL: "https://privacy.com", | ||
SignInURL: "https://signin.com", | ||
RoleName: "Administrator", | ||
RoleVerb: "manage", | ||
}, | ||
"field OrganizationName failed validation - <script>alert('Hack');</script>", | ||
}, | ||
|
||
// Test case 4: AdminName contains JavaScript code | ||
{ | ||
bodyData{ | ||
AdminName: "onload=alert('test')", | ||
OrganizationName: "Acme Corp", | ||
InvitationURL: "https://invitation.com", | ||
RecipientEmail: "[email protected]", | ||
MinderURL: "https://minder.com", | ||
TermsURL: "https://terms.com", | ||
PrivacyURL: "https://privacy.com", | ||
SignInURL: "https://signin.com", | ||
RoleName: "Administrator", | ||
RoleVerb: "manage", | ||
}, | ||
"field AdminName failed validation - onload=alert('test')", | ||
}, | ||
|
||
// Test case 5: All fields contain valid plain text with some URLs | ||
{ | ||
bodyData{ | ||
AdminName: "Plain Text User", | ||
OrganizationName: "No HTML Corp", | ||
InvitationURL: "https://example.com", | ||
RecipientEmail: "[email protected]", | ||
MinderURL: "https://example.com/minder", | ||
TermsURL: "https://example.com/terms", | ||
PrivacyURL: "https://example.com/privacy", | ||
SignInURL: "https://example.com/signin", | ||
RoleName: "User", | ||
RoleVerb: "view", | ||
}, | ||
"", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
tt := tt // capture range variable for parallel execution | ||
t.Run(tt.input.AdminName, func(t *testing.T) { | ||
t.Parallel() | ||
err := tt.input.Validate() | ||
if err != nil && err.Error() != tt.expectedErrMsg { | ||
t.Errorf("validateDataSourceTemplate(%+v) got error message: %v, expected message: %v", tt.input, err.Error(), tt.expectedErrMsg) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.