find_node_by_name endpoint does not enforce MAX_ITEMS_PER_PAGE, allowing unbounded pagination queries`
维护者通常 1 天内回复
评估
调研方向
从 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 小时
- 30 天内合并 PR
- 28
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 提供 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
OWASP/OpenCRE 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
Map Analysis continues polling after a background job fails可能已有人在做 @amantebriwal4321 于 4 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 84/100
维护者通常 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
维护者通常 1 天内回复
-
Information disclosure via filesystem existence oracle in web_main.py catch-all route可能已有人在做 @0x5t4l1n 于 39 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 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 天内回复