Commit e2f5c82

mo khan <mo@mokhan.ca>
2026-08-04 02:19:05
fix: reject a --url that is not an absolute http(s) URL
URI.join raised URI::BadURIError, which is neither Cli::Error nor Thor::Error, so a base URL without a scheme printed a backtrace.
cli
1 parent 2cdd1ce
Changed files (2)
lib
scim
spec
scim
lib/scim/kit/cli/settings.rb
@@ -19,12 +19,7 @@ module Scim
         end
 
         def url
-          @url ||= begin
-            resolved = options[:url] || env.fetch('SCIM_KIT_URL', nil)
-            raise Thor::Error, '--url is required' if resolved.to_s.empty?
-
-            resolved
-          end
+          @url ||= validate(options[:url] || env.fetch('SCIM_KIT_URL', nil))
         end
 
         def headers
@@ -39,6 +34,24 @@ module Scim
 
         attr_reader :options, :env
 
+        def validate(url)
+          raise Thor::Error, '--url is required' if url.to_s.empty?
+
+          unless absolute_http?(url)
+            raise Thor::Error,
+              "--url must be an absolute http(s) URL, got #{url.inspect}"
+          end
+
+          url
+        end
+
+        def absolute_http?(url)
+          uri = URI.parse(url)
+          uri.is_a?(URI::HTTP) && !uri.host.to_s.empty?
+        rescue URI::InvalidURIError
+          false
+        end
+
         def split_header(header)
           name, value = header.split(':', 2)
           if value.nil?
spec/scim/kit/cli/settings_spec.rb
@@ -25,6 +25,25 @@ RSpec.describe Scim::Kit::Cli::Settings do
       expect { settings({ url: '' }).url }
         .to raise_error(Thor::Error, /--url is required/)
     end
+
+    it 'raises when the url has no scheme' do
+      expect { settings({ url: 'example.com/scim/v2' }).url }
+        .to raise_error(Thor::Error, /--url must be an absolute http/)
+    end
+
+    it 'raises when the url scheme is not http(s)' do
+      expect { settings({ url: 'ftp://example.com' }).url }
+        .to raise_error(Thor::Error, /--url must be an absolute http/)
+    end
+
+    it 'raises when the url is unparseable' do
+      expect { settings({ url: 'http://exa mple.com' }).url }
+        .to raise_error(Thor::Error, /--url must be an absolute http/)
+    end
+
+    it 'accepts an http url' do
+      expect(settings({ url: 'http://a' }).url).to eql('http://a')
+    end
   end
 
   describe '#headers' do