Skip to content

Commit

Permalink
Fix cache integrity check false-positives across multiple registries (y…
Browse files Browse the repository at this point in the history
…arnpkg#7595)

* Add tests for cache integrity check

* Always store sha1 hash as part of cacheIntegrity

This prevents broken installs as a result of a package being resolved
from a registry that does not return an sha512 integrity field, such as
an internal npm registry, where the package was previously cached from
a registry that did return a sha512 integrity hash.

* Improve cache integrity check error messages
  • Loading branch information
Blasz authored and arcanis committed Oct 3, 2019
1 parent e7cc86b commit c040e79
Show file tree
Hide file tree
Showing 30 changed files with 392 additions and 6 deletions.
99 changes: 99 additions & 0 deletions __tests__/commands/install/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1165,3 +1165,102 @@ test('install skips the scripts if the yarnrc specifies skip-scripts true', () =
const ignoredScriptsMessage = reporter.lang('ignoredScripts');
expect(stdout).toMatch(ignoredScriptsMessage);
}));
describe('Cache', () => {
test('install should cache package without integrity prefix if no integrity field present', () =>
runInstall({}, 'install-update-auth-no-integrity-field', async config => {
const pkgCacheDir = path.join(
config.cwd,
'.yarn-cache',
`v${constants.CACHE_VERSION}`,
'npm-safe-buffer-5.1.1-893312af69b2123def71f57889001671eeb2c853',
);
expect(await fs.exists(pkgCacheDir)).toEqual(true);
}));
test('install should cache package with integrity suffix if integrity field present', () =>
runInstall({}, 'install-update-auth-sha512', async config => {
const pkgCacheDir = path.join(
config.cwd,
'.yarn-cache',
`v${constants.CACHE_VERSION}`,
'npm-safe-buffer-5.1.1-893312af69b2123def71f57889001671eeb2c853-integrity',
);
expect(await fs.exists(pkgCacheDir)).toEqual(true);
}));
test('install should store cached sha1 + sha512 integrity when lockfile has sha1 integrity field', () =>
runInstall({}, 'install-update-auth-sha1-safebuffer', async config => {
const pkgCacheDir = path.join(
config.cwd,
'.yarn-cache',
`v${constants.CACHE_VERSION}`,
'npm-safe-buffer-5.1.1-893312af69b2123def71f57889001671eeb2c853-integrity',
);
const pkgCacheMetaData = JSON.parse(
await fs.readFile(path.join(pkgCacheDir, 'node_modules', 'safe-buffer', constants.METADATA_FILENAME)),
);
expect(pkgCacheMetaData.remote.cacheIntegrity).toBe(
// eslint-disable-next-line max-len
'sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=',
);
}));
test('install should store cached sha1 + sha512 integrity when lockfile has sha512 integrity field', () =>
runInstall({}, 'install-update-auth-sha512', async config => {
const pkgCacheDir = path.join(
config.cwd,
'.yarn-cache',
`v${constants.CACHE_VERSION}`,
'npm-safe-buffer-5.1.1-893312af69b2123def71f57889001671eeb2c853-integrity',
);
const pkgCacheMetaData = JSON.parse(
await fs.readFile(path.join(pkgCacheDir, 'node_modules', 'safe-buffer', constants.METADATA_FILENAME)),
);
expect(pkgCacheMetaData.remote.cacheIntegrity).toBe(
// eslint-disable-next-line max-len
'sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=',
);
}));
test('install should store cached sha1 + sha512 integrity when lockfile has no integrity field', () =>
runInstall({}, 'install-update-auth-no-integrity-field', async config => {
const pkgCacheDir = path.join(
config.cwd,
'.yarn-cache',
`v${constants.CACHE_VERSION}`,
'npm-safe-buffer-5.1.1-893312af69b2123def71f57889001671eeb2c853',
);
const pkgCacheMetaData = JSON.parse(
await fs.readFile(path.join(pkgCacheDir, 'node_modules', 'safe-buffer', constants.METADATA_FILENAME)),
);

expect(pkgCacheMetaData.remote.cacheIntegrity).toBe(
// eslint-disable-next-line max-len
'sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=',
);
}));

test('install should fail when cached package integrity does not match lockfile integrity field', () =>
expect(runInstall({}, 'install-update-auth-invalid-cache-integrity')).rejects.toThrow(
// eslint-disable-next-line max-len
'Incorrect integrity when fetching from the cache for "safe-buffer". Cache has "sha512-foo sha1-bar" and remote has "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="',
));

test('install should fail when cached package hash does not match remote hash', () =>
expect(runInstall({}, 'install-update-auth-invalid-cache-hash')).rejects.toThrow(
// eslint-disable-next-line max-len
'Incorrect hash when fetching from the cache for "safe-buffer". Cache has "bad-hash" and remote has "893312af69b2123def71f57889001671eeb2c853"',
));

test('install should not fail cache integrity validation when lockfile has sha1 integrity field', () =>
expect(runInstall({}, 'install-update-auth-sha1-with-cache')).resolves.toBeUndefined());

test('install should not fail cache integrity validation when lockfile has sha512 integrity field', () =>
expect(runInstall({}, 'install-update-auth-sha512-with-cache')).resolves.toBeUndefined());

test('install should not fail cache integrity validation when lockfile has no integrity field', () =>
expect(runInstall({}, 'install-update-auth-no-integrity-field-with-cache')).resolves.toBeUndefined());
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "install-update-auth-cached-sha1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"safe-buffer": "^5.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "install-update-auth-cached-sha1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"safe-buffer": "^5.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "install-update-auth-invalid-cache-integrity",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"safe-buffer": "^5.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "install-update-auth-invalid-cache-integrity",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"safe-buffer": "^5.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "install-update-auth-no-integrity-field",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "install-update-auth-sha512",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"safe-buffer": "^5.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "install-update-auth-sha512",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"safe-buffer": "^5.1.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c040e79

Please sign in to comment.