quoteable.site comping soon! Keep an eye out for great new things

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;
    }