I recently added a pod from an external source. A pod with the same name also exists in the main pod repo, which gives a warning upon first pod install:
[!] Found multiple specifications for `ServiceSDK (1.1.0)`:
- /Users/phil/.cocoapods/repos/master/Specs/3/1/e/ServiceSDK/1.1.0/ServiceSDK.podspec.json
- /Users/phil/.cocoapods/repos/goinstant/ServiceSDK/1.1.0/ServiceSDK.podspec
It selected the correct pod, but I was curious how the selection works. According to the docs of source:
The order of the sources is relevant. CocoaPods will use the highest version of a Pod of the first source which includes the Pod (regardless whether other sources have a higher version).
With this definition in mind, I tried switching the order of source.
Running pod install with the reversed source definitions, I expected CocoaPods to select the other pod at version 1.1.0. This did not happen.
Instead, it always chooses the pod from the private source at version 218.0.1.
It seams to be picking the highest version available, regardless of the order of source.
Note that this might be expected behavior and the documentation for source might just be outdated.
(Note that this happens in the latest stable version 1.6.1 as well as the latest beta 1.7.0.beta.3.)
CocoaPods : 1.7.0.beta.3
Ruby : ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin18]
RubyGems : 3.0.1
Host : Mac OS X 10.14.2 (18C54)
Xcode : 10.1 (10B61)
Git : git version 2.18.0
Ruby lib dir : /Users/phil/.rubies/ruby-2.6.1/lib
Repositories : goinstant - https://github.com/goinstant/pods-specs-public @ 8fc9da7f193f0c4d07b9d287b9237565cb2f7d3d
master - https://github.com/CocoaPods/Specs.git @ bb24e795959e33014f1449d2697942de87cc854c
Executable Path: /Users/phil/.gem/ruby/2.6.1/bin/pod
cocoapods-deintegrate : 1.0.3
cocoapods-plugins : 1.0.0
cocoapods-search : 1.0.0
cocoapods-stats : 1.1.0
cocoapods-trunk : 1.3.1
cocoapods-try : 1.1.0
source 'https://github.com/CocoaPods/Specs.git'
source 'https://github.com/goinstant/pods-specs-public'
install! 'cocoapods', integrate_targets: false
platform :ios, '12.0'
target 'FooBar' do
pod 'ServiceSDK'
end
This might not necessarily be a bug, but that it's (IMO correctly) locked to the last version - does switching and then running pod update ServiceSDK then update to the other?
Cool, yep, sounds like a bug then 馃憤
according to sort by: https://github.com/CocoaPods/CocoaPods/blob/c1292cca13a8afa067e5157856b73cb0a65d6da4/lib/cocoapods/resolver/lazy_specification.rb#L79, and molinillo will use the latest possibility, so the resolved spec always be max version.
and according to https://github.com/CocoaPods/Molinillo/blob/b419616b2230663db01462a4b93c01d3c3569a8d/lib/molinillo/resolution.rb#L704 and https://github.com/CocoaPods/Core/blob/fe19e73758c2bcbed4f59ca3fdc0ed4040ba3db3/lib/cocoapods-core/specification.rb#L99,
array & will only keep the first for specs with different source
I think this could be abused to carry out a dependency confusion attack like this. Maybe this warrants a priority bump?
Does the following statement correctly summarize the current behavior?
If a pod exists in multiple source repos and multiple
sources are specified in the Podfile the CocoaPods dependency resolver will select the latest version among all the source repos. Note that the order of the Podfilesources does not change this behavior.
If not, please correct me.
I'll make a docs PR update cos this was confusing and I got hit by this issue.
Thanks
@dnkoutso
Most helpful comment
I think this could be abused to carry out a dependency confusion attack like this. Maybe this warrants a priority bump?