From 44fd7a1916aacbd6d07ab108002e2f2ec7062aa6 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 8 Dec 2023 15:34:29 +0100 Subject: [PATCH 1/6] feat: hardened JSON imports Signed-off-by: Jan Kowalleck --- HISTORY.md | 4 ++++ src/_helpers.ts | 27 +++++++++++++++++++++++++++ src/builders.ts | 6 +++--- src/cli.ts | 3 ++- 4 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 src/_helpers.ts diff --git a/HISTORY.md b/HISTORY.md index 29e7e6287..3018cb2b0 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## unreleased +* Changed + * Hardened JSON imports (via [#]) + + ## 1.14.3 - 2023-12-01 * Fixed diff --git a/src/_helpers.ts b/src/_helpers.ts new file mode 100644 index 000000000..8ad636a4b --- /dev/null +++ b/src/_helpers.ts @@ -0,0 +1,27 @@ +/*! +This file is part of CycloneDX generator for NPM projects. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +SPDX-License-Identifier: Apache-2.0 +Copyright (c) OWASP Foundation. All Rights Reserved. +*/ + +import { readFileSync } from 'fs' + +export function loadJsonFile (path: string): any { + return JSON.parse(readFileSync(path, 'utf8')) + // may be replaced by `require(f, { with: { type: "json" } })` + // as soon as this spec is properly implemented. + // see https://github.com/tc39/proposal-import-attributes +} diff --git a/src/builders.ts b/src/builders.ts index 07419cd12..ab6cf486a 100644 --- a/src/builders.ts +++ b/src/builders.ts @@ -23,6 +23,7 @@ import * as normalizePackageData from 'normalize-package-data' import { type PackageURL } from 'packageurl-js' import * as path from 'path' +import { loadJsonFile } from './_helpers' import { makeNpmRunner, type runFunc } from './npmRunner' import { PropertyNames, PropertyValueBool } from './properties' import { versionCompare } from './versionCompare' @@ -350,8 +351,7 @@ export class BomBuilder { const packageJsonPath = path.join(data.path, 'package.json') try { return Object.assign( - /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - require(packageJsonPath), + loadJsonFile(packageJsonPath), data ) } catch { @@ -590,7 +590,7 @@ export class BomBuilder { for (const packageJsonPath of packageJsonPaths) { /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - const packageData = require(packageJsonPath) + const packageData = loadJsonFile(packageJsonPath) normalizePackageData(packageData /* add debug for warnings? */) const tool = this.toolBuilder.makeTool(packageData) if (tool !== undefined) { diff --git a/src/cli.ts b/src/cli.ts index 45e2b6a42..ceba5ff78 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -22,6 +22,7 @@ import { Argument, Command, Option } from 'commander' import { existsSync, openSync, writeSync } from 'fs' import { dirname, resolve } from 'path' +import { loadJsonFile } from './_helpers' import { BomBuilder, TreeBuilder } from './builders' enum OutputFormat { @@ -174,7 +175,7 @@ function makeCommand (process: NodeJS.Process): Command { ).version( // that is supposed to be the last option in the list on the help page. /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - require('../package.json').version as string + loadJsonFile('../package.json').version as string ).allowExcessArguments( false ) From c617df602bac26c153649e6015db1bb54bb8ae6f Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 8 Dec 2023 15:35:17 +0100 Subject: [PATCH 2/6] docs Signed-off-by: Jan Kowalleck --- HISTORY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 3018cb2b0..25f9eaeb4 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,8 +5,9 @@ All notable changes to this project will be documented in this file. ## unreleased * Changed - * Hardened JSON imports (via [#]) + * Hardened JSON imports (via [#1132]) +[#1132]: https://github.com/CycloneDX/cyclonedx-node-npm/pull/1132 ## 1.14.3 - 2023-12-01 From d79ef9e25445f584704fd893d1092cc6124f126e Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 8 Dec 2023 15:42:11 +0100 Subject: [PATCH 3/6] fix Signed-off-by: Jan Kowalleck --- src/cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli.ts b/src/cli.ts index ceba5ff78..64c9d5b76 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -175,7 +175,7 @@ function makeCommand (process: NodeJS.Process): Command { ).version( // that is supposed to be the last option in the list on the help page. /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - loadJsonFile('../package.json').version as string + require('../package.json').version as string ).allowExcessArguments( false ) From eed3228295c27c2ef2386ff7402f4009d7768cf6 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 8 Dec 2023 15:46:55 +0100 Subject: [PATCH 4/6] fix Signed-off-by: Jan Kowalleck --- src/builders.ts | 2 +- src/cli.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/builders.ts b/src/builders.ts index ab6cf486a..8977d7de9 100644 --- a/src/builders.ts +++ b/src/builders.ts @@ -569,7 +569,7 @@ export class BomBuilder { private * makeTools (): Generator { /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - const packageJsonPaths = ['../package.json'] + const packageJsonPaths = [path.resolve(module.path, '..', 'package.json')] const libs = [ '@cyclonedx/cyclonedx-library' diff --git a/src/cli.ts b/src/cli.ts index 64c9d5b76..ceba5ff78 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -175,7 +175,7 @@ function makeCommand (process: NodeJS.Process): Command { ).version( // that is supposed to be the last option in the list on the help page. /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - require('../package.json').version as string + loadJsonFile('../package.json').version as string ).allowExcessArguments( false ) From 2d1c88ea24758bf9f172452dfb00b32dff89d06c Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 8 Dec 2023 15:50:30 +0100 Subject: [PATCH 5/6] fix Signed-off-by: Jan Kowalleck --- src/cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli.ts b/src/cli.ts index ceba5ff78..30ddd4128 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -175,7 +175,7 @@ function makeCommand (process: NodeJS.Process): Command { ).version( // that is supposed to be the last option in the list on the help page. /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - loadJsonFile('../package.json').version as string + loadJsonFile(resolve(module.path, '..', 'package.json')).version as string ).allowExcessArguments( false ) From 344cd83c2ac198132081b7b02cb8b96e95d7d7b5 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 8 Dec 2023 15:53:32 +0100 Subject: [PATCH 6/6] tidy Signed-off-by: Jan Kowalleck --- src/builders.ts | 2 -- src/cli.ts | 1 - 2 files changed, 3 deletions(-) diff --git a/src/builders.ts b/src/builders.ts index 8977d7de9..a0c5c3b7a 100644 --- a/src/builders.ts +++ b/src/builders.ts @@ -568,7 +568,6 @@ export class BomBuilder { } private * makeTools (): Generator { - /* eslint-disable-next-line @typescript-eslint/no-var-requires */ const packageJsonPaths = [path.resolve(module.path, '..', 'package.json')] const libs = [ @@ -589,7 +588,6 @@ export class BomBuilder { /* eslint-enable no-labels */ for (const packageJsonPath of packageJsonPaths) { - /* eslint-disable-next-line @typescript-eslint/no-var-requires */ const packageData = loadJsonFile(packageJsonPath) normalizePackageData(packageData /* add debug for warnings? */) const tool = this.toolBuilder.makeTool(packageData) diff --git a/src/cli.ts b/src/cli.ts index 30ddd4128..6258365dc 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -174,7 +174,6 @@ function makeCommand (process: NodeJS.Process): Command { ) ).version( // that is supposed to be the last option in the list on the help page. - /* eslint-disable-next-line @typescript-eslint/no-var-requires */ loadJsonFile(resolve(module.path, '..', 'package.json')).version as string ).allowExcessArguments( false