find_node_by_name endpoint does not enforce MAX_ITEMS_PER_PAGE, allowing unbounded pagination queries`
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 88/100
調査の方向性
application/web/web_main.py から始めてください。find_node_by_name は request.args から items_per_page を読み取り (261 行目付近)、database.get_nodes_with_pagination に渡しています (272 行目付近)。all_cres ハンドラと比較してください。こちらは 1538 行目付近で min(per_page, MAX_ITEMS_PER_PAGE) を使って値を上限で制限しています。同じ上限を追加し、application/tests/web_main_test.py の test_find_node_by_name の隣に回帰テストを追加してください。items_per_page が大きい値のリクエストで、結果が最大 MAX_ITEMS_PER_PAGE 件に収まれば完了です。
索引モデルが issue の本文から書いたものです。
説明
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:
- Degrade server response time — the ORM materialises the full result set
into Python objects before serialising to JSON. - Cause excessive memory pressure — every matched
Node+ all itsLinks
are loaded into memory. - Allow resource-exhaustion abuse — any unauthenticated caller can trigger
it, becausefind_node_by_namerequires no auth.
Steps to reproduce
- Start a local instance with a populated database (e.g.
make devafter
make import-all). - 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 - Observe: the server responds with all matching rows without any limit error.
Alternatively, confirm in code:
web_main.pyL57:MAX_ITEMS_PER_PAGE = 100(defined but unused on this route)web_main.pyL261:items_per_page = request.args.get("items_per_page") or ITEMS_PER_PAGE(no cap applied)web_main.pyL272:items_per_page=int(items_per_page)(raw value forwarded to DB)- Compare with
web_main.pyL1538:per_page = min(per_page, MAX_ITEMS_PER_PAGE)(correct guard onall_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).
- 主要言語
- Python
- スター
- 210
- フォーク
- 167
- 平均マージ
- 4日 12時間
- マージ済み PR(30日)
- 28
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
OWASP/OpenCRE のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
OWASP/OpenCRE#1215 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Map Analysis continues polling after a background job fails対応中かも @amantebriwal4321 が 4 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
OWASP/OpenCRE#1211 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 66/100
メンテナーはふだん 1 日以内に返信
-
MCP tools return "Internal MCP tool error." when OpenCRE is unreachable or times out対応中かも @ShaanGS が 23 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
OWASP/OpenCRE#1163 · コメント 5 件 ·
メンテナーはふだん 1 日以内に返信
-
Information disclosure via filesystem existence oracle in web_main.py catch-all route対応中かも @0x5t4l1n が 39 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
OWASP/OpenCRE#1112 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
似ている issue
-
Unknown stop ID in slow zone data crashes post formatting and skips the rest of that day's postsオープンbackend bug tm-new-volunteer
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
transitmatters/mbta-slow-zone-bot#81 · コメント 1 件 ·
-
area:schema documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
risk:high type:ci
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 64/100
spacetelescope/rdmt-spire#49 ·
メンテナーはふだん 1 日以内に返信