storage: V4 getSignedUrl sorts canonical headers with localeCompare, so they disagree with X-Goog-SignedHeaders

未关闭 适合新手
#9,840 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@itsrayeedscodespace 已经在做这个了。

开始于 2026年11月8日。

  • #9841 来自 @itsrayeedscodespace —— 未关闭

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
82/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
领域
backend, security

调研方向

从 handwritten/storage/src/signer.ts 中的 URLSigner.getCanonicalHeaders 开始,将其 header 排序与 signedHeaders 使用的普通 .sort() 进行比较。检查 storage signer 的测试是否覆盖包含 - 和 _ 的 header 名称,以及受 locale 影响的排序。完成标准是 canonical headers 块遵循 code point 顺序,并与 signed headers 列表一致。

由索引模型根据 Issue 内容生成。

描述

api: storage
Please make sure you have searched for information in the following guides.
Library Name

@google-cloud/storage

A screenshot that you have tested with "Try this API".

Not applicable: V4 URL signing happens entirely in the client library; no API call is involved.

Link to the code that reproduces this issue. A link to a public Github Repository or gist with a minimal reproduction.

https://gist.github.com/trackoor/dc977f474cf9a692628c158959bbef2c

A step-by-step description of how to reproduce the issue, based on the linked reproduction.
  1. npm install (installs @google-cloud/storage 8.4.0), Node.js v26.13.0 (full ICU), Linux.
  2. node index.js prints the canonical request that gets signed, for extensionHeaders: {"x-goog-meta-a_b": "1", "x-goog-meta-a-b": "2"}:
GET
/test-bucket/test-object
X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test%40example.iam.gserviceaccount.com%2F20261107%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20261107T105715Z&X-Goog-Expires=60&X-Goog-SignedHeaders=host%3Bx-goog-meta-a-b%3Bx-goog-meta-a_b
host:storage.googleapis.com
x-goog-meta-a_b:1
x-goog-meta-a-b:2

host;x-goog-meta-a-b;x-goog-meta-a_b
UNSIGNED-PAYLOAD
  1. LANG=lt_LT.UTF-8 node index.js lt does the same for x-goog-meta-y and x-goog-meta-j:
host:storage.googleapis.com
x-goog-meta-y:1
x-goog-meta-j:2

host;x-goog-meta-j;x-goog-meta-y
A clear and concise description of what the bug is, and what you expected to happen.

The canonical headers block is in a different order from the signed headers list in the same canonical request, so GCS computes a different signature and rejects the URL. Expected: canonical headers in code point order, matching X-Goog-SignedHeaders:

host:storage.googleapis.com
x-goog-meta-a-b:2
x-goog-meta-a_b:1

host;x-goog-meta-a-b;x-goog-meta-a_b
A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. **

The V4 canonical request docs say headers are sorted by name "using a lexicographical sort by code point value": https://cloud.google.com/storage/docs/authentication/canonical-requests

URLSigner.getCanonicalHeaders in handwritten/storage/src/signer.ts (line 401 on main at 97b0d64daa8ea9407756aee646b8ac1bf19aec80) sorts with a[0].localeCompare(b[0]), which puts _ before - and follows the process locale, while signedHeaders uses a plain .sort().

Credit: https://ucsbplse.github.io/

主要语言
TypeScript
星标
3.2k
派生
732
平均合并
3 天 7 小时
30 天内合并 PR
117

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

googleapis/google-cloud-node 的其他 Issue

查看 googleapis/google-cloud-node 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。