Merge pull request #19277 from resilient-tech/refactor-sanitize_searchfield
fix: use stricter regex for `sanitize_searchfield`
This commit is contained in:
commit
c0e5408659
2 changed files with 22 additions and 32 deletions
|
|
@ -7,45 +7,18 @@ import re
|
|||
|
||||
import frappe
|
||||
from frappe import _, is_whitelisted
|
||||
from frappe.database.schema import SPECIAL_CHAR_PATTERN
|
||||
from frappe.permissions import has_permission
|
||||
from frappe.utils import cint, cstr, unique
|
||||
|
||||
|
||||
def sanitize_searchfield(searchfield):
|
||||
blacklisted_keywords = ["select", "delete", "drop", "update", "case", "and", "or", "like"]
|
||||
if not searchfield:
|
||||
return
|
||||
|
||||
def _raise_exception(searchfield):
|
||||
if SPECIAL_CHAR_PATTERN.search(searchfield):
|
||||
frappe.throw(_("Invalid Search Field {0}").format(searchfield), frappe.DataError)
|
||||
|
||||
if len(searchfield) == 1:
|
||||
# do not allow special characters to pass as searchfields
|
||||
regex = re.compile(r'^.*[=;*,\'"$\-+%#@()_].*')
|
||||
if regex.match(searchfield):
|
||||
_raise_exception(searchfield)
|
||||
|
||||
if len(searchfield) >= 3:
|
||||
|
||||
# to avoid 1=1
|
||||
if "=" in searchfield:
|
||||
_raise_exception(searchfield)
|
||||
|
||||
# in mysql -- is used for commenting the query
|
||||
elif " --" in searchfield:
|
||||
_raise_exception(searchfield)
|
||||
|
||||
# to avoid and, or and like
|
||||
elif any(f" {keyword} " in searchfield.split() for keyword in blacklisted_keywords):
|
||||
_raise_exception(searchfield)
|
||||
|
||||
# to avoid select, delete, drop, update and case
|
||||
elif any(keyword in searchfield.split() for keyword in blacklisted_keywords):
|
||||
_raise_exception(searchfield)
|
||||
|
||||
else:
|
||||
regex = re.compile(r'^.*[=;*,\'"$\-+%#@()].*')
|
||||
if any(regex.match(f) for f in searchfield.split()):
|
||||
_raise_exception(searchfield)
|
||||
|
||||
|
||||
# this is called by the Link Field
|
||||
@frappe.whitelist()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: MIT. See LICENSE
|
||||
|
||||
import re
|
||||
|
||||
import frappe
|
||||
from frappe.app import make_form_dict
|
||||
from frappe.desk.search import get_names_for_mentions, search_link, search_widget
|
||||
from frappe.desk.search import (
|
||||
get_names_for_mentions,
|
||||
sanitize_searchfield,
|
||||
search_link,
|
||||
search_widget,
|
||||
)
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
from frappe.utils import set_request
|
||||
from frappe.website.serve import get_response
|
||||
|
|
@ -179,6 +185,17 @@ class TestSearch(FrappeTestCase):
|
|||
search_link("User", "user@random", searchfield="name")
|
||||
self.assertListEqual(frappe.response["results"], [])
|
||||
|
||||
def test_sanitize_searchfield(self):
|
||||
for searchfield in ("1=1", "name or (select * from tabSessions)", ";", "`tabSessions`"):
|
||||
self.assertRaisesRegex(
|
||||
frappe.DataError,
|
||||
re.compile(r"^(Invalid Search Field .*)$"),
|
||||
sanitize_searchfield,
|
||||
searchfield,
|
||||
)
|
||||
|
||||
sanitize_searchfield("name")
|
||||
|
||||
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_data(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue