fix: cap search keywords and query results to prevent CWE-407 amplification
- list_nodes.py: strip empty tokens, cap keywords to 10 before passing to model - node.py: add .limit(200) per keyword query — was unbounded .all() - namespace.py: add .limit(500) on root.children in dict_dump — was unbounded iteration - __init__.py: cap page_number to 1000 — large offsets force full table scans
This commit is contained in:
parent
2061097e13
commit
c87fb0bd1f
4 changed files with 11 additions and 5 deletions
|
|
@ -512,6 +512,8 @@ def main(global_config, **settings):
|
|||
def add_page_number(request):
|
||||
"""Attach page_number starting at 0"""
|
||||
page_number = int(request.params.get("page", 1))
|
||||
# Cap to prevent OFFSET DoS — large offsets force full table scans (CWE-407).
|
||||
page_number = min(page_number, 1000)
|
||||
return page_number if page_number >= 1 else 1
|
||||
|
||||
def add_page_size(request):
|
||||
|
|
|
|||
|
|
@ -437,8 +437,9 @@ class Namespace(RBase, Base):
|
|||
# TODO: fix when root.created becomes root.created_timestamp.
|
||||
"timestamp" : root.created,
|
||||
}
|
||||
comments = []
|
||||
for node in root.children:
|
||||
comments = []
|
||||
# Limit children per root to prevent unbounded JSON serialization (CWE-407).
|
||||
for node in root.children.limit(500):
|
||||
comment = {
|
||||
"date" : node.created_date,
|
||||
# TODO: when root.created becomes root.created_timestamp.
|
||||
|
|
|
|||
|
|
@ -514,9 +514,10 @@ def get_root_nodes_by_keywords(dbsession, keywords, namespace=None):
|
|||
|
||||
for keyword in keywords:
|
||||
|
||||
# extend nodes, with a list of nodes which match this keyword.
|
||||
# extend nodes, with a list of nodes which match this keyword.
|
||||
# Limit per-keyword results to prevent memory exhaustion (CWE-407).
|
||||
keyword_filter = Node.data.ilike("%{}%".format(keyword))
|
||||
nodes.extend(node_query.filter(keyword_filter).all())
|
||||
nodes.extend(node_query.filter(keyword_filter).limit(200).all())
|
||||
|
||||
# accumulate scores and root node objects.
|
||||
for node in nodes:
|
||||
|
|
|
|||
|
|
@ -146,9 +146,11 @@ def search(request):
|
|||
return HTTPFound(get_referer_or_home(request))
|
||||
|
||||
# Note: a search from topsecret page does not pass a namespace.
|
||||
# Cap keywords to prevent O(k*n) amplification (CWE-407).
|
||||
keyword_list = [k for k in keywords.split(" ") if k][:10]
|
||||
nodes = get_root_nodes_by_keywords(
|
||||
request.dbsession,
|
||||
keywords.split(" "),
|
||||
keyword_list,
|
||||
request.namespace
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue