[policy, no patch] Use Update XML in Package manager to determine release support status

Created on 18 October 2023, about 1 year ago
Updated 15 December 2023, 11 months ago

Problem/Motivation

This core issue is to determine what approach should be taken on 🐛 Rely on TUF-protected resources to determine which updates are available Postponed: needs info for the Package Manager(API only) and Automatic Updates modules which are being created for core in 

Add Alpha level Experimental Package Manager module Needs review and Add Alpha level Experimental Automatic Updates module Needs work .

I wanted to raise this as a core issue because

  1. It deals with with The Update Framework(TUF) signing which has been determined to be a core product level decision
  2. It deals with  security in general
  3. If we want Auto Updates in any near timeframe there is no perfect solution
  4. Implementing it could take a while, depending on the approach chosen,  so I don’t want to choose a way without a core consensus and then have to redo before we get committed to core

The current problem

Package Manager provides a validator that will stop Composer operations if any new Drupal projects are installed or updated to a version that is not considered installable.

The installable definition works on the current Update module logic(though does not use it directly entirely) which is

  1. The project must be published
  2. The release must be published
  3. The release must be on a supported branch
  4. The release cannot be considered insecure.

We implemented this validator in Package Manager instead of Auto Updates because when Project Browser was being developed it was obvious that it would need that same type of validation. We wanted Package Manager, as much as possible, to be secure by default for any module that uses it’s API.

The problem with this is that the 4 criteria above come from the Update XML.

Currently in 🌱 [policy, no patch] How much of The Update Framework integration is needed for alpha-level review/commit of Package Manager? Needs review we are deciding(has been decided? The issue is not closed🤷) if TUF packaging signing will be an Alpha requirement for Package Manager and Automatic Updates.

The Update XML itself is not protected by TUF and this metadata is not available in Composer, except for `composer audit` which should be the same as 4) but does not account for any of the others.

This will not be the only part of the system that is not TUF protected. We will not get complete TUF protection because our client TUF libraries only protect targets that have a signed TUF target repos on the server side.

For the foreseeable future this will be limited to Composer metadata and downloads from packages.drupal.org which will protect all Contrib projects, and a special Rugged instance set up to provide a TUF protected source for Drupal core itself and other drupal/* packages that are generated from Drupal Core and hosted via Packagist.org.

This means that Composer metadata and downloads from packagist.org, all of our vendor dependencies, will not be TUF protected. This would be somewhat mitigated by 🌱 [policy, no patch] Should Package Manager require Composer HTTPS? Active . We also require HTTPS  for downloading Update XML in Package Manager.

Through Composer metadata, which for Drupal projects will be TUF protected, we can determine what the latest releases of a project are and which versions are considered insecure according to Composer. That information alone is probably not enough to determine if a release should be installed because the metadata from Drupal Update XML provides more security  context that we currently don’t consider ignorable(at least in the Update module)

For example security advisories are not made for unsupported branches. 

Therefore if Package Manager(or modules using its API to perform Composer operations) rely solely on Composer metadata they could easily update a project from version that is considered secure to one where the security status is unknown. Also Project Browser could install a version of a project that is not supported.

An example:

Module A

1.0.x is marked as supported and has  releases 1.0.0 or more

2.0.x is marked as unsupported and has releases 2.0.0 or more

Solely from Composer metadata alone Package Manager would have no way of knowing to prevent Module A from being updated from 1.0.0 to 2.0.0 or installing Module A as a new project at 2.0.0. From Composer’s point of version 2.0.0 is the latest version of the project. It has no concept of supported.

Drupal Core’s special case

For Drupal core itself we do have one other source of information that we could rely on to help this situation. 

\Drupal\update\ProjectSecurityData currently has hard coded  security coverage end dates for the last 2 minor versions of Drupal  9 and this will be added for Drupal 10 in 📌 Hardcode security coverage EOL dates for Drupal 10.last-1 and 10.last Needs review .  Presumably this will be added for each new core major. It also CORE_MINORS_WITH_SECURITY_COVERAGE which specifies that 2 core minors are supported at a time. 

Combining this information with 

  1. Composers’ metadata about which core versions are available
  2. ‘composer audit` catching all core security releases
  3. An assumption that the most recent major versions of Drupal core with a X.0.0 release should be considered supported.
  4. An assumption that no release of Drupal core >10.2.0 will ever be unpublished and be available in composer without a Composer security advisory(assuming also very unlikely it be would unpublished at all)
  5. Before the Drupal core project itself was ever unpublished🙀 we could ship code in Package Manager to deal with this in some way and/or we would have no opinion about security for users who kept using Drupal core regardless.

We should be able to securely deal with updates in Drupal core without any of the metadata that is only Update XML.

Proposed resolution

Package Manager should have validation for what is considered “installable”. This will ensure that other modules that use the API will get some confidence that we are making the operations as secure as possible. Update XML from drupal.org should be the source of what should be considered installable.

It will not be the only part of the system that is not TUF protected and will be checked, as much as possible, against TUF protected metadata(see following).

So for example say a module has supported 1 and 2 branches, and an unsupported an abandoned dead end 3.x branch, that kind of information is only currently available from update XML. If we don't check installability, we could update people to dead end branches or paper bag releases that have been withdrawn.

In addition add ComposerAuditValidator that would use `composer audit` to prevent Composer operations that update packages to a new version or install a new package at a version that is insecure according to Composer.

We should also check that the available versions returned by the Update XML, just the numbers not the metadata unknown to Composer, match the available versions as known to Composer (composer info -a).

This allows Composer metadata, which for drupal/* will be TUF protected, to be the authority for which releases there are and which are secure.This would mean that even if the Update XML was compromised you could not "hide"(freeze attack) a newer version of a module. You could also not spoof the XML to make a version marked insecure as secure(as long as there is corresponding Composer security advisory that would show up in composer audit).

In Automatic Updates we should also use the logic from Drupal Core’s special case above to validate supported versions of Drupal core. We may just want to move this logic directly into Package Manager because there is nothing stopping other Package Manager users from updating Drupal core also. On the other hand if the XML was compromised you could however make a site think a new unsupported branch is actually supported allowing updates to or installs of version in that branch. This should not be possible for Drupal core itself because of the other information we have.

Of course the attack you could make by compromising the Update XML you could also make if you compromised the servers providing the  Composer metadata for vendor packages which are not TUF. In addition the Update XML is never used for code downloads whereas the un TUF-protected Composer metadata does provide code download locations.But I am assuming we are more worried about Drupal ecosystem resources being compromised than the vendor ecosystem.

Risks

Since Update XML will be protected by a HTTPS connection but not by TUF there are risks if the drupal.org server is comprised or there is problem with HTTPS request coming from the client.

If we consider that Update XML may not be 100% trustworthy the risks if it is compromised are:

  1. Fake XML could mark a newer version of project as supported when it is not.
    Updating to a from a supported to non-support version has a few problems.

    One, it may be broken and crash the site
    Two, it work but may make schema or other changes which are reversible so the site could not revert back to a supported version of the project.
    Three, there may be know security problems with the module but in since it is not support a security advisory might be issued so composer audit would not find know about the security problems and stop the update.

  2. Fake XML could remove the insecure flag on a current release
  3. Fake XML could hide a newer release

For 2,3 by using the information that is available via composer we would be able tell the XML had likely been compromised is otherwise out of sync with Composer.

For 2 composer audit would tell us the current release is actually insecure. In this case we can tell the user something is wrong with the Update XML but if they are the latest release as known by Composer we would know there isn't actually a version to update to. If they are not on the latest release still could not recommend the update because since we would reason to believe the XML is compromised we can't trust the newer version is supported which only the XML can tell us.
For 3 composer info would tell us there is newer release that not in the XML but we still could recommend the update because it might be supported.

So in 2,3 we would need to tell the user "Currently the update information from drupal.org has likely been compromised and currently your site cannot be updated. It is recommend that check for drupal security updates [where?] and manually your site with Composer"

Remaining tasks

  1. '

Rejected ideas

This were hypothetical ways we could have solved the problem of Update XML not being TUF protected but they we didn't choose

  1. Remove Package Manager validation for the “installable” state because we need to rely on Update XML for this information which is not TUF protected. In Package Manager itself rely on `composer audit` solely for determining if package versions can be updated or installed.In Automatic Updates in addition to the `composer audit` validator provided by Package Manager rely on the information specified above in “Drupal Core’s special case” to determine what version of Drupal core can be updated to.While this solution will work well for Drupal core itself it leaves all of the other users of the Package Manager API, Project Browser included,  with the problems listed above in this issue.We could recommend that other users of the API should additionally check versions with the Update XML but that would probably beg the question why doesn’t Package Manager do this itself. If Package Manager itself does not consider it secure why should anyone else. It would it would probably also be better if Package Manager itself to be dealing update XML validation because it will have many more eyes on it than for every contrib project that uses Package Manager  to have to implement this.
  2. Do not recommend any other users use the Package Manager API beside Automatic Updates until every resource that affects on drupal.org is TUF protected.
📌 Task
Status

Fixed

Version

11.0 🔥

Component
Composer 

Last updated about 22 hours ago

No maintainer
Created by

🇺🇸United States tedbow Ithaca, NY, USA

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @tedbow
  • 🇺🇸United States drumm NY, US

    and a special Rugged instance set up to provide a TUF protected source for Drupal core itself(and other drupal/* packages that are not hosted on drupal.org?).

    Clarifying this in the issue summary. The Rugged instance for Drupal Core will cover the core components / subtree splits.

  • 🇺🇸United States drumm NY, US

    Need to get confirmation that Drupal security releases of core and contrib will also be show up in composer audit

    This is mostly correct, and I’d say good to rely on.

    There is an "insecure" label for releases used in update status XML. This is a separate source of data that can diverge from the affected versions in Composer audit. Use SA Affected Version to determine whether old versions are insecure Active has some more details. Practically, these should match up. Composer audit may be fully updated up to a couple minutes earlier than update status XML. There are a handful of releases, mostly older, probably less than 100, marked as insecure without an advisory for Composer audit. These would be non-stable contrib releases, like a 8.x-1.0-beta1, which got marked as insecure outside of the normal security team process. We could audit these to reconcile the data if needed.

  • 🇺🇸United States drumm NY, US

    Need to confirm that getting all relevant the metadata that is only in Update XML into composer metadata or other TUF protect targets is not on the short term road map for the DA.

    If needed, we can add a “release is on a supported branch” flag to the extra metadata section. Or we could have a “supported branch version constraint” added to the package’s extra metadata section. Either would not take a huge amount of effort and could be done short term.

    We could also fabricate security advisory metadata to flag unsupported releases with Composer audit. This is somewhat of an abuse of the API, unsupported without a security advisory isn’t the same as having a security advisory. In particular, Drupal projects with future versions that are not yet supported would be especially weird being flagged in Composer audit; Drupal maintainers should probably not do this anyway, the release stability is the way to show how stable the releases on a new branch are. If this is the way to go, it would not take a huge amount of effort and could be done short term.

    In an ideal world, this would be natively supported in Composer via https://github.com/composer/composer/issues/8272 or equivalent. So we aren’t implementing something too Drupal-specific.

  • 🇺🇸United States drumm NY, US

    While we can quickly metadata about supported branches on packages.drupal.org, I agree with tedbow that relying on update status XML for this looks best right now. When/if a resolution for https://github.com/composer/composer/issues/8272 lands, that would be ideal as a permanent home of the metadata. Anything we add to the metadata is effectively permanent, we don’t want to add anything too hastily.

  • 🇺🇸United States tedbow Ithaca, NY, USA

    Bumping this up to critical.

    I generally don't do this on core issues but @xjm set 🐛 Exceptions in batch no longer are shown on the page when Javascript is disabled Needs work to critical because

    This blocks AU in core and is therefore critical.

    This also applies to this issue as depending on what decision is made here it could lead to major work in the module and on the drupal.org infrastructure, though I don't think it needs to as I agree with @drumm on #5

    I have postponed 🐛 Rely on TUF-protected resources to determine which updates are available Postponed: needs info which is last known major core alpha security issue in the module itself on 🌱 Drupal 10 Core Roadmap for Automatic Updates Active

  • 🇬🇧United Kingdom catch

    There appears to be only one proposed solution, with sub-items underneath, and no #2 - is that correct or is one of the sub-items at the wrong level?

  • Assigned to tedbow
  • 🇺🇸United States tedbow Ithaca, NY, USA

    @catch I probably got the formatting, wrong will fix

  • Issue was unassigned.
  • 🇺🇸United States tedbow Ithaca, NY, USA
  • 🇬🇧United Kingdom catch

    This would mean that even if the Update XML was compromised you could not “hide”(freeze attack) a newer version of a modul

    Say we got into this actual situation, what would happen. Composer would know about the new release, but update XML wouldn't, would we then assume that 'missing' releases from update XML are because it's compromised, and allow an update?

    Overall #1 sounds like the much better option, if we're slowly able to move more metadata into composer later, then we can do that transparently over time.

  • 🇺🇸United States tedbow Ithaca, NY, USA

    @catch we would have to figure that out.

    For Drupal core I think we could use the Drupal Core’s special case reasoning in the issue summary to only rely Composer metadata

    For package manager in general where we want to expose an API to determine what is installable, basically Project Browsers use case, I think we could not allow the install and when we support contrib updates I don't think we could not allow the update.

    This is because for all we know the reason someone compromised the XML and removed newest releases is that these releases are unsupported. So they are trying to trick the site from moving from a current installed version, 1.0.1 where 1.0.x is supported and secure, to 1.2.1, where 1.2.x is not supported(and therefore can't be considered secure because the security team would not put an SA). Or in Project Browsers case they are trying to trick the site into installing 1.2.x instead of 1.0.1

    I think in this case we just have show the user an error and say the system is not usable right now.

  • 🇬🇧United Kingdom catch

    I think in this case we just have show the user an error and say the system is not usable right now.

    That makes sense, then we assume that if it's really compromised somewhere, it'll be recovered and start working again, but default to not making any changes.

    Also agree with making use of core's hard-coding of minor release cycles.

  • 🇬🇧United Kingdom catch

    Switching this from release manager review to framework manager review, seems like a security/functionality question not really about bc (except for d.o packagist data which it will help us stuffing extra things into in a rush, but core doesn't produce that).

  • 🇬🇧United Kingdom catch

    My general feeling here is:

    1. We should start with project XML data, since prematurely adding something to packagist data could cause us problems down the line.

    If the worst thing someone can do is a freeze attack (and if we can show an error that the system is broken, maybe even prompt them to check the announcements feed?) that to me is in the category of lesser risks compared to everything else that could go wrong. Would be good to e-mail the site admin if that error state happens similar to update status e-mails in case the site is infrequently visited by admins.

    2. I think that automatic updates forces this to use the https URL already independent of the update status configuration which still allows http? If so could we document that in the issue summary?

    3. We should have a follow-up issue for moving/duplicating the data to the packagist endpoint. I don't think this issue should be alpha or beta blocking, I think we should defer deciding whether it's stable blocking until that issue is open and in progress. For me, I think if it turns out to be easy, it's worth doing asap, but if it's not, it's better to do it without a 'deadline' to get it right - unless we come up with new risk vectors from the update XML feed in the process.

    Would be great to get more opinions here.

  • 🇬🇧United Kingdom catch

    To summarise #10 and #11, hopefully correctly:

    1. Update XML, assuming we rely on it, would be relied upon for installability of a version, not its existence. So for example say a module has supported 1 and 2 branches, and an unsupported an abandoned dead end 3.x branch, that kind of information is only currently available from update XML. If we don't check installability, we could update people to dead end branches or paper bag releases that have been withdrawn.

    There are two weakness to relying on update XML:

    A. Because we have the packagist data to compare to for the existence of releases, it would be impossible for someone to use compromised update XML to get someone to install a release that doesn't exist - because we would only install something we can see from packagist. However, they could fake that a previously uninstallable release (unsupported newer branch) is installable, and get someone to install to that, and we wouldn't be able to detect that. However if there's a security advisory that's recognisable for composer audit, we could prevent updates to known insecure versions.

    We can mitigate this for core because we know what core's release cycle is within core itself, but for contrib it would be a known weakness -however no worse than not using the update XML metadata in the first place and relying on the existing packagist APIs.

    B. Someone could hide a release entirely from update.xml or mark it as uninstallable and we'd still be able to see it in packagist, but we wouldn't know whether it was installable or not.

    If the release is hidden in update xml and visible in packagist, there are two options:

    1. Update anyway - this could lead to the 'dead end' situation similar to A.

    2. Don't update, but because we know there's a mismatch, we can show a warning that something isn't right and the site owner should check manually - this could be in the UI and/or maybe an e-mail notification.

    So the two risks from the current proposed solution are:

    1. You might get updated from an installable version of a module to an uninstallable version (but not a known insecure one as far as composer audit knows).

    2. You might get stuck on your existing version, but with a loud warning.

    What we need to decide:

    1. Is the above correct, or is there a mistake in the logic?

    2. If it's not correct, are there different mitigations that would be OK, or none?

    3. If the problem is correct and the mitigations are solid, are mitigations good enough for an alpha, beta, or stable release?

    4. At whatever point we decide it's not OK to rely on update XML, we would need to replicate the same information into d.o's packagist endpoint, but once we do that, we will need to decide on, and handle changes to, the format over time since there's not a single standard for this additional metadata.

  • 🇺🇸United States tedbow Ithaca, NY, USA

    updated the summary with the selected solution

  • 🇫🇮Finland lauriii Finland

    Thanks for explaining this in Slack and updating the issue summary based on that. I think the proposal makes sense now. At the moment, I think that the proposed approach is fine for AU stable. However, I'd like to review the actual implementation and messages before stable.

  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    I agree with everything @catch says in #14
    Thanks for taking the time to explain in slack. Sorry for the delay in getting to this.

  • Status changed to Needs work 12 months ago
  • 🇺🇸United States tedbow Ithaca, NY, USA

    @lauriii @larowlan thanks for the sign-off

    So can we mark this issue as fixed?. I am not going to start work on this until it is marked as fixed because to me that is clearest indication the decision has been made by the committer team

    However, I'd like to review the actual implementation and messages before stable.

    Of course we will first implement this is in the contrib module unless getting this done is not an Alpha core blocker.

    Setting it "Needs work" since it is not fixed. I don't think as a non-core committer I can mark these types of policy issues as fixed

  • Status changed to RTBC 12 months ago
  • 🇫🇮Finland lauriii Finland

    Marking as RTBC

  • Status changed to Fixed 11 months ago
  • 🇬🇧United Kingdom catch

    I was going to open a follow-up issue so we had something to document the idea of moving to extended Drupal.org packagist info later on (even if we decided not to do that ever, we could still explicitly rule it out), but then realised 🐛 Rely on TUF-protected resources to determine which updates are available Postponed: needs info is that issue which this was spun out of, so just moved that one to postponed/task.

    Going to go ahead and mark this fixed.

  • 🇬🇧United Kingdom catch

    After thinking about about #21 and discussing with @tedbow, we realised it would be better to have a core policy issue about the packagist endpoint changes, because after a decision, it'll need both infra and AU changes if that's what we do, so I've opened 🌱 [policy, no patch] Decide if and when automatic updates should rely only on packagist data to determine installability of modules Active .

    Also adding commit (or 'commit') credit because I forgot when marking this fixed.

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024