fix(base): refuse to send credentials over a non-HTTPS endpoint
I maintainer di solito rispondono entro 1 giorno
@ffumero2003 ci sta già lavorando.
Dal 8/11/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
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
- Lingua principale
- Go
- Stelle
- 66
- Fork
- 18
- Merge medio
- 1g 10h
- PR unite (30g)
- 132
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Backblaze/blazer
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
Bucket.Attrs never returns ReplicationConfig: replication configuration is write-onlyForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
test: skip the fuzz non-vacuity guard when replaying a single seedForse già presa @ffumero2003 l’ha presa 5 giorni fa. Apertatesting
Backblaze/blazer#330 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di Backblaze/blazer
Issue simili
-
needs-triage typo
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
llm-d-incubation/llm-d-scaling-manager#122 ·
I maintainer di solito rispondono entro 1 giorno
-
good first issue severity: low tech-debt
Difficoltà 2/5 Mezza giornata Idoneità per principianti 75/100
TMHSDigital/subenum#329 ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug] Backend summarize min() / max() panics when a field has no numeric valuesForse già presa @weng5e l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
grafana/grafana-infinity-datasource#1832 ·
I maintainer di solito rispondono entro 1 giorno
-
tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
GillMacedo/godebugdiff#13 ·