Example of Package Collision (aka Package Hijacking) behavior with SAT using URLs and forks
The way Nimble reads project info currently is broken. It depends on the iteration order of packages in ~/.nimble/pkgs2, which include packages from any URL.
This should be useful, but unfortunately the package caching and URL handling doesn't account for this. Also, it depends on the Nimble commands used and refactors could changes the behavior of commands as well.
This issue can also occur even if an upstream dependency uses a URL for requires "url". In that way a bad actor could trick your local Nimble to install their package and modify their project checksum so it'll be loaded first.
This is a concrete example showing what happens based on https://github.com/nim-lang/nimble/issues/1323
Stage 1
My project Figuro uses windy. We do a nimble install -d and get:
├── windy @any (@0.0.0) [vcs: 4333b8145 checksum: 2c7e93eba]
Step 2
I fork windy and test out a new feature at https://github.com/elcritch/windy#macos-keyinput-fixes.
Running nimble install -d works as expected and we get:
├── windy #macos-keyinput-fixes (@0.0.0) [vcs: 6da1864c8 checksum: a8227bbbd]
Step 3
I decide to abandon the feature, or it gets merged upstream but without a new release, etc. Lots of variations can occur.
We revert figuro.nimble back to requires "windy". We expect Nimble would go back to the official Windy package right?
Nope! Worse is that behavior seems to depend on the checksum hash as that's the order that Nimble will load the package info. In this case it appears to be choosing the last package repo which is my forked package.
It sticks with the forked version even if we do a nimble install -d again:
Bonus Issue - Let the compiler decide which package it uses
Adding this to figuro.nimble like:
requires "https://github.com/elcritch/windy#macos-keyinput-fixes"
requires "windy"
Results in this:
├── windy #macos-keyinput-fixes (@0.0.0) [vcs: 6da1864c8 checksum: a8227bbbd]
├── windy @any (@0.0.0) [vcs: 6da1864c8 checksum: a8227bbbd]
Which means on the Nimble commands used, the Nim compiler could get multiple paths for the same package name "windy". I'm not sure what happens then.
It seems like this would occur even with the same URL / official repo as well since every branch also gets added to the mix. Having versions wouldn't fix this either as long as two branchs/forks/urls exist with the same version.
-> % cat figuro.nimble | grep windy
requires "windy"
-> % nimble install -d
Info: Using the environment variable: NIMBLE_DIR='/Users/elcritch/.nimble/'
-> % nimble deps
Info: Using the environment variable: NIMBLE_DIR='/Users/elcritch/.nimble/'
Info: Dependency tree format: {PackageName} {Requirements} (@{Resolved Version} commit {short-hash-id})
figuro (@0.7.2) [vcs: 3782f6014 checksum: e819850aa]
...
├── windy @any (@0.0.0) [vcs: 4333b8145 checksum: 2c7e93eba]
└── zippy >= 0.10.4 (@0.10.16) [vcs: a99f6a7d8 checksum: da3bb5ea3]
-> % ### We expect @any (@0.0.0) [vcs: 4333b8145 checksum: 2c7e93eba]
Now install a fork:
-> % ### Now install fork branches with random sha1 hashes...
-> % for i in `seq 1 20`; do echo I: $i ; nimble install https://github.com/elcritch/windy@\#test-nimble-$i && nimble deps; done
I: 1
Info: Dependency tree format: {PackageName} {Requirements} (@{Resolved Version} commit {short-hash-id})
figuro (@0.7.2) [vcs: 3782f6014 checksum: e819850aa]
...
├── windy @any (@0.0.0) [vcs: 611af18a8 checksum: 8711197d9]
└── zippy >= 0.10.4 (@0.10.16) [vcs: a99f6a7d8 checksum: da3bb5ea3]
I: 2
Info: Dependency tree format: {PackageName} {Requirements} (@{Resolved Version} commit {short-hash-id})
figuro (@0.7.2) [vcs: 3782f6014 checksum: e819850aa]
...
├── windy @any (@0.0.0) [vcs: 55211bbfc checksum: 7599341c5]
└── zippy >= 0.10.4 (@0.10.16) [vcs: a99f6a7d8 checksum: da3bb5ea3]
I: 3
Info: Dependency tree format: {PackageName} {Requirements} (@{Resolved Version} commit {short-hash-id})
figuro (@0.7.2) [vcs: 3782f6014 checksum: e819850aa]
...
├── windy @any (@0.0.0) [vcs: 4b93fde94 checksum: 804d02ba3]
└── zippy >= 0.10.4 (@0.10.16) [vcs: a99f6a7d8 checksum: da3bb5ea3]
I: 4
Info: Dependency tree format: {PackageName} {Requirements} (@{Resolved Version} commit {short-hash-id})
figuro (@0.7.2) [vcs: 3782f6014 checksum: e819850aa]
...
├── windy @any (@0.0.0) [vcs: 4b93fde94 checksum: 804d02ba3]
└── zippy >= 0.10.4 (@0.10.16) [vcs: a99f6a7d8 checksum: da3bb5ea3]
I: 5
Info: Dependency tree format: {PackageName} {Requirements} (@{Resolved Version} commit {short-hash-id})
figuro (@0.7.2) [vcs: 3782f6014 checksum: e819850aa]
...
├── windy @any (@0.0.0) [vcs: 4b93fde94 checksum: 804d02ba3]
└── zippy >= 0.10.4 (@0.10.16) [vcs: a99f6a7d8 checksum: da3bb5ea3]
I: 6
Info: Dependency tree format: {PackageName} {Requirements} (@{Resolved Version} commit {short-hash-id})