* [FIX] login xss * [FIX] Client Side Sanitization * moved from frappe to frappe.utils * added strategies * removed console.log * fixed codacy * XSS sanitization at login * moved to common js - xss_sanitizeversion-14
@@ -255,3 +255,36 @@ frappe.is_mobile = function() { | |||||
return $(document).width() < 768; | return $(document).width() < 768; | ||||
} | } | ||||
frappe.utils.xss_sanitise = function (string, options) { | |||||
// Reference - https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet | |||||
let sanitised = string; // un-sanitised string. | |||||
const DEFAULT_OPTIONS = { | |||||
strategies: ['html', 'js'] // use all strategies. | |||||
} | |||||
const HTML_ESCAPE_MAP = { | |||||
'&': '&', | |||||
'<': '<', | |||||
'>': '>', | |||||
'"': '"', | |||||
"'": ''', | |||||
'/': '/' | |||||
}; | |||||
const REGEX_SCRIPT = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi; // used in jQuery 1.7.2 src/ajax.js Line 14 | |||||
options = Object.assign({ }, DEFAULT_OPTIONS, options); // don't deep copy, immutable beauty. | |||||
// Rule 1 | |||||
if ( options.strategies.includes('html') ) { | |||||
// By far, the best thing that has ever happened to JS - Object.keys | |||||
Object.keys(HTML_ESCAPE_MAP).map((char, escape) => { | |||||
const regex = new RegExp(char, "g"); | |||||
sanitised = sanitised.replace(regex, escape); | |||||
}); | |||||
} | |||||
// Rule 3 - TODO: Check event handlers? | |||||
if ( options.strategies.includes('js') ) { | |||||
sanitised = sanitised.replace(REGEX_SCRIPT, ""); | |||||
} | |||||
return sanitised; | |||||
} |
@@ -17,8 +17,8 @@ login.bind_events = function() { | |||||
event.preventDefault(); | event.preventDefault(); | ||||
var args = {}; | var args = {}; | ||||
args.cmd = "login"; | args.cmd = "login"; | ||||
args.usr = ($("#login_email").val() || "").trim(); | |||||
args.pwd = $("#login_password").val(); | |||||
args.usr = frappe.utils.xss_sanitise(($("#login_email").val() || "").trim()); | |||||
args.pwd = frappe.utils.xss_sanitise($("#login_password").val()); | |||||
args.device = "desktop"; | args.device = "desktop"; | ||||
if(!args.usr || !args.pwd) { | if(!args.usr || !args.pwd) { | ||||
frappe.msgprint("{{ _("Both login and password required") }}"); | frappe.msgprint("{{ _("Both login and password required") }}"); | ||||
@@ -185,6 +185,7 @@ $.extend(frappe, { | |||||
if($.isArray(html)) { | if($.isArray(html)) { | ||||
html = html.join("<hr>") | html = html.join("<hr>") | ||||
} | } | ||||
return frappe.get_modal(title || "Message", html).modal("show"); | return frappe.get_modal(title || "Message", html).modal("show"); | ||||
}, | }, | ||||
send_message: function(opts, btn) { | send_message: function(opts, btn) { | ||||