fix(base): refuse to send credentials over a non-HTTPS endpoint
メンテナーはふだん 1 日以内に返信
@ffumero2003 がすでに取り組んでいます。
2026年11月8日 から。
評価
この issue はまだ評価されていません。
説明
Context
b2.APIBase / base.SetAPIBase accept any URL string, and b2_authorize_account sends the application key as Authorization: Basic ... to it (base/base.go), which is the actual secret on the wire, not a derived signature. No scheme check exists, so a misconfigured non-loopback http:// endpoint sends the key, and later tokens, in cleartext.
Decision: refuse non-HTTPS, no opt-out (resolved)
Allow HTTPS, allow loopback-IP-literal HTTP for local testing, refuse everything else — including localhost and private-network http — with a clear error. No opt-out flag. Rationale, from blazer and the B2 reference SDKs:
- blazer already treats a broken transport as permanent: TLS certificate failures are not retried and there is no skip-verify escape hatch (
base/base.go:555). Refusing plaintext credentials is consistent with that posture. - The B2 TypeScript SDK (the newest) solves exactly this with no opt-out:
assertSecureRealmUrl(src/auth/realms.ts) allows HTTPS or loopback-IP HTTP and throwsrefusing to send credentials over plaintext HTTP realmfor anything else. - It deliberately excludes
localhostfrom loopback: "it is resolver-controlled, while [IP literals are not]." Loopback is therefore127.0.0.1and::1only. - The B2 Java SDK's
setSupportInsecureHttpis off by default and documented as test-only ("that's a good way to leave it"). - B2 sends the key as HTTP Basic, unlike S3 SigV4 where the secret never travels, so an easy opt-out would cleartext a long-lived master key — exactly the footgun to avoid. If a real internal-HTTPS-less endpoint need appears later, an opt-out can be added as a non-breaking minor feature.
Behavior change: needs a **Breaking:** changelog entry and an /sdk-panel-review pass.
Acceptance criteria
- R1. Red: a non-loopback
http://endpoint is currently accepted and the credential is sent. - R2. Green: a non-loopback
http://endpoint is refused before any credential is sent, with a clear error naming the endpoint;https://works; loopback-IPhttp://(127.0.0.1,::1) works. - R3.
localhostoverhttp://is refused (resolver-controlled, not a loopback IP literal). No existing test depends onhttp://localhost; the wire tests usehttptest, whose URL ishttp://127.0.0.1:PORT. - R4. The ~87 tests that reach a server through
APIBase/SetAPIBasewith a loopback-IPhttptestURL still pass. - R5. The check covers both the initial authorize and a restored-session API URL (a persisted
AccountInfowhoseapiUrlis non-loopbackhttp), so a cleartext URL cannot slip in through session restore.
In scope
- Refuse to attach credentials when the endpoint scheme is not
httpsand the host is not a loopback IP literal (127.0.0.1,::1). Apply atb2_authorize_accountand to a restored-session API URL. - A clear, non-retryable error that names the offending endpoint and does not leak the credential.
Out of scope
- An opt-out flag for non-HTTPS endpoints (decided against above; revisit only on real demand, as a non-breaking addition).
- Accepting
http://localhost(excluded deliberately). - Any change to upload/download URL handling that B2 itself returns over HTTPS, beyond the restored-session API URL check in R5.
- Unrelated work outside the components and behavior described in In scope.
Verification
Run the repository regression checks with live credentials unset:
unset B2_APPLICATION_KEY_ID B2_APPLICATION_KEY B2_ACCOUNT_ID B2_ACCOUNT_KEY
go build ./...
go vet ./...
go test -race -count=1 ./base ./b2/...
- Red first: show a non-loopback
http://endpoint is accepted and the credential is sent today. After the fix, show it is refused with the stated error before any request carries the key. - Cover both the authorize path and a restored-session API URL (R5), using synthetic credentials.
- Show
https://and loopback-IPhttp://still work, andhttp://localhostis refused (R3). Retain the existing loopback-IP test coverage (R4). - Record the
**Breaking:**changelog entry and run the SDK panel review on the diff. - Expected result: the checks above succeed and the observable outcomes in Acceptance criteria are demonstrated. If a check cannot run, report
Could not run because: ...; if it starts but fails, reportCould not complete because: .... A skipped check is not a pass.
Links
- Model: B2 TypeScript SDK
assertSecureRealmUrl(src/auth/realms.ts); B2 Java SDKsetSupportInsecureHttp(off by default, test-only). - blazer TLS-permanent precedent:
base/base.go:555. - Repository contribution guidance
- Testing guidance
- 主要言語
- Go
- スター
- 66
- フォーク
- 18
- 平均マージ
- 1日 10時間
- マージ済み PR(30日)
- 132
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
Backblaze/blazer のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
Bucket.Attrs never returns ReplicationConfig: replication configuration is write-only再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
test: skip the fuzz non-vacuity guard when replaying a single seed対応中かも @ffumero2003 が 5 日前に担当しました。 オープンtesting
Backblaze/blazer#330 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
Backblaze/blazer の issue をすべて見る
似ている issue
-
needs-triage typo
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
llm-d-incubation/llm-d-scaling-manager#122 ·
メンテナーはふだん 1 日以内に返信
-
good first issue severity: low tech-debt
難易度 2/5 半日 初心者へのやさしさ 75/100
TMHSDigital/subenum#329 ·
メンテナーはふだん 1 日以内に返信
-
[Bug] Backend summarize min() / max() panics when a field has no numeric values対応中かも @weng5e が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 64/100
grafana/grafana-infinity-datasource#1832 ·
メンテナーはふだん 1 日以内に返信
-
tech-debt
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
GillMacedo/godebugdiff#13 ·