CVE-2024-38368 (Ruby, published 2024-07-01T21:15Z)
Description: value: trunk.cocoapods.org is the authentication server for the CoacoaPods dependency manager. A vulnerability affected older pods which migrated from the pre-2014 pull request workflow to trunk. If the pods had never been claimed then it was still possible to do so. It was also possible to have all owners removed from a pod, and that made the pod available for the same claiming system. This was patched server-side in commit 71be5440906b6bdfbc0bcc7f8a9fec33367ea0f4 in September 2023.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/CocoaPods/trunk.cocoapods.org
Files changed:
app/controllers/claims_controller.rb
app/views/claims/thanks.slim
spec/functional/claims_controller_spec.rb
Commit message: Drop the claims feature


Vulnerable code:

      get '/new' do
        @owner = Owner.new
        @pods = []
        slim :new
      end

      post '/' do
        find_owner
        find_pods
        if @owner.valid? && valid_pods?
          change_ownership
          if all_pods_already_claimed?
            query = {
              :claimer_email => @owner.email,
              :pods => @already_claimed_pods,
            }
            redirect to("/disputes/new?#{query.to_query}")
          else
            query = {
              :claimer_email => @owner.email,
              :successfully_claimed => @successfully_claimed_pods,
              :already_claimed => @already_claimed_pods,
            }
            redirect to("/thanks?#{query.to_query}")
          end
        end
        prepare_errors
        slim :new
      end

      get '/thanks' do
        slim :thanks
      end
      def all_pods_already_claimed?
        @successfully_claimed_pods.empty? && !@already_claimed_pods.empty?
      end


      def change_ownership
        @successfully_claimed_pods = []
        @already_claimed_pods = []
        DB.test_safe_transaction do
          @owner.save_changes(:raise_on_save_failure => true)
          unclaimed_owner = Owner.unclaimed
          @pods.each do |pod|
            if pod.owners == [unclaimed_owner]
              @owner.add_pod(pod)
              pod.remove_owner(unclaimed_owner)
              @successfully_claimed_pods << pod.name
            else
              @already_claimed_pods << pod.name
            end
          end
        end
      end
  p All of your choosen Pods are already claimed.
  describe ClaimsController, 'when claiming pods' do
    seed_unclaimed

    it 'renders a new claim form' do
      get '/new'
      last_response.status.should == 200
      form = response_doc.css('form').first
      form['action'].should == '/claims'
      form['method'].should == 'POST'
    end

    it 'does not create an owner if no pods are specified' do
      lambda do
        post '/', :owner => { :email => 'appie@example.com', :name => 'Appie Duran' }, :pods => []
      end.should.not.change { Owner.count }
      last_response.status.should == 200
      form = response_doc.css('form').first
      form.css('input[name="owner[email]"]').first['value'].should == 'appie@example.com'
      form.css('input[name="owner[name]"]').first['value'].should == 'Appie Duran'
    end

    before do
      @pod = Owner.unclaimed.add_pod(:name => 'AFNetworking')
    end

    it 'creates an owner and assigns it to the claimed pods' do
      lambda do
        post '/', :owner => { :email => 'appie@example.com', :name => 'Appie Duran' }, :pods => ['AFNetworking']
      end.should.change { Owner.count }
      owner = Owner.find_by_email('appie@example.com')
      owner.name.should == 'Appie Duran'
      @pod.reload.owners.should == [owner]
    end

    it 'finds an existing owner and assigns it to the claimed pods' do
      owner = Owner.create(:email => 'appie@example.com', :name => 'Appie Duran')
      lambda do
        post '/', :owner => { :email => 'appie@example.com' }, :pods => ['AFNetworking']
      end.should.not.change { Owner.count }
      @pod.reload.owners.should == [owner]
    end

    it "finds an existing owner and doesn't update its name" do
      owner = Owner.create(:email => 'appie@example.com', :name => 'Appie Duran')
      post '/', :owner => { :email => 'appie@example.com', :name => 'Appiepocalypse' }, :pods => ['AFNetworking']
      owner.reload.name.should == 'Appie Duran'
    end

    it 'does not assign a pod that has already been claimed' do
      other_pod = Pod.create(:name => 'ObjectiveSugar')
      other_owner = Owner.create(:email => 'jenny@example.com', :name => 'Jenny Penny')
      other_owner.add_pod(other_pod)
      post '/', :owner => { :email => 'appie@example.com', :name => 'Appie Duran' },
                :pods => %w[AFNetworking ObjectiveSugar]
      owner = Owner.find_by_email('appie@example.com')
      @pod.reload.owners.should == [owner]
      other_pod.reload.owners.should == [other_owner]
      last_response.status.should == 302
      query = { :claimer_email => owner.email, :successfully_claimed => ['AFNetworking'],
                :already_claimed => ['ObjectiveSugar'] }
      last_response.location.should == "https://example.org/thanks?#{query.to_query}"
    end

    it 'immediately redirects to the dispute page if all pods are claimed' do
      @pod.remove_owner(Owner.unclaimed)
      owner = Owner.create(:email => 'jenny@example.com', :name => 'Jenny Penny')
      owner.add_pod(@pod)
      lambda do
        post '/', :owner => { :email => 'appie@example.com', :name => 'Appie Duran' }, :pods => ['AFNetworking']
      end.should.change { Owner.count }
      last_response.status.should == 302
      uri = URI.parse(last_response.location)
      uri.path.should == '/disputes/new'
      query = { 'claimer_email' => 'appie@example.com', 'pods[]' => 'AFNetworking' }
      Rack::Utils.parse_query(uri.query).should == query
      Owner.find_by_email('appie@example.com').should.not.be.nil
    end

    it 'rolls back in case of an error' do
      Pod.any_instance.stubs(:remove_owner).raises
      lambda do
        should.raise do
          post('/',
               :owner => {
                 :email => 'appie@example.com',
                 :name => 'Appie Duran',
               },
               :pods => ['AFNetworking'])
        end
      end.should.not.change { Owner.count }
      @pod.reload.owners.should == [Owner.unclaimed]
    end

    it 'shows validation errors' do
      post('/',
           :owner => { :email => 'appie@example.com', :name => '' },
           :pods => %w[AFNetworking EYFNetworking JAYSONKit])
      last_response.status.should == 200
      @pod.reload.owners.should == [Owner.unclaimed]
      errors = response_doc.css('.errors li')
      errors.first.text.should == 'Owner name is not present.'
      errors.last.text.should == 'Unknown Pods EYFNetworking and JAYSONKit.'
    end

    it 'shows a thanks page' do
      get('/thanks',
          :claimer_email => 'appie@example.com',
          :successfully_claimed => ['AFNetworking'],
          :already_claimed => ['JSONKit'])
      last_response.status.should == 200
      last_response.body.should.include 'AFNetworking'
      last_response.body.should.include 'JSONKit'

      link = response_doc.css('article p a')[2]
      query = { :claimer_email => 'appie@example.com', :pods => ['JSONKit'] }
      link['href'].should == "https://example.org/disputes/new?#{query.to_query}"
    end
  end

  describe ClaimsController, 'concerning disputes' do

Fixed code:
      #  Deprecated
  p All of your chosen Pods are already claimed.
    describe ClaimsController, 'concerning disputes' do