Skip to content

tools/sourcehut: POST forwards Bearer token on redirect and skips the HTTPS assertion #1091

Description

@potiuk

Summary

tools/sourcehut/src/magpie_sourcehut/client.py issues its GraphQL POST
with a bare urllib.request.urlopen(req) — no HTTPS assertion and no
redirect handler. The request carries Authorization: Bearer <token>, so a
redirect response would cause urllib's default handler to follow it and
re-send the credential to the redirect target.

Surfaced while reviewing #1078, which added the first write to the Bitbucket
bridge. That bridge now demonstrates the safer pattern, so this is a
consistency gap rather than a new discovery.

Current state

req = urllib.request.Request(
    ...,
    headers={..., "Authorization": f"Bearer {token}"},
    method="POST",
)
try:
    with urllib.request.urlopen(req) as resp:

No _require_https(url) equivalent, and no build_opener(...), so
HTTPRedirectHandler applies by default.

What the Bitbucket bridge does instead

tools/bitbucket/src/magpie_bitbucket/client.py:

  • _require_https(url) before the request is built, so a plaintext URL
    cannot carry the credential at all.
  • Two explicit redirect policies rather than the default:
    • NoAuthRedirectHandler — raises on any redirect. Used by get_json and
      by the new post_json.
    • SameHostRedirectHandler — follows only same-origin HTTPS redirects,
      rejecting host changes, port changes and scheme downgrades. Used by
      get_text.
  • Writes deliberately take the strict handler: replaying a mutation at a
    redirected location is worse than failing and making the caller retry.

Suggested change

  1. Add an HTTPS assertion before building the request.
  2. Build an opener with an explicit redirect policy instead of relying on the
    default. For a mutation, rejecting redirects outright is the appropriate
    choice, matching post_json.
  3. Add tests for the redirect policy. Note tools/bitbucket has four tests
    for SameHostRedirectHandler but none for NoAuthRedirectHandler — worth
    covering both handlers wherever they guard a write.

Notes

No evidence this has been exploited or that sourcehut.org issues such
redirects; this is defence in depth on a credential-bearing request, and
alignment with the pattern the Bitbucket bridge now sets.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions