Click here for the beta site.
private static final int XSS_THRESHOLD = 3;
private static final Pattern XSS_EVENT_PATTERN = Pattern.compile(
"onbeforeprint|onbeforeunload|onblur|onchange|onclick|oncontextmenu|" +
"oncopy|oncut|ondblclick|ondrag|ondragend|ondragenter|ondragleave|" +
"ondragover|ondragstart|ondrop|onerror|onfocus|onhashchange|oninput|" +
"oninvalid|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|" +
"onmouseout|onmouseover|onmouseup|onoffline|ononline|onpageshow|onpaste|" +
"onreset|onresize|onscroll|onsearch|onselect|onsubmit|onunload|onwheel",
Pattern.CASE_INSENSITIVE
);
private static final Pattern XSS_CHARACTER_PATTERN = Pattern.compile("[<=>{}\\x22]");
// Global counter accumulating detections across all fields
private static int globalDetectionCount = 0;
// Count JS event keyword occurrences and add to global count (keywords are never removed)
private static void detectEventPatterns(String fieldName, String value) {
Matcher m = XSS_EVENT_PATTERN.matcher(value);
int count = 0;
while (m.find()) count++;
if (count > 0) {
globalDetectionCount += count;
logger.info(String.format("Field [%s]: detected %d JS event keyword(s) in value: \"%s\"", fieldName, count, value));
}
}
// Count special character occurrences, add to global count, and return the stripped value
private static String detectAndStripCharacterPatterns(String fieldName, String value) {
Matcher m = XSS_CHARACTER_PATTERN.matcher(value);
int count = 0;
while (m.find()) count++;
if (count > 0) {
globalDetectionCount += count;
logger.info(String.format("Field [%s]: stripping %d special char(s) from original value: \"%s\"", fieldName, count, value));
value = XSS_CHARACTER_PATTERN.matcher(value).replaceAll("");
}
return value;
}
public static HashMap validateAndSanitize(HashMap inputMap) {
if (inputMap == null) return new HashMap<>();
globalDetectionCount = 0;
HashMap result = new HashMap<>();
HashSet flagged = new HashSet<>();
// --- First pass: run both detection functions per field ---
for (Map.Entry entry : inputMap.entrySet()) {
String key = entry.getKey();
String val = entry.getValue();
int before = globalDetectionCount;
if (val == null || val.isEmpty()) {
result.put(key, val);
continue;
}
detectEventPatterns(key, val);
val = detectAndStripCharacterPatterns(key, val);
if (globalDetectionCount > before) flagged.add(key);
result.put(key, val);
}
logger.info(String.format("Global detection total across all fields: %d", globalDetectionCount));
// --- Second pass: prepend XSS! to flagged fields if global total exceeds threshold ---
if (globalDetectionCount > XSS_THRESHOLD) {
for (String key : flagged) {
result.put(key, "XSS!" + result.get(key));
logger.warning(String.format("Field [%s] flagged: \"%s\"", key, result.get(key)));
}
}
return result;
}