Problem/Motivation

I would think that drupal/core-composer-scaffold definitely has the potential to alter other packages. The README has a section "Altering Scaffold Files" so you can change other package scaffold files.
Also the file-mapping section doesn't seem to put any restrictions on where you can place the scaffold files so I would assume you could put them anywhere even within another package and even overwrite files in that package.
Actually in the section composer/installers it says

However, Composer and the
composer/installers plugin have a limitation that one project cannot be moved
inside of another project. Therefore, if you use composer/installers to place
Drupal modules inside the directory web/modules/contrib, then you cannot also
use composer/installers to place files such as index.php and robots.txt
into the web directory. The drupal-scaffold plugin was created to work around
this limitation.

So it definitely sounds like you can places scaffold files inside other projects
Actually drupal/core-composer-scaffold seems like such a unique plugin that I think we might need a follow-up to force sites to opt-in the ability for other packages to use this besides the known Drupal core uses. Looking at \Drupal\Composer\Plugin\Scaffold\AllowedPackages::getTopLevelAllowedPackages():

$implicit_packages = [
      'drupal/legacy-scaffold-assets',
      'drupal/core',
    ];

These are special cases but besides that you have to opt-in packages into via the allowed-packages setting. If I look at github dependents https://github.com/drupal/core-composer-scaffold/network/dependents I don't find any. So my guess is this composer plugin is not used very much at all outside of Drupal core itself. I think like composer plugins itself a plugin like this that lets other packages copy files literally anywhere seems to be incompatible with a staged update system. In #3331310: Exclude unknown paths in project base: only allow vendor + web root + whatever drupal/core-composer-scaffold allows we attempted to determine where all files to be scaffolded were but because there is no API for this it involved copying a bunch of internal code. If we were able to get that list we would probably have to do more with it that just worry about files in the base project directory. For instance what if a plugin moves a scaffold file into a directory that we are excluding from the apply phase?

Steps to reproduce

Proposed resolution

Don't support drupal/core-composer-scaffold if you have set any allowed-packages since core's own use it implicitly allowed by AllowedPackages::getTopLevelAllowedPackages().

It think this would save use a ton of complexity and actually only affect a very few sites who probably have complex use cases which is not the primary target of AU at least.

Remaining tasks

Determine if we want to let sites to override this to allow allowed-packages to be set. We could have something like allow-non-core-scaffold-packages that is simply a true or false.

This could be done in a core-post-mvp follow-up.

We also might want to consider at some supporting any package if drupal/core-composer-scaffold provided a UI like getAllScaffoldfiles() that would return all files across all packages that are allowed. Without this I don't think we can support it.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

tedbow created an issue. See original summary.

tedbow’s picture

Issue summary: View changes
wim leers’s picture

👏 Great find, and thanks for the detailed write-up! 🙏🤩

Issue summary update: improved markup and issue links; no material changes.

This definitely improves reliability, arguably also security. Added to roadmap at #3319030: Drupal Core Roadmap for Package Manager and Update Manager because you tagged it core-mvp.

Composer and the
composer/installers plugin have a limitation that one project cannot be moved
inside of another project.

Woah, this very much sounds like the "inter-package symlinks should indeed not be allowed, but intra-package symlinks should be!" problem that is described in #3319507: Add symlink support to Composer Stager 2.0, require that version, and simplify UX & tests accordingly and being solved in https://github.com/php-tuf/composer-stager/issues/58. i.e. composer/installers makes sure that each installed package remains one atomic unit. That is exactly what the symlink support is aiming to do going forward!

(I bet they did that for composer/installers to allow parallellization in the future: if each package is an atomic unit, operations can be run in parallel. If that is not the case, they must be run serially. Clearly, the drupal/core-composer-scaffold plugin must execute after all other packages have been installed/updated!)

For instance what if a plugin moves a scaffold file into a directory that we are excluding from the apply phase?

🤔I don't understand yet how this can happen; isn't that exactly what the code in #3331310: Exclude unknown paths in project base: only allow vendor + web root + whatever drupal/core-composer-scaffold allows is proposing to do? (Take into account the targets of the scaffold plugin, and not exclude those?)

We also might want to consider at some supporting any package if drupal/core-composer-scaffold provided a UI like getAllScaffoldfiles() that would return all files across all packages that are allowed. Without this I don't think we can support it.

Very interesting! Tagging needs follow-up for that: that plugin is part of Drupal core, and so we can just file a Drupal core issue that blocks general Automatic Updates/Package Manager support for this plugin 👍

tedbow’s picture

re @Wim Leers question about

For instance what if a plugin moves a scaffold file into a directory that we are excluding from the apply phase?

What I mean is a scaffold plugin could more files into any of the directories that excluded by any of the classes in package_manager/src/PathExcluder. for instance SiteFilesExcluder excludes our files directories but for all we know a scaffold plugin could move file in there and then that file would be excluded when we apply the update to the site

wim leers’s picture

Couldn't that be prevented by ensuring that a new validator + excluder run last? 🤔

tedbow’s picture

  1. re #5 yes for sure we could figure out a way to solve it. but I think the solution would be complex and it would benefit very few sites.

    so that is why I think we should not support it for core-mvp. then we can decide later if there is actually a need to support it.

    I think if it turns out that there very few site that are affecting by this restriction then I think it might be reasonable that those sites have to custom or contrib solution

  2. I think any solution that we come up will always have the possibility of detecting a scaffold file has moved a file into a location we can't support and those preventing a critical security update from applying

    For instance we exclude directories like the file directory because 1, it could be very large, 2. we expect files could be adding there during the update process.

    If a scaffold move a file into the sites directory we would have to stop an update if we detected that.

wim leers’s picture

  1. 👍 — but we should document explicitly that this could be supported in the future
tedbow’s picture

Version: 8.x-2.x-dev » 3.0.x-dev
wim leers’s picture

Title: Do not allow drupal/core-composer-scaffold to be used by packages other than core » [PP-1]\ Do not allow drupal/core-composer-scaffold to be used by packages other than core
Related issues: +#3342227: ScaffoldFilePermissionsValidator should use ComposerInspector instead of ComposerUtility

Doesn't make sense to do this until #3342227: ScaffoldFilePermissionsValidator should use ComposerInspector instead of ComposerUtility is done, otherwise we're doing double work.

wim leers’s picture

Title: [PP-1]\ Do not allow drupal/core-composer-scaffold to be used by packages other than core » [PP-1] Do not allow drupal/core-composer-scaffold to be used by packages other than core
Status: Active » Postponed
wim leers’s picture

Title: [PP-1] Do not allow drupal/core-composer-scaffold to be used by packages other than core » Do not allow drupal/core-composer-scaffold to be used by packages other than core
Status: Postponed » Needs work
wim leers’s picture

Assigned: Unassigned » omkar.podey

Discussed this with @omkar.podey, who'd already started looking into this! 👍 He has a pretty clear idea of how to approach this, very curious to see what he comes up with! 😄

omkar.podey’s picture

Using composer/Plugin/Scaffold/AllowedPackages.php makes it easier to manage which packages are allowed to scaffold files.

sample code -

"extra": {
    "drupal-scaffold": {
      "allowed-packages": [
        "fixtures/drupal-core-fixture",
        "fixtures/scaffold-override-fixture"
      ],
      "locations": {
        "web-root": "./docroot"
      },
      "symlink": __SYMLINK__,
      "file-mapping": {
        "[web-root]/.htaccess": false,
        "[web-root]/robots.txt": "assets/robots-default.txt"
      }
    }

omkar.podey’s picture

Assigned: omkar.podey » wim leers
Status: Needs work » Needs review

@Wim.leers i talked with @phenaproxima yesterday and he confirmed that any modules not in the allowed packages list except "drupal/legacy-scaffold-assets", "drupal/core", will not be allowed to scaffold files by default, He also helped writing the documentation for drupal/core-composer-scaffold and has vouched for it's implementation (also agreed on the documentation needs to be clearer). So I was able to simplify the validator as well as the tests.

wim leers’s picture

Assigned: wim leers » Unassigned
Status: Needs review » Needs work

Looking good! And thanks for catching "strict types" just in time before my review! 😁👍

omkar.podey’s picture

Assigned: Unassigned » wim leers
Status: Needs work » Needs review
wim leers’s picture

Assigned: wim leers » Unassigned

Please just mark Needs review going forward — I will have reduced capacity for reviews. @tedbow or @phenaproxima can also review! 😊

phenaproxima’s picture

Status: Needs review » Needs work

This is looking very good. There is one choice here that I strongly object to, though.

omkar.podey’s picture

Status: Needs work » Needs review
phenaproxima’s picture

Status: Needs review » Needs work

This looks really good. Thanks for addressing my feedback! A few more things and then IMHO this is good to go.

omkar.podey’s picture

Assigned: Unassigned » omkar.podey
omkar.podey’s picture

Assigned: omkar.podey » Unassigned
Status: Needs work » Needs review
phenaproxima’s picture

Status: Needs review » Needs work

Looks great to me! This is still tagged for a follow-up, originating in #3. Once that's filed, this is RTBC!

omkar.podey’s picture

omkar.podey’s picture

Status: Needs work » Needs review
omkar.podey’s picture

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs followup

phenaproxima’s picture

Status: Reviewed & tested by the community » Fixed
wim leers’s picture

Beautiful end result! 👏😄

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.