-
Notifications
You must be signed in to change notification settings - Fork 227
Potential fix for code scanning alert no. 73: Server-side request forgery #672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…gery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Contributor
审核者指南(在小型 PR 上折叠)审核者指南重构
|
| 变更 | 详情 | 文件 |
|---|---|---|
| 在校验之前,使用稳定的变量名对传入的图片 URL 参数进行解码并记录日志。 |
|
src/webui/BE/server.ts |
| 加固 URL 解析和校验,限制向外部发起的请求只能访问特定的 http/https 主机,并避免使用基于子串的检查。 |
|
src/webui/BE/server.ts |
通过 URLSearchParams 安全管理 rkey 查询参数,替代字符串拼接,并在 fetch 中使用重新构造且已验证的 URL。 |
|
src/webui/BE/server.ts |
小贴士与命令
与 Sourcery 交互
- 触发新的审核: 在 Pull Request 中评论
@sourcery-ai review。 - 继续讨论: 直接回复 Sourcery 的审核评论。
- 从审核评论生成 GitHub Issue: 通过回复某条审核评论,请求 Sourcery 从该评论创建一个 Issue。你也可以在评论中回复
@sourcery-ai issue,将其转换为 Issue。 - 生成 Pull Request 标题: 在 Pull Request 标题中任意位置写上
@sourcery-ai,即可随时生成标题。也可以在 Pull Request 中评论@sourcery-ai title来(重新)生成标题。 - 生成 Pull Request 概要: 在 Pull Request 正文任意位置写上
@sourcery-ai summary,即可在该位置生成 PR 概要。也可以在 Pull Request 中评论@sourcery-ai summary来(重新)生成概要。 - 生成审核者指南: 在 Pull Request 中评论
@sourcery-ai guide,可随时(重新)生成审核者指南。 - 解决所有 Sourcery 评论: 在 Pull Request 中评论
@sourcery-ai resolve,将标记所有 Sourcery 评论为已解决。如果你已经处理完所有评论且不希望再看到它们,这会很有用。 - 撤销所有 Sourcery 审核: 在 Pull Request 中评论
@sourcery-ai dismiss,撤销所有现有的 Sourcery 审核。尤其适用于你希望从一次全新的审核开始时——别忘了再评论@sourcery-ai review来触发新的审核!
自定义你的使用体验
访问你的 控制面板 以:
- 启用或禁用审核功能,例如 Sourcery 自动生成的 Pull Request 概要、审核者指南等。
- 更改审核语言。
- 添加、删除或编辑自定义审核指令。
- 调整其他审核设置。
获取帮助
Original review guide in English
Reviewer's guide (collapsed on small PRs)
Reviewer's Guide
Refactors the /api/webqq/image-proxy handler to perform strict URL parsing and validation (scheme and hostname), manipulate query parameters via the URL API, and ensure only a validated, reconstructed URL is used in fetch, mitigating SSRF risk.
Sequence diagram for validated image proxy fetch in /api/webqq/image-proxy
sequenceDiagram
actor User
participant WebUIServer
participant ntFileApi_rkeyManager
participant QQImageHost
User->>WebUIServer: HTTP GET /api/webqq/image-proxy?url=urlParam
WebUIServer->>WebUIServer: decodedUrl = decodeURIComponent(urlParam)
WebUIServer->>WebUIServer: parsedUrl = new URL(decodedUrl)
WebUIServer->>WebUIServer: Validate protocol is http: or https:
WebUIServer->>WebUIServer: Validate hostname in allowedHosts
WebUIServer->>WebUIServer: Check parsedUrl.searchParams.has(rkey)
alt Needs rkey and hostname is multimedia.nt.qq.com.cn or gchat.qpic.cn
WebUIServer->>ntFileApi_rkeyManager: getRkey()
ntFileApi_rkeyManager-->>WebUIServer: rkeyData
WebUIServer->>WebUIServer: Select rkey by appid 1406 or 1407
WebUIServer->>WebUIServer: parsedUrl.searchParams.set(rkey, rkey)
end
WebUIServer->>WebUIServer: finalUrl = parsedUrl.toString()
WebUIServer->>QQImageHost: fetch(finalUrl)
QQImageHost-->>WebUIServer: Image response
WebUIServer-->>User: Proxied image response
Flow diagram for SSRF-safe URL validation in /api/webqq/image-proxy
flowchart TD
A["Start /api/webqq/image-proxy request"] --> B["Decode urlParam to decodedUrl"]
B --> C["Try parse decodedUrl into URL parsedUrl"]
C -->|parse error| R["Return 400 无效的URL"]
C -->|ok| D{"protocol is http: or https:?"}
D -->|no| S["Return 400 不支持的URL协议"]
D -->|yes| E{"hostname in allowedHosts?"}
E -->|no| T["Return 403 不允许代理此域名的图片"]
E -->|yes| F{"parsedUrl.searchParams.has(rkey)?"}
F -->|yes| H["Skip adding rkey"]
F -->|no| G{"hostname is multimedia.nt.qq.com.cn or gchat.qpic.cn?"}
G -->|no| H
G -->|yes| I["appid = parsedUrl.searchParams.get(appid)"]
I --> J{"appid in 1406 or 1407?"}
J -->|no| H
J -->|yes| K["rkeyData = ntFileApi.rkeyManager.getRkey()"]
K --> L{"rkey exists?"}
L -->|no| H
L -->|yes| M["parsedUrl.searchParams.set(rkey, rkey)"]
M --> H
H --> N["finalUrl = parsedUrl.toString()"]
N --> O["fetch(finalUrl) to image host"]
O --> P["Return proxied image response"]
File-Level Changes
| Change | Details | Files |
|---|---|---|
| Decode and log the incoming image URL parameter using a stable variable name before validation. |
|
src/webui/BE/server.ts |
| Harden URL parsing and validation to restrict outbound requests to specific http/https hosts and avoid substring-based checks. |
|
src/webui/BE/server.ts |
| Safely manage the rkey query parameter via URLSearchParams instead of string concatenation, and use the reconstructed, validated URL for fetch. |
|
src/webui/BE/server.ts |
Tips and commands
Interacting with Sourcery
- Trigger a new review: Comment
@sourcery-ai reviewon the pull request. - Continue discussions: Reply directly to Sourcery's review comments.
- Generate a GitHub issue from a review comment: Ask Sourcery to create an
issue from a review comment by replying to it. You can also reply to a
review comment with@sourcery-ai issueto create an issue from it. - Generate a pull request title: Write
@sourcery-aianywhere in the pull
request title to generate a title at any time. You can also comment
@sourcery-ai titleon the pull request to (re-)generate the title at any time. - Generate a pull request summary: Write
@sourcery-ai summaryanywhere in
the pull request body to generate a PR summary at any time exactly where you
want it. You can also comment@sourcery-ai summaryon the pull request to
(re-)generate the summary at any time. - Generate reviewer's guide: Comment
@sourcery-ai guideon the pull
request to (re-)generate the reviewer's guide at any time. - Resolve all Sourcery comments: Comment
@sourcery-ai resolveon the
pull request to resolve all Sourcery comments. Useful if you've already
addressed all the comments and don't want to see them anymore. - Dismiss all Sourcery reviews: Comment
@sourcery-ai dismisson the pull
request to dismiss all existing Sourcery reviews. Especially useful if you
want to start fresh with a new review - don't forget to comment
@sourcery-ai reviewto trigger a new review!
Customizing Your Experience
Access your dashboard to:
- Enable or disable review features such as the Sourcery-generated pull request
summary, the reviewer's guide, and others. - Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.
Getting Help
- Contact our support team for questions or feedback.
- Visit our documentation for detailed guides and information.
- Keep in touch with the Sourcery team by following us on X/Twitter, LinkedIn or GitHub.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Potential fix for https://github.com/LLOneBot/LuckyLilliaBot/security/code-scanning/73
General approach: Ensure that user input cannot arbitrarily control the destination host of the outgoing request. Enforce a strict allow-list on the hostname (using equality rather than substring matching), and also validate the scheme (only
http/https) and optionally the port. All URL construction should be based on the parsedURLobject rather than trusting an arbitrary string.Best concrete fix here:
urlonce into aURLobject.parsedUrl.protocolishttp:orhttps:.parsedUrl.hostnameis exactly one of the allowed hosts (using===).URLobject (so we don’t keep concatenating unparsed strings).rkey, useparsedUrl.searchParamsrather than string concatenation; e.g., set/appendrkeyviaparsedUrl.searchParams.set('rkey', rkey)and then takeparsedUrl.toString()as the final URL.finalUrlinfetch.These changes are all within
src/webui/BE/server.tsin the/api/webqq/image-proxyhandler, around lines 860–895. No new imports are required, sinceURLis already used elsewhere in the file.Suggested fixes powered by Copilot Autofix. Review carefully before merging.
由 Sourcery 提供的总结
通过在获取前严格验证并重建被代理的 URL,加固图像代理端点,防御 SSRF 攻击。
Bug 修复:
功能增强:
rkey的处理),而不是使用字符串拼接。Original summary in English
Summary by Sourcery
Harden the image proxy endpoint against SSRF by strictly validating and rebuilding proxied URLs before fetching.
Bug Fixes:
Enhancements: