5

Detect license changes in packages · Issue #11520 · NuGet/Home · GitHub

 2 years ago
source link: https://github.com/NuGet/Home/issues/11520
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Copy link

clairernovotny commented 6 days ago

edited

Summary

NuGet packages are licensed for use according to either the licenseUrl, embedded license, or SPDX expression. While the license for a particular package is considered to be immutable, new versions of packages can have different licenses. When a package is updated, a customer may get a license with different terms than what they previously accepted. Today there is no warning/detection mechanism for this and as a result, updating a package could accidentally lead to a customer being out of compliance with the license.

Proposal

NuGet should detect license changes when updating a package and ensure the customer is aware of the change.

Implementation

Straw-person implementation: we could generate a packages.licenses.json file on package restore that contains license information for every package in the restore graph. That file can be committed to the repo. Then, upon future restore/upgrade, if there's a change, the tooling could prompt and a customer could see the difference.

Questions

  • Should NuGet block breaking license changes? This would require a new package id. Example (Apache -> MIT would be allowed, MIT -> GPL would not).
  • Should it enforce a major version change?
  • How and when do we alert users to the change?
  • How about transitive dependencies?
  • Should a license check be on-demand (a specific check command) or always on restore (could be perf issues)?

Copy link

WhiteBlackGoose commented 6 days ago

edited

My 5 cents:

Should NuGet block breaking license changes? This would require a new package id. Example (Apache -> MIT would be allowed, MIT -> GPL would not).

No, but it can be enforced with tooling, I think. For example, updating the package would yield an error about license incompatibility, so one would need to pass something like --accept-the-license flag or something like this.


Should it enforce a major version change?

Wouldn't it only make sense for semver, which isn't always strictly followed?


How and when do we alert users to the change?

In CLI it would by default try to update to the latest possible. Then

  • If the license is incompatible then it fails
  • If the license is incompatible but --accept-the-license is passed, it succeeded
  • If the license is incompatible but --latest-compatible-license is passed, then it updates to the latest version with compatible license

Wild cards will use --latest-compatible-license option by default, probably?

What do you think?

Copy link

heaths commented 6 days ago

Given nuget's limited/less-known support for version ranges, forcing an ID change for a more restrictive license seems like a good idea, but what - conceptually - does that even look like? Some rights might be more restrictive where others loosen. Who or what decides?

Certainly prompt when a license URL or ID/token changes. You might even use a sightly different dialog that really emphasizes that the license has changed and how. If it's a well-known license ID, perhaps link the old and new license with a explanation, like to opensource.org.

  • Should NuGet block breaking license changes? This would require a new package id. Example (Apache -> MIT would be allowed, MIT -> GPL would not)

In my opion: yes. There still is the option to simply create a new package for the maintainer.

Copy link

BenjaminAbt commented 6 days ago

edited

Should NuGet block breaking license changes? This would require a new package id. Example (Apache -> MIT would be allowed, MIT -> GPL would not)

How and when do we alert users to the change?

I think the NuGet lock file would be a good place for this, and a user must accept a license change, if the license is different from the last state in the lock file. This would also be an opt-in to the license check.

The problem would be that hardly anyone uses / can use the lock mechanism.

Maybe it would also be a good idea to keep an allow-list of licenses in the NuGet.config.

Excellent question!

Should NuGet block breaking license changes? This would require a new package id. Example (Apache -> MIT would be allowed, MIT -> GPL would not).

Yes, but configurable. CLI design changes may be needed to decide whether license changes should cause a failure. For instance, ANY license change, a more permissive license change, a more restrictive license change, or no warning.

Should it enforce a major version change?

Yes. Ideally, a new version which has the old licensed software. This would be the last version of that software, besides any LTS or critical fixes. This would allow the user to continue on with the old version but without getting update warnings that other devs may ignore without realising the consequences.

How and when do we alert users to the change?

Before package is downloaded. The developer should be warned that the license has changed and to review before proceeding. Ideally consent should be recorded somewhere for posterity, but I don't see how that could be done.

I do like the goal to ensure that there is a mechanism to alert people to a license change... Reading some of the proposals around this though I must say, I would be quite p***ed off if NuGet did anything explicitly to block me from publishing my packages. As a package author I do not want to have to publish an entirely new package id because of a license change, and it doesn't really lead down good paths... MyPackage -> MyPackage.LicenseA -> MyPackage.LicenseB... now how the heck does a consumer know which one to use.

Some things I would find helpful.

  1. When it comes to the actual goal here, I think there are really only 2 things that need to be done.
    • The tooling in Visual Studio should be updated to intervene when updating a package that changes from say MIT to a more sustainable license.
    • On NuGet.org an alert UI could be added similar to what we see when a package is deprecated. That could alert users that there has been a license change
  2. Rather than locking an entire package Id it would be more useful to have a soft lock on the major version, so that the license change must be accompanied by a major version change. This should also ultimately be up to the package author not the NuGet team so if the package authors really felt there was a need for it they should have an ability to still publish those changes.

I would want to at least know that a license change has occurred in a dependent package. When I worked at a large software corporate we had to keep a dependent database of licenses, and we had restrictions on what licenses are acceptable for OSS. If one of those changes may prevent developers from using the package without legal approval.

Visual Studio should default to alerting you. With an option to turn it off similar to the licenses screen at the moment.

Override switch for nuget.exe as well.

On the ReactiveUI which is an OSS project, I would probably want the build to fail until I checked how the license change affects the project for example.

Copy link

DavidKarlas commented 6 days ago

edited

‪Would be nice to have list of approved/compatible licenses in nuget.config with same propagation rules as sources, and I have to manually add new license to nuget.config.

Idea is if I have MIT and BSD in list of compatible licenses and package switches from MIT to BSD its not showing any warnings just upgrades. But if it goes to GPL and I don't have it in nuget.config it errors and it tells me that I need to add it to nuget.config.

This way newbie on project can't add incompatible nuget package but also protects you from deep dependencies...
This should keep popups and warnings to minimum which is must otherwise people just click I agree.

Of course it should be opt-in feature.

Edit:
Example:

<compatibleLicenses>
    <add type="expression" value="MIT" />
    <add type="expression" value="BSD-2-Clause OR MIT" />
    <add type="url" value="https://licenses.nuget.org/MIT" />
    <add type="fileHash" value="d27937f914ebe99ee315f04449678eccfb658191" />
    <add type="file" value="licensesFolder/MIT-With-Additional-Requirements.txt" />
</compatibleLicenses>

It's up to user to rely on fileHash which is a bit more simple but loses visibility into actual content vs. to add actual file to repository for comparing.

Copy link

groksrc commented 6 days ago

  • Should NuGet block breaking license changes? This would require a new package id. Example (Apache -> MIT would be allowed, MIT -> GPL would not).
    • No, definitely not. Now you've got a dependency graph of all of the "breaking license" changes. Good luck figuring that out.
  • Should it enforce a major version change?
    • No, definitely not. I should have the freedom to version my package as I see fit. If I only change the license and not the code, that's not a semantic versioning change.
  • How and when do we alert users to the change?
    • Maybe put a warning in the console output -- maybe. Like if we enable it with a flag. This is ultimately a problem between the devs and the package authors and NuGet doesn't need to be the intermediary.
  • How about transitive dependencies?
    • Again, this is a licensing problem between the package authors and their consumers. NuGet should prefer a light touch. Single Responsibility Principle -> Manage Packages (not licenses)
  • Should a license check be on-demand (a specific check command) or always on restore (could be perf issues)?
    • On-demand would make more sense to me. Tell me if I care to look, otherwise don't bother me with it. I have plenty of other problems to deal with.

Copy link

ltrzesniewski commented 6 days ago

edited

Straw-person implementation: we could generate a packages.licenses.json file on package restore that contains license information for every package in the restore graph. That file can be committed to the repo. Then, upon future restore/upgrade, if there's a change, the tooling could prompt and a customer could see the difference.

Wouldn't generating that file in obj be sufficient? VS restores NuGet packages when the solution is opened, so you'd already have a file you could compare against on the next restore.

I don't like the idea of having a committed file that just duplicates information from PackageReference tags.

Copy link

ryanbnl commented 6 days ago

There are some good replies here :-)

Basically:

  1. DO NOT fail on change. This will make new / dark matter developers get frustrated, break CI and is a breaking change to whichever tool you're changing.
  2. DO make licence changes visible.
  3. DO make the scope clear.

In practise that will mean:

  • Showing a warning in any situations where a package will be updated without explicit action (iirc you can bind resolution to automatically update to the latest minor revision, like in npm).
  • Require explicit consent on version update in UI tooling (i.e. package manager in Studio).
  • Default to warnings in CLI apps but also provide a strict mode (to avoid breaking CI builds etc).

Most important of all - clear communication over:

  • Problem being solved, why this is highly professional to do.
  • That this only affects nuget, not npm packages, so it isn't solving all problems.

Copy link

ryanbnl commented 6 days ago

Requiring a major version change for license changes? My first feeling is that it makes a lot of sense - licenses are a foundational building block of a project/package, changing them is a BIG deal so it should be absolutely visible.

Copy link

devlead commented 6 days ago

I like the idea of having better supply chain management features.

Some thoughts

  • I see it there are two aspects, the consumer and the producer, which might have totally different needs.
  • I don't think the major version is enforceable as there're many different types of versioning schemes, some use SemVer, some use yyyy.mm.dd.xxx, some use 0.x.y, so if viable it would need to be opt-in and configurable which versioning scheme to use.
  • From a producer point of view, if license changes I would not like to be disallowed to push package, but would appreciate it if the package was put on queue and an email to package owners with a link to approve the change, just to avoid mistakes.
  • As a consumer, I would like to be able to fail my builds if licenses change, preferable this would be opt-in and a notice file created based on dependencies (with id, license, repository info, but without version so it's not too noisy), with such a file any changes could easily be spotted in a PR, and any transient dependency changes could be cought by CI too i.e. fail if the file would to be modified when ContinuousIntegrationBuild is true. This would also give a good file for attribution and a bill of materials for auditors.

I see two different features mentioned in these discussion:

  1. Detect and notify on license changes of existing packages
  2. Limit packages to specific licenses

While I think limiting packages to specific licenses is a nice feature, I'm not sure if CLI is the best place to implement this. As this is a feature interesting for enterprise scenarios, being in a enterprise scenario would often also mean that I can't rely on client or repo configurations. Limiting packages to specific licenses is something, which nowadays already is handled by enterprise package management solution, with the additional benefit of having a central point to block packages with licenses, also from build, which can't be used, instead of relying on client or repo configuration.

On the other hand, I think, detecting and notifying of license changes when upgrading would bring additional value when supported by the CLI.

Copy link

ryanbnl commented 6 days ago

As this is a feature interesting for enterprise scenarios, being in an enterprise scenario would often also mean that I can't rely on client or repo configurations.

Sure in the enterprise I have my own artefact/package management repository and infrastructure to ensure compliance.

However I would argue that it's also very importent for smaller teams/companies. They don't have the resources to do this. Even the project I'm working on - which is very well resourced - doesn't have the capacity (checks are enforced during review).

Having this built in would have the added benefit of educating people, which would make it easier for me to sell said internal/project-specific nuget repo / npm repo / docker repo.

I'll weigh in a bit here as a package producer who's made license changes and who is likely to do so again in the future at some point. In my opinion, the package manager should be as unopinionated as possible, not just around licensing but around any package metadata. Others have already chimed in with similar sentiment, so this is mostly repetitive but to me, in this context, that means:

  • Don't make any assumptions or requirements around package naming and license (I.e. don't require a new package name if the license changes).
  • Don't make any assumptions or requirements connecting package version to license (I.e. don't require a particular versioning change when the license changes).
  • Don't make any assumptions about license content (I.e. NuGet shouldn't be trying to determine or calculate license compatibility, etc. - that's a huge, complex problem to solve in and of itself).

That's not to say I don't think NuGet shouldn't be license-aware and help consumers in that regard, just that the features to do so should be as simple and make as few assumptions and requirements on the packages as possible. Some thoughts about what that means NuGet could do:

  • Track (or compare) accepted licenses and trigger similar acceptance flows on license changes as if the package were being reinstalled from scratch.
  • @devlead mentioned some production tooling that could request approval for license changes when publishing - that seems reasonable as an extra confirmation step, as long as it never prevents the package author from actually publishing the package on approval.
  • @DavidKarlas mentioned the possibility for a opt-in license allow-list and I rather like that idea. I don't think it's a must-have, but would be a nice feature for organizations that want to strictly limit their license acceptance. I could also see something similar being provided out of the box as an auditing tool rather than baked into the package manager though.

I'm also still a little torn on whether any of this is NuGet's responsibility at all. As far as I can tell, other package managers tend to rely on external tooling or reporting capabilities (I.e. nlf or yarn licenses list) and I could see the same in the .NET ecosystem. In other words, perhaps the questions like "what licenses have I accepted in this project?", "are the licenses I've accepted what I expect?", and "am I currently in compliance with my licensing requirements?" can be better answered by .NET tools, reporting features (either in or out of box), etc. Of course there's no reason the NuGet or .NET team couldn't build and support such tools, just that maybe direct integration in the package manager might not be optimal or required.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK