Skip to content

Commit 4963db0

Browse files
committed
🐛 Support standalone auth-sanitizer loading
1 parent a6ba86a commit 4963db0

3 files changed

Lines changed: 80 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ Please file a bug if you notice a violation of semantic versioning.
2828

2929
### Fixed
3030

31+
- Fixed isolated `auth-sanitizer` loading when Bundler standalone setup makes
32+
`auth_sanitizer/loader.rb` available on `$LOAD_PATH` without adding
33+
`auth-sanitizer` to `Gem.loaded_specs` or `GEM_PATH`.
34+
3135
### Security
3236

3337
## [2.0.23] - 2026-06-13

lib/oauth2/auth_sanitizer.rb

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,35 @@ module OAuth2
66
auth_sanitizer_spec = Gem.loaded_specs["auth-sanitizer"]
77
unless auth_sanitizer_spec && auth_sanitizer_requirement.satisfied_by?(auth_sanitizer_spec.version)
88
# :nocov:
9-
auth_sanitizer_spec = Gem::Specification.find_by_name("auth-sanitizer", auth_sanitizer_requirement)
9+
begin
10+
auth_sanitizer_spec = Gem::Specification.find_by_name("auth-sanitizer", auth_sanitizer_requirement)
11+
rescue Gem::MissingSpecError
12+
auth_sanitizer_spec = nil
13+
end
1014
# :nocov:
1115
end
1216

13-
auth_sanitizer_loader_path = File.join(
14-
auth_sanitizer_spec.full_gem_path,
15-
"lib/auth_sanitizer/loader.rb"
16-
)
17-
unless File.file?(auth_sanitizer_loader_path)
17+
auth_sanitizer_loader_path = if auth_sanitizer_spec
18+
File.join(auth_sanitizer_spec.full_gem_path, "lib/auth_sanitizer/loader.rb")
19+
end
20+
unless auth_sanitizer_loader_path && File.file?(auth_sanitizer_loader_path)
21+
auth_sanitizer_loader_path = Gem.find_files("auth_sanitizer/loader.rb").find do |path|
22+
version_path = File.expand_path("../auth/sanitizer/version.rb", File.dirname(path))
23+
next false unless File.file?(version_path)
24+
25+
version_source = File.read(version_path)
26+
# Gem.find_files resolves loaders from $LOAD_PATH without exposing gemspec
27+
# metadata, so validate the adjacent version file before evaluating the
28+
# loader. This is intentionally limited to auth-sanitizer's VERSION file.
29+
version_match = version_source.match(/VERSION\s*=\s*(["'])([^"']+)\1/)
30+
version_match && auth_sanitizer_requirement.satisfied_by?(Gem::Version.new(version_match[2]))
31+
end
32+
end
33+
34+
unless auth_sanitizer_loader_path && File.file?(auth_sanitizer_loader_path)
1835
# :nocov:
1936
raise LoadError, "oauth2 requires auth-sanitizer #{auth_sanitizer_requirement}; " \
20-
"loader not found at #{auth_sanitizer_loader_path}"
37+
"loader not found in installed gems or on $LOAD_PATH"
2138
# :nocov:
2239
end
2340

spec/oauth2/auth_sanitizer_spec.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# frozen_string_literal: true
22

3+
require "open3"
4+
require "rbconfig"
5+
36
RSpec.describe "OAuth2::AUTH_SANITIZER" do
47
it "keeps auth-sanitizer constants isolated inside the OAuth2 namespace" do
58
expect(Object.const_defined?(:Auth, false)).to be(false)
@@ -9,4 +12,53 @@
912
it "preserves the public OAuth2::FilteredAttributes alias" do
1013
expect(OAuth2::FilteredAttributes).to be(OAuth2::AUTH_SANITIZER::FilteredAttributes)
1114
end
15+
16+
it "loads when auth-sanitizer is only available on the load path, not GEM_PATH" do
17+
oauth2_lib = File.expand_path("../../lib", __dir__)
18+
auth_sanitizer_lib = File.join(Gem.loaded_specs.fetch("auth-sanitizer").full_gem_path, "lib")
19+
script = <<~'RUBY'
20+
require "rubygems"
21+
22+
Gem.loaded_specs.delete("auth-sanitizer")
23+
24+
class << Gem::Specification
25+
alias_method :oauth2_original_find_by_name, :find_by_name
26+
27+
def find_by_name(name, *requirements)
28+
raise Gem::MissingSpecError.new(name, requirements) if name == "auth-sanitizer"
29+
30+
oauth2_original_find_by_name(name, *requirements)
31+
end
32+
end
33+
34+
require "oauth2/auth_sanitizer"
35+
abort("OAuth2::AUTH_SANITIZER was not loaded") unless OAuth2.const_defined?(:AUTH_SANITIZER, false)
36+
RUBY
37+
38+
stdout, stderr, status = Open3.capture3(
39+
{
40+
"BUNDLE_GEMFILE" => nil,
41+
"BUNDLER_VERSION" => nil,
42+
"RUBYLIB" => nil,
43+
"RUBYOPT" => nil,
44+
},
45+
RbConfig.ruby,
46+
"-I",
47+
oauth2_lib,
48+
"-I",
49+
auth_sanitizer_lib,
50+
"-e",
51+
script
52+
)
53+
54+
expect(status).to be_success, <<~MSG
55+
expected oauth2/auth_sanitizer to load with auth-sanitizer only on $LOAD_PATH
56+
57+
stdout:
58+
#{stdout}
59+
60+
stderr:
61+
#{stderr}
62+
MSG
63+
end
1264
end

0 commit comments

Comments
 (0)