Skip to content

Restrict the loopback redirect_uri exception to the port (RFC 8252 §7.3) - #1878

Merged
nbulaj merged 1 commit into
doorkeeper-gem:mainfrom
55728:fix/loopback-redirect-uri-userinfo
Jul 27, 2026
Merged

Restrict the loopback redirect_uri exception to the port (RFC 8252 §7.3)#1878
nbulaj merged 1 commit into
doorkeeper-gem:mainfrom
55728:fix/loopback-redirect-uri-userinfo

Conversation

@55728

@55728 55728 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Problem

RFC 8252 §7.3 lets only the port of a loopback redirect URI vary at runtime. The check blanked the port with URI#port= and compared the reassembled strings, but on Ruby >= 4.0 URI#port= also clears the userinfo. So http://attacker@127.0.0.1/cb matched a registered http://127.0.0.1/cb.

Scope: the destination host is always the loopback interface (127.0.0.1 / ::1), so this is not a cross-origin open redirect. Non-loopback hosts take the exact-match branch and were never affected. Ruby-version dependent (surfaced by the URI#port= behavior change in Ruby 4.0).

Fix

Compare the two URIs component by component (scheme, userinfo, host, path, query, fragment), leaving the port out. This keeps the port-only exception while no longer ignoring userinfo differences, and preserves the previous property of not letting URI#== normalize an empty path to "/".

RFC 8252 §7.3 lets only the port of a loopback redirect URI vary. The
port was blanked with URI#port= before a string comparison, but on
Ruby >= 4.0 URI#port= also clears the userinfo, so
http://attacker@127.0.0.1/cb matched a registered http://127.0.0.1/cb.

Compare the URIs component by component instead, keeping the port out of
the comparison. The destination host is always the loopback interface,
so this was not a cross-origin open redirect; non-loopback hosts take
the exact-match branch and were never affected.
Copilot AI review requested due to automatic review settings July 25, 2026 06:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens Doorkeeper’s RFC 8252 §7.3 “loopback redirect URI port variance” handling by avoiding URI#port= mutation (which can drop userinfo on Ruby >= 4.0) and instead comparing URI components while ignoring only the port. This prevents userinfo-based mismatches (e.g. attacker@127.0.0.1) from being accepted as valid loopback redirects.

Changes:

  • Replace the previous “nil out port then compare to_s” approach with an explicit component-by-component comparison that excludes the port.
  • Add regression specs ensuring userinfo is not ignored for loopback redirect URIs while preserving the port-only variance behavior.
  • Document the security fix in CHANGELOG.md.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
spec/lib/oauth/helpers/uri_checker_spec.rb Adds regression coverage for loopback redirect URI matching when userinfo differs, and confirms port-only variance still works.
lib/doorkeeper/oauth/helpers/uri_checker.rb Implements loopback_match? to compare all URI components except port, preventing userinfo from being unintentionally ignored.
CHANGELOG.md Records the loopback redirect URI userinfo/port matching fix and its Ruby >= 4.0 motivation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/doorkeeper/oauth/helpers/uri_checker.rb Outdated
@55728
55728 force-pushed the fix/loopback-redirect-uri-userinfo branch from bccd096 to 4678fcf Compare July 27, 2026 10:28
Copilot AI review requested due to automatic review settings July 27, 2026 10:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 27, 2026 10:30
@55728
55728 force-pushed the fix/loopback-redirect-uri-userinfo branch from 4678fcf to c8ab38e Compare July 27, 2026 10:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@55728
55728 requested a review from nbulaj July 27, 2026 10:32

@nbulaj nbulaj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM ✅

@nbulaj
nbulaj merged commit 26e63e9 into doorkeeper-gem:main Jul 27, 2026
23 checks passed
@55728

55728 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Thank you 😊

@55728
55728 deleted the fix/loopback-redirect-uri-userinfo branch July 27, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants