@@ -17,6 +17,7 @@ import collections
import os
import signal
import subprocess
+import json
import tarfile
from bb.fetch2 import URI
import bb
@@ -2875,7 +2876,6 @@ class CrateTest(FetcherTest):
class NPMTest(FetcherTest):
def skipIfNoNpm():
- return unittest.skip('npm disabled due to security issues')
if not shutil.which('npm'):
return unittest.skip('npm not installed')
return lambda f: f
@@ -2897,7 +2897,9 @@ class NPMTest(FetcherTest):
@skipIfNoNpm()
@skipIfNoNetwork()
def test_npm_bad_checksum(self):
- urls = ['npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=1.0.0']
+ urls = ['npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=1.0.0'
+ ';sha512sum=f2dd7d88cb9a129fbb97eb87a8b5103bab24f783420fd7587f8000a355a12bf7'
+ '83f1263230afc588123958b73e36bb241f63eaf08119aac5aa2a870bc4de9223']
# Fetch once to get a tarball
fetcher = bb.fetch.Fetch(urls, self.d)
ud = fetcher.ud[fetcher.urls[0]]
@@ -3001,8 +3003,8 @@ class NPMTest(FetcherTest):
unpackdir = os.path.join(self.unpackdir, 'foo', 'bar')
self.assertTrue(os.path.exists(os.path.join(unpackdir, 'package.json')))
+ @skipIfNoNpm()
def test_npm_no_network_no_tarball(self):
- return unittest.skip('npm disabled due to security issues')
urls = ['npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=1.0.0']
self.d.setVar('BB_NO_NETWORK', '1')
fetcher = bb.fetch.Fetch(urls, self.d)
@@ -3027,7 +3029,7 @@ class NPMTest(FetcherTest):
@skipIfNoNpm()
@skipIfNoNetwork()
def test_npm_registry_alternate(self):
- urls = ['npm://skimdb.npmjs.com;package=@savoirfairelinux/node-server-example;version=1.0.0']
+ urls = ['npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=1.0.0']
fetcher = bb.fetch.Fetch(urls, self.d)
fetcher.download()
fetcher.unpack(self.unpackdir)
@@ -3035,14 +3037,10 @@ class NPMTest(FetcherTest):
self.assertTrue(os.path.exists(os.path.join(unpackdir, 'package.json')))
@skipIfNoNpm()
- @skipIfNoNetwork()
- def test_npm_version_latest(self):
+ def test_npm_version_latest_rejected(self):
url = ['npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=latest']
- fetcher = bb.fetch.Fetch(url, self.d)
- fetcher.download()
- fetcher.unpack(self.unpackdir)
- unpackdir = os.path.join(self.unpackdir, 'npm')
- self.assertTrue(os.path.exists(os.path.join(unpackdir, 'package.json')))
+ with self.assertRaises(bb.fetch2.ParameterError):
+ bb.fetch.Fetch(url, self.d)
@skipIfNoNpm()
@skipIfNoNetwork()
@@ -3067,6 +3065,42 @@ class NPMTest(FetcherTest):
with self.assertRaises(bb.fetch2.ParameterError):
fetcher = bb.fetch.Fetch(urls, self.d)
+ @skipIfNoNpm()
+ @skipIfNoNetwork()
+ def test_npm_recipe_checksum(self):
+ """A sha512sum param in SRC_URI is forwarded to the proxy and verified."""
+ import subprocess
+ from bb.fetch2.npm import npm_integrity
+ result = subprocess.run(
+ ['npm', 'view', '--json', '@savoirfairelinux/node-server-example@1.0.0'],
+ capture_output=True, text=True)
+ if result.returncode != 0:
+ self.skipTest('npm view failed: %s' % result.stderr.strip())
+ try:
+ view = json.loads(result.stdout)
+ except json.JSONDecodeError:
+ self.skipTest('npm view returned invalid JSON')
+ integrity = view.get('dist', {}).get('integrity')
+ if not integrity:
+ self.skipTest('npm view response missing dist.integrity')
+ checksum_name, hexsum = npm_integrity(integrity)
+ urls = ['npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example'
+ ';version=1.0.0;%s=%s' % (checksum_name, hexsum)]
+ fetcher = bb.fetch.Fetch(urls, self.d)
+ ud = fetcher.ud[fetcher.urls[0]]
+ fetcher.download()
+ self.assertTrue(os.path.exists(ud.localpath))
+
+ @skipIfNoNpm()
+ @skipIfNoNetwork()
+ def test_npm_bad_recipe_checksum_rejected(self):
+ """A wrong sha512sum param in SRC_URI causes the fetch to fail."""
+ urls = ['npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example'
+ ';version=1.0.0;sha512sum=deadbeef00']
+ fetcher = bb.fetch.Fetch(urls, self.d)
+ with self.assertRaises(bb.fetch2.FetchError):
+ fetcher.download()
+
@skipIfNoNpm()
@skipIfNoNetwork()
def test_npm_registry_none(self):
@@ -3099,7 +3133,6 @@ class NPMTest(FetcherTest):
@skipIfNoNetwork()
def test_npmsw(self):
- return unittest.skip('npm disabled due to security issues')
swfile = self.create_shrinkwrap_file({
'packages': {
'node_modules/array-flatten': {
@@ -3136,7 +3169,6 @@ class NPMTest(FetcherTest):
@skipIfNoNetwork()
def test_npmsw_git(self):
- return unittest.skip('npm disabled due to security issues')
swfile = self.create_shrinkwrap_file({
'packages': {
'node_modules/cookie': {
@@ -3150,7 +3182,6 @@ class NPMTest(FetcherTest):
@skipIfNoNetwork()
def test_npmsw_dev(self):
- return unittest.skip('npm disabled due to security issues')
swfile = self.create_shrinkwrap_file({
'packages': {
'node_modules/array-flatten': {
@@ -3179,7 +3210,6 @@ class NPMTest(FetcherTest):
@skipIfNoNetwork()
def test_npmsw_destsuffix(self):
- return unittest.skip('npm disabled due to security issues')
swfile = self.create_shrinkwrap_file({
'packages': {
'node_modules/array-flatten': {
@@ -3195,7 +3225,6 @@ class NPMTest(FetcherTest):
self.assertTrue(os.path.exists(os.path.join(self.unpackdir, 'foo', 'bar', 'node_modules', 'array-flatten', 'package.json')))
def test_npmsw_no_network_no_tarball(self):
- return unittest.skip('npm disabled due to security issues')
swfile = self.create_shrinkwrap_file({
'packages': {
'node_modules/array-flatten': {
@@ -3235,7 +3264,6 @@ class NPMTest(FetcherTest):
@skipIfNoNetwork()
def test_npmsw_npm_reusability(self):
- return unittest.skip('npm disabled due to security issues')
# Fetch once with npmsw
swfile = self.create_shrinkwrap_file({
'packages': {
@@ -3258,7 +3286,6 @@ class NPMTest(FetcherTest):
@skipIfNoNetwork()
def test_npmsw_bad_checksum(self):
- return unittest.skip('npm disabled due to security issues')
# Try to fetch with bad checksum
swfile = self.create_shrinkwrap_file({
'packages': {
@@ -3355,7 +3382,6 @@ class NPMTest(FetcherTest):
@skipIfNoNetwork()
def test_npmsw_bundled(self):
- return unittest.skip('npm disabled due to security issues')
swfile = self.create_shrinkwrap_file({
'packages': {
'node_modules/array-flatten': {
Re-enable all NPMTest cases that were disabled by returning an unconditional unittest.skip(): - Fix skipIfNoNpm() dead code: the shutil.which check was unreachable after the early return. - Remove the return-skip guard from all test_npmsw_* tests; the npmsw fetcher is now re-enabled. - Restore test_npm_no_network_no_tarball with a proper @skipIfNoNpm() decorator. Adapt tests for the new npm fetcher behaviour: - Replace test_npm_version_latest (which asserted success) with test_npm_version_latest_rejected, which asserts ParameterError since version=latest is no longer accepted. Add two new tests: - test_npm_recipe_checksum: verifies that a sha512sum/sha256sum param in SRC_URI is forwarded to the proxy fetcher and the download succeeds when it matches. - test_npm_bad_recipe_checksum_rejected: verifies that a wrong checksum in the recipe causes the fetch to fail. [YOCTO #16105] Signed-off-by: Thomas Perrot <thomas.perrot@bootlin.com> --- lib/bb/tests/fetch.py | 64 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 19 deletions(-)