8000 [AssetMapper] Add audit command by Jean-Beru · Pull Request #51650 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[AssetMapper] Add audit command #51650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 5, 2023
Merged

Conversation

Jean-Beru
Copy link
Contributor
@Jean-Beru Jean-Beru commented Sep 13, 2023
Q A
Branch? 6.4
Bug fix? no
New feature? yes
Deprecations? no
Tickets
License MIT
Doc PR TODO

After discussing with @WebMamba, I made this PR to introduce the importmap:audit command inspired from yarn audit and npm audit.

It reads the importmap.php and extract packages version to query the https://registry.npmjs.org/-/npm/v1/security/audits API.

image

image

];
}

private function getPackagesVersion(): array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a phpdoc describing the return type as array<string, string>

$subPathRegex = '(?<subpath>/.*)';

if (
1 === preg_match("#^https://ga.jspm.io/{$registryRegex}:{$packageRegex}@{$versionRegex}{$subPathRegex}?$#", $url, $matches)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why using a registry regex when the only valid value for something supported by the npmjs endpoint would be npm ?

For instance, if you use the gh ecosystem for cdn.jsdelivr.net URLs, you won't get an npm package name after it, so this won't be valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic has been moved to resolvers. JsDelivrEsmResolver already get the version when requiring a package. JspmResolver still use a regex (which might be improved I think).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Update] Resolver now must implement a getPackageVersion method with extract v 8000 ersion from URL.

Copy link
Contributor
@WebMamba WebMamba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wooo thanks @Jean-Beru 🧡

Copy link
Member
@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic! Thanks for creating this!

$subPathRegex = '(?<subpath>/.*)';

if (
1 === preg_match("#^https://ga.jspm.io/{$registryRegex}:{$packageRegex}@{$versionRegex}{$subPathRegex}?$#", $url, $matches)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's extract this section to the individual PackageResolverInterface classes - e.g. a new getPackageInfo(string $url): ?array which would return... an array with package and version keys or null of a resolver doesn't support the URL (or maybe we make a new small class instead of the array).

We'll need to reuse this logic for an asset-map:outdated command. So putting it in the package resolvers would allow that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the interface is an extension point of the package, I suggest using a value object rather than an array shape.

Copy link
Contributor Author
@Jean-Beru Jean-Beru Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add this check at "resolvePackages" step, add a ?string $version property to ResolvedImportMapPackage and dump it in importmap.php file. It will look like:

<?php

return [
    '@hotwired/stimulus' => [
        'url' => 'https://unpkg.com/@hotwired/stimulus@3.2.1/dist/stimulus.js',
        'version' => '3.2.1',
    ],
    'file' => [
        'path' => 'some/file.js',
    ],
];

WDYT ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can review this in the last commit.

@javiereguiluz
Copy link
Member

This looks like a nice proposal to me. Thanks Hubert.

I have a minor comment about the command output. At the bottom we can see this:

5 packages audited
* jquery
* bootstrap
* json5
* semver
* minimist

9 vulnerabilities found
* 0 Info
* 0 Low
* 6 Moderate
* 2 High
* 1 Critical

Two comments:

  • I'd remove the "N packages audited" because this list could be very long in practice and we already have that information in the Package column of the table above
  • I'd change the "N vulnerabilities found" to display them in a single line and omit the categories that have 0 issues (and sort the rest from highest to lowest)

So, this is how the output would look like:

9 vulnerabilities found: 1 Critical / 2 High / 6 Moderate

@Jean-Beru
Copy link
Contributor Author
  • I'd remove the "N packages audited" because this list could be very long in practice and we already have that information in the Package column of the table above

We can keep it to inform that, there were n packages that could not be audited.

  • I'd change the "N vulnerabilities found" to display them in a single line and omit the categories that have 0 issues (and sort the rest from highest to lowest)

Good idea. I made changes and updated screenshots in the PR description.

Copy link
Member
@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really, really nice. I left a few comments - the only major thing is that I'd like to avoid putting a version key in importmap.php unless it's needed. The other 99% of the time, we should grab the version from the url.

Thanks!

protected function initialize(InputInterface $input, OutputInterface $output): void
{
$this->io = new SymfonyStyle($input, $output);
$this->format = $input->getOption('format');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if setting these types of things on properties in commands is a normal practice. Someone else can please tell me if I'm wrong or right about that :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can move it. IMO it is more readable like this instead of passing $io in every method.

continue;
}
$installed[$entry->importName] ??= [];
$installed[$entry->importName][] = $entry->version;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can save for another PR, but probably we need to add an optional packageName to ImportMapEntry. 99% of the time the key (importName here) IS the package name. But that's not required. In fact, you can run importmap:require "vue/dist/vue.esm-bundler.js=vue to do this exact thing :).

The idea would be that packageName never appears in importmap.php unless you have changed the key, and then you would need it.

@weaverryan
Copy link
Member

We've merged in some changes to AssetMapper - let me know if you need help finishing this / fixing the conflicts :).

@Jean-Beru Jean-Beru force-pushed the feat/assetmapper-audit branch 2 times, most recently from fdc3152 to c213bbd Compare October 3, 2023 12:52
@Jean-Beru
Copy link
Contributor Author

We've merged in some changes to AssetMapper - let me know if you need help finishing this / fixing the conflicts :).

@weaverryan Thanks for the proposal. I rebased this PR, it should be OK now.

Copy link
Member
@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good to go. It's going to conflict with my #51786, which adds a version key to importmap.php (a bit similar to what's done in this PR), but if this is merged first, I can patch things up over in my PR after.

@@ -57,6 +57,7 @@ public function getEntries(): ImportMapEntries
isDownloaded: isset($data['downloaded_to']),
type: $type,
isEntrypoint: $isEntry,
version: $data['version'] ?? null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

version needs to be written also if it's not null in writeEntries().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure. it's done.

@Jean-Beru
Copy link
Contributor Author

This is good to go. It's going to conflict with my #51786, which adds a version key to importmap.php (a bit similar to what's done in this PR), but if this is merged first, I can patch things up over in my PR after.

You can ping me when your PR is merged. I'll update mine.

@fabpot fabpot force-pushed the feat/assetmapper-audit branch from ca75ec2 to 6d150fc Compare October 5, 2023 06:23
@fabpot
Copy link
Member
fabpot commented Oct 5, 2023

Thank you @Jean-Beru.

10000
@fabpot fabpot merged commit f149841 into symfony:6.4 Oct 5, 2023
@Jean-Beru Jean-Beru deleted the feat/assetmapper-audit branch October 5, 2023 06:48
chalasr added a commit that referenced this pull request Oct 5, 2023
…an LE BORGNE)

This PR was merged into the 6.4 branch.

Discussion
----------

[AssetMapper] Fix unit test in assetmapper auditor

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       |
| License       | MIT

Fix a typo in `ImportMapAuditor::audit` introduced in #51650 that causes tests to fail

Commits
-------

556486c Fix typo that causes unit test to fail
fabpot added a commit that referenced this pull request Oct 10, 2023
This PR was squashed before being merged into the 6.4 branch.

Discussion
----------

[AssetMapper] Add outdated command

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       |
| License       | MIT

As suggested by `@WebMamba`, I added a new command for the AssetMapper component to list outdated 3rd party packages. It is inspired by the `composer outdated` command so I tried to replicate its options as much as I could.
It reads the importmap.php and extract packages version to query the https://registry.npmjs.org/%package% API and read the latest version from metadata.

![image](https://github.com/symfony/symfony/assets/11990607/189f66a0-dda0-4916-a91b-988ebe8f9fb3)

:warning: The code is base on #51650 branch so it is not ready to be merged yet, but I'd be happy to get some reviews and feedback in the meantime. This is my first PR on symfony, so there will probably be a lot to say !

- [ ] gather feedback
- [x] wait for #51650 to be merged and rebase
- [ ] write documentation

Commits
-------

4d32a35 [AssetMapper] Add outdated command
nicolas-grekas added a commit that referenced this pull request Oct 19, 2023
… (weaverryan)

This PR was squashed before being merged into the 6.4 branch.

Discussion
----------

[AssetMapper] Warn of missing or incompat dependencies

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | None
| License       | MIT

Hi!

The aim of the `importmap.php` system is to be a simple way to manage your JS dependencies. But to make it robust enough for production use, it does need a few things - like the `importmap:audit` command in #51650. This PR adds a check, during `importmap:require` and `importmap:update`, that reports any missing dependencies or dependencies with invalid versions. This is necessary so that, if package `A` requires package `B`, their versions don't "drift" over time without you being aware (e.g. you update package `A` to v3 but keep package `B` at v1, even though v3 of `A` requires v2 of `B`).

<img width="1266" alt="Screenshot 2023-10-04 at 2 44 04 PM" src="https://github.com/symfony/symfony/assets/121003/3901a070-d092-494a-a7cb-3bfe5d5a99f9">

Built on top of #51786.

Cheers!

Commits
-------

42dfb9a [AssetMapper] Warn of missing or incompat dependencies
This was referenced Oct 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants
0