Skip to content
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

fix(protect): skip previously patched files #2175

Merged
4 commits merged into from
Aug 20, 2021
Merged

Conversation

ghost
Copy link

@ghost ghost commented Aug 19, 2021

In the old snyk protect we used to add placeholder files to patched modules so indicate we've already patched them. The new snyk/protect doesn't do this so it attempts to patch modules that have already been patched, causing a failure.

This PR fixes that by creating the same placeholder file. The difference is that it's simpler and should work with any existing ignore rules a project might use to exclude them in their builds.

snyk protect:

[filename].snyk-[vuln-id].flag containing a timestamp.

Now:

[filename].snyk-protect.flag containing nothing.

So a project using *.snyk-*.flag will still match the same files. Like:

https://github.com/signalapp/Signal-Desktop/blob/f96246fecf4855db88d571e5825132ee4d5605c8/package.json#L435

See error logs
node ➜ .../snyk-protect/test/fixtures/fix-pr (master ✗) $ npm install
> [email protected] prepare
> npm run snyk-protect
> [email protected] snyk-protect
> snyk-protect
patched /workspaces/snyk/packages/snyk-protect/test/fixtures/fix-pr/node_modules/lodash/lodash.js
Successfully applied Snyk patches
added 2 packages, and audited 3 packages in 9s
1 high severity vulnerability
To address all issues, run:
  npm audit fix --force
Run `npm audit` for details.
node ➜ .../snyk-protect/test/fixtures/fix-pr (master ✗) $ npm install
> [email protected] prepare
> npm run snyk-protect
> [email protected] snyk-protect
> snyk-protect
Expected
  line from local file
 "        if ((key === '__proto__' || key === 'constructor' || key === 'prototype')) {" 
  to match patch line
 "        if (index != lastIndex) {" 
(node:7862) UnhandledPromiseRejectionWarning: Error: File to be patched does not match, not patching
    at patchString (/workspaces/snyk/packages/snyk-protect/test/fixtures/fix-pr/node_modules/@snyk/protect/dist/lib/patch.js:59:27)
    at Object.applyPatchToFile (/workspaces/snyk/packages/snyk-protect/test/fixtures/fix-pr/node_modules/@snyk/protect/dist/lib/patch.js:9:29)
    at /workspaces/snyk/packages/snyk-protect/test/fixtures/fix-pr/node_modules/@snyk/protect/dist/lib/index.js:68:29
    at Array.forEach ()
    at /workspaces/snyk/packages/snyk-protect/test/fixtures/fix-pr/node_modules/@snyk/protect/dist/lib/index.js:67:39
    at Array.forEach ()
    at /workspaces/snyk/packages/snyk-protect/test/fixtures/fix-pr/node_modules/@snyk/protect/dist/lib/index.js:66:24
    at Array.forEach ()
    at /workspaces/snyk/packages/snyk-protect/test/fixtures/fix-pr/node_modules/@snyk/protect/dist/lib/index.js:65:94
    at Array.forEach ()
(node:7862) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:7862) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
up to date, audited 3 packages in 2s
1 high severity vulnerability
To address all issues, run:
  npm audit fix --force
Run `npm audit` for details.

@ghost ghost changed the title fix(protect): do not attempt to patch modules twices fix(protect): do not attempt to patch modules twice Aug 19, 2021
@ghost ghost force-pushed the fix/snyk-protect-multiple branch 2 times, most recently from 176919a to f2d5d86 Compare August 19, 2021 18:41
Jahed Ahmed added 3 commits August 19, 2021 18:45
Otherwise we'll get "UnhandledPromiseRejectionWarning" warnings from
NodeJS which warns us that their behaviour will change to non-zero exit
codes in the future. We don't want that and we shouldn't block pipelines
due to failures on our end.
@ghost ghost force-pushed the fix/snyk-protect-multiple branch from f2d5d86 to b2ca8a9 Compare August 19, 2021 18:45
@ghost ghost changed the title fix(protect): do not attempt to patch modules twice fix(protect): skip previously patched files Aug 19, 2021
Comment on lines +4 to +7
.catch((error) => {
// don't block pipelines on unexpected errors
console.error(error);
});
Copy link
Author

Choose a reason for hiding this comment

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

This is existing behaviour. Previously we let NodeJS handle "unhandled rejections" which it does by printing a warning and exiting with zero. However, the warnings state they'll change it to a non-zero in the future so it's best that we handle it ourselves. We still exit with zero as errors on our end should not block pipelines.

@@ -83,7 +83,8 @@ async function protect(projectFolderPath: string) {
vuldIdAndPatches?.forEach((vp) => {
vp.patches.forEach((patchDiffs) => {
patchDiffs.patchDiffs.forEach((diff) => {
applyPatchToFile(diff, fpp.path);
const patchedPath = applyPatchToFile(diff, fpp.path);
console.log(`Patched: ${patchedPath}`);
Copy link
Author

Choose a reason for hiding this comment

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

I moved this log line here so it's clear exactly what we're printing to stdout for the user to see in a single top-level file.

Comment on lines -69 to -75
console.log(
'Expected\n line from local file\n',
JSON.stringify(currentLine),
'\n to match patch line\n',
JSON.stringify(nextLine),
'\n',
);
Copy link
Author

Choose a reason for hiding this comment

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

I moved this into the error message, otherwise it prints out back-to-front which is confusing.

@@ -94,7 +95,7 @@ async function protect(projectFolderPath: string) {
});
});

console.log('Successfully applied Snyk patches');
console.log('Applied Snyk patches.');
Copy link
Author

Choose a reason for hiding this comment

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

"Applied" already implies success. Less words, better.

project = await createProject('fix-pr');
patchedLodash = await getPatchedLodash();
});

test('patches vulnerable dependencies on install', async () => {
Copy link
Author

Choose a reason for hiding this comment

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

I tried spliting this test up so that one runs npm install then another runs it again so it's clear what the second run is looking for. However Jest doesn't fail fast, so if the first test fails, it will still execute the second test which wouldn't make sense.

@ghost ghost force-pushed the fix/snyk-protect-multiple branch from b2ca8a9 to 5e824c0 Compare August 19, 2021 19:00
@ghost ghost marked this pull request as ready for review August 19, 2021 19:01
@ghost ghost self-requested a review as a code owner August 19, 2021 19:01
@ghost ghost merged commit dd46c19 into master Aug 20, 2021
@ghost ghost deleted the fix/snyk-protect-multiple branch August 20, 2021 10:37
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant