find_node_by_name endpoint does not enforce MAX_ITEMS_PER_PAGE, allowing unbounded pagination queries`

Aperta Adatta ai principianti
#1,149 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@Jeffy123-zhu ci sta già lavorando.

Dal 17/10/2026.

  • #1150 di @vishalmore90 — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
88/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
api, backend

Direzione di ricerca

Inizia da application/web/web_main.py, dove find_node_by_name legge items_per_page da request.args (intorno alla riga 261) e lo passa a database.get_nodes_with_pagination (intorno alla riga 272). Confronta con il gestore all_cres, che limita il valore con min(per_page, MAX_ITEMS_PER_PAGE) vicino alla riga 1538. Aggiungi lo stesso limite, poi un test di regressione accanto a test_find_node_by_name in application/tests/web_main_test.py. È completato quando una richiesta con un items_per_page elevato restituisce al massimo MAX_ITEMS_PER_PAGE risultati.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

What is the issue?

MAX_ITEMS_PER_PAGE (value: 100) is defined in
application/web/web_main.py line 57
but is never enforced on the find_node_by_name endpoint
(GET /rest/v1/<ntype>/<name> and all its route aliases).

The endpoint reads items_per_page directly from the query-string and passes
the raw integer to database.get_nodes_with_pagination() with no upper-bound
check:

# web_main.py  line 261
items_per_page = request.args.get("items_per_page") or ITEMS_PER_PAGE

# …passed straight in at line 272 with no min/max guard:
total_pages, nodes, _ = database.get_nodes_with_pagination(
    …
    items_per_page=int(items_per_page),
    …
)

By contrast, the all_cres endpoint correctly caps the value:

# web_main.py  line 1538
per_page = min(per_page, MAX_ITEMS_PER_PAGE)

find_node_by_name is the primary browsing API used by the SPA for every
standard/tool/code lookup. A caller can request an arbitrarily large page
(e.g. ?items_per_page=999999), causing the ORM to execute an unbounded
SELECT … LIMIT 999999 OFFSET … against the SQLite/Postgres database.


Expected Behaviour

GET /rest/v1/standard/OWASP%20Top%2010?items_per_page=999999 should behave
identically to ?items_per_page=100 — returning at most MAX_ITEMS_PER_PAGE
results, with total_pages calculated accordingly.


Actual Behaviour

The server honours any positive integer for items_per_page and issues an
unbounded paginate query. For large enough values (or on databases with many
sections per standard) this can:

  1. Degrade server response time — the ORM materialises the full result set
    into Python objects before serialising to JSON.
  2. Cause excessive memory pressure — every matched Node + all its Links
    are loaded into memory.
  3. Allow resource-exhaustion abuse — any unauthenticated caller can trigger
    it, because find_node_by_name requires no auth.

Steps to reproduce
  1. Start a local instance with a populated database (e.g. make dev after
    make import-all).
  2. Run:
    curl -s "http://127.0.0.1:5000/rest/v1/standard/OWASP%20Top%2010?items_per_page=100000" | python -m json.tool | head -5
    
  3. Observe: the server responds with all matching rows without any limit error.

Alternatively, confirm in code:

  • web_main.py L57: MAX_ITEMS_PER_PAGE = 100 (defined but unused on this route)
  • web_main.py L261: items_per_page = request.args.get("items_per_page") or ITEMS_PER_PAGE (no cap applied)
  • web_main.py L272: items_per_page=int(items_per_page) (raw value forwarded to DB)
  • Compare with web_main.py L1538: per_page = min(per_page, MAX_ITEMS_PER_PAGE) (correct guard on all_cres)

Proposed Fix

In find_node_by_name, apply the same guard used by all_cres:

# web_main.py  ~line 261
items_per_page = int(request.args.get("items_per_page") or ITEMS_PER_PAGE)
items_per_page = min(items_per_page, MAX_ITEMS_PER_PAGE)   # ← add this line

A regression test should be added alongside test_find_node_by_name in
application/tests/web_main_test.py (currently only all_cres has a test
for this cap — see line 1523).

Lingua principale
Python
Stelle
210
Fork
167
Merge medio
4g 12h
PR unite (30g)
28

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di OWASP/OpenCRE

Tutte le issue di OWASP/OpenCRE

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.