From afb36535253bc9da3e824d3de7d883a44160294c Mon Sep 17 00:00:00 2001 From: VitoAlbano Date: Wed, 3 Jun 2026 14:34:20 +0100 Subject: [PATCH] [ci:force] - Using audit in place of custom scripts --- .github/actions/setup/action.yml | 3 + .github/workflows/build-lib-workflow.yml | 2 +- .github/workflows/pull-request.yml | 4 +- .github/workflows/unit-test-workflow.yml | 4 +- .husky/pre-commit | 5 - package.json | 3 +- scripts/check-new-packages.mjs | 59 ----- scripts/post-install-check.mjs | 53 ---- scripts/safe-add.mjs | 159 ------------ scripts/security/lockfile-parser.mjs | 133 ---------- scripts/security/malware-checker.mjs | 294 ----------------------- scripts/security/report-printer.mjs | 95 -------- 12 files changed, 9 insertions(+), 805 deletions(-) delete mode 100644 scripts/check-new-packages.mjs delete mode 100644 scripts/post-install-check.mjs delete mode 100644 scripts/safe-add.mjs delete mode 100644 scripts/security/lockfile-parser.mjs delete mode 100644 scripts/security/malware-checker.mjs delete mode 100644 scripts/security/report-printer.mjs diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 4d29f30f65..f2c0e1693e 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -43,6 +43,9 @@ runs: - name: Install dependencies shell: bash run: pnpm install --frozen-lockfile + - name: Security audit + shell: bash + run: pnpm audit --audit-level=critical - name: Restore nx cache uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: diff --git a/.github/workflows/build-lib-workflow.yml b/.github/workflows/build-lib-workflow.yml index 5d7a8bd0d8..1936a6b928 100644 --- a/.github/workflows/build-lib-workflow.yml +++ b/.github/workflows/build-lib-workflow.yml @@ -31,7 +31,7 @@ jobs: - name: Build affected libs env: BASE_REF: ${{ inputs.base_ref }} - run: npx nx affected --target=build --base=origin/$BASE_REF --head=HEAD --configuration=production --exclude=stories + run: pnpm nx affected --target=build --base=origin/$BASE_REF --head=HEAD --configuration=production --exclude=stories - name: Save nx cache if: ${{ success() }} uses: ./.github/actions/save-nx-cache diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index f80eb60e00..834db3830b 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -209,7 +209,7 @@ jobs: - name: Run lint env: BASE_REF: ${{ github.base_ref || 'develop' }} - run: npx nx affected --target=lint --base=origin/$BASE_REF --head=HEAD + run: pnpm nx affected --target=lint --base=origin/$BASE_REF --head=HEAD - name: Save nx cache if: ${{ success() }} uses: ./.github/actions/save-nx-cache @@ -243,7 +243,7 @@ jobs: env: BASE_REF: ${{ github.base_ref || 'develop' }} run: | - npx nx affected --target=build-storybook --base=origin/$BASE_REF --head=HEAD --configuration=ci + pnpm nx affected --target=build-storybook --base=origin/$BASE_REF --head=HEAD --configuration=ci - name: Save nx cache if: ${{ success() }} uses: ./.github/actions/save-nx-cache diff --git a/.github/workflows/unit-test-workflow.yml b/.github/workflows/unit-test-workflow.yml index 07d8933eac..e025fede0f 100644 --- a/.github/workflows/unit-test-workflow.yml +++ b/.github/workflows/unit-test-workflow.yml @@ -32,7 +32,7 @@ jobs: BASE_REF: ${{ inputs.base_ref }} run: | echo "Base ref is $BASE_REF" - AFFECTED_UNIT=$(npx nx show projects --affected --target=test --base=origin/$BASE_REF --head=HEAD --select=projects --plain --exclude=cli,stories,eslint-angular) + AFFECTED_UNIT=$(pnpm nx show projects --affected --target=test --base=origin/$BASE_REF --head=HEAD --select=projects --plain --exclude=cli,stories,eslint-angular) echo "Affected projects for UNIT: $AFFECTED_UNIT" if [ -z "$AFFECTED_UNIT" ]; then @@ -73,7 +73,7 @@ jobs: env: NODE_OPTIONS: "--max-old-space-size=5120" run: | - xvfb-run --auto-servernum npx nx run ${{ matrix.project }}:test + xvfb-run --auto-servernum pnpm nx run ${{ matrix.project }}:test - name: Save nx cache if: ${{ success() }} uses: ./.github/actions/save-nx-cache diff --git a/.husky/pre-commit b/.husky/pre-commit index 7c77dc188d..ad7554c52e 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,9 +2,4 @@ export NODE_OPTIONS=--max_old_space_size=8192 -# Check new packages against security databases -if git diff --cached --name-only | grep -q "pnpm-lock.yaml"; then - node scripts/check-new-packages.mjs -fi - lint-staged diff --git a/package.json b/package.json index f792d27cef..1308e749df 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,7 @@ "author": "Hyland Software, Inc. and its affiliates", "scripts": { "preinstall": "npx only-allow pnpm", - "prepare": "husky && nx run eslint-angular:build && node scripts/post-install-check.mjs", - "add": "node scripts/safe-add.mjs", + "prepare": "husky && nx run eslint-angular:build && pnpm audit --audit-level=critical", "bundle:js-api": "nx run js-api:bundle", "bundle:cli": "nx run cli:bundle", "test:affected": "nx affected:test", diff --git a/scripts/check-new-packages.mjs b/scripts/check-new-packages.mjs deleted file mode 100644 index 5f09ca50f3..0000000000 --- a/scripts/check-new-packages.mjs +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env node - -/*! - * @license - * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * 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. - */ - -/** - * Pre-commit security check. - * - * Runs via husky pre-commit hook. - * Blocks commits containing known malicious packages. - */ - -import { readChangedPackagesFromGitDiff } from './security/lockfile-parser.mjs'; -import { checkPackagesForMalware } from './security/malware-checker.mjs'; -import { - printCheckingMessage, - printCommitBlockedWarning, - printAllPackagesClean -} from './security/report-printer.mjs'; - -async function main() { - const changedPackages = readChangedPackagesFromGitDiff(); - - if (!changedPackages.length) { - process.exit(0); - } - - printCheckingMessage(changedPackages.length); - - const malwareFindings = await checkPackagesForMalware(changedPackages); - - if (malwareFindings.length > 0) { - printCommitBlockedWarning(malwareFindings); - process.exit(1); - } - - printAllPackagesClean(); -} - -try { - await main(); -} catch (error) { - console.error('Security check error:', error.message); - process.exit(0); -} diff --git a/scripts/post-install-check.mjs b/scripts/post-install-check.mjs deleted file mode 100644 index c248eb92b5..0000000000 --- a/scripts/post-install-check.mjs +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env node - -/*! - * @license - * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * 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. - */ - -/** - * Post-install security check. - * - * Runs after pnpm install via the prepare hook. - * Warns if any installed packages are known malware. - */ - -import { join, dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -import { readAllPackagesFromLockfile } from './security/lockfile-parser.mjs'; -import { checkPackagesForMalware } from './security/malware-checker.mjs'; -import { printMalwareWarning } from './security/report-printer.mjs'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); -const ROOT_DIR = join(__dirname, '..'); -const LOCKFILE_PATH = join(ROOT_DIR, 'pnpm-lock.yaml'); - -async function main() { - const installedPackages = readAllPackagesFromLockfile(LOCKFILE_PATH); - - if (!installedPackages.length) { - return; - } - - const malwareFindings = await checkPackagesForMalware(installedPackages); - - if (malwareFindings.length > 0) { - printMalwareWarning(malwareFindings); - process.exit(1); - } -} - -main().catch(() => {}); diff --git a/scripts/safe-add.mjs b/scripts/safe-add.mjs deleted file mode 100644 index 9d8ce8ce7c..0000000000 --- a/scripts/safe-add.mjs +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env node - -/*! - * @license - * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * 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. - */ - -/** - * Safe add package. - * - * Checks packages against security databases before installing. - * Usage: pnpm run add [@version] [-- -D] - */ - -import { execSync } from 'node:child_process'; - -import { checkSinglePackageForMalware } from './security/malware-checker.mjs'; -import { - printSecurityCheckHeader, - printPackageClean, - printInstallBlockedWarning -} from './security/report-printer.mjs'; - -const NPM_REGISTRY_URL = 'https://registry.npmjs.org'; -const REQUEST_TIMEOUT_MS = 5000; - -// ============================================================================ -// ARGUMENT PARSING -// ============================================================================ - -function parsePackageArgument(argument) { - const packageMatch = argument.match(/^(@?[^@]+)(?:@(.+))?$/); - - if (!packageMatch) { - return null; - } - - return { - name: packageMatch[1], - version: packageMatch[2] || 'latest' - }; -} - -function separatePackagesAndFlags(args) { - const packageArguments = args.filter(arg => !arg.startsWith('-')); - const flagArguments = args.filter(arg => arg.startsWith('-')); - - return { - packages: packageArguments, - flags: flagArguments.join(' ') - }; -} - -// ============================================================================ -// VERSION RESOLUTION -// ============================================================================ - -async function fetchLatestVersion(packageName) { - try { - const response = await fetch(`${NPM_REGISTRY_URL}/${packageName}/latest`, { - signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) - }); - - if (!response.ok) { - return null; - } - - const packageData = await response.json(); - return packageData.version; - } catch { - return null; - } -} - -async function resolvePackageVersion(packageName, requestedVersion) { - if (requestedVersion !== 'latest') { - return requestedVersion; - } - - return fetchLatestVersion(packageName); -} - -// ============================================================================ -// PACKAGE INSTALLATION -// ============================================================================ - -function installPackages(packageNames, flags) { - const packageList = packageNames.join(' '); - const installCommand = `pnpm add ${packageList} ${flags}`.trim(); - - execSync(installCommand, { stdio: 'inherit' }); -} - -// ============================================================================ -// MAIN -// ============================================================================ - -async function validateAndCheckPackage(packageArgument) { - const parsedPackage = parsePackageArgument(packageArgument); - - if (!parsedPackage) { - console.error(`Invalid package argument: ${packageArgument}`); - process.exit(1); - } - - const resolvedVersion = await resolvePackageVersion(parsedPackage.name, parsedPackage.version); - - if (!resolvedVersion) { - console.error(`Could not resolve version for ${parsedPackage.name}`); - process.exit(1); - } - - const malwareReason = await checkSinglePackageForMalware(parsedPackage.name, resolvedVersion); - - if (malwareReason) { - printInstallBlockedWarning(parsedPackage.name, resolvedVersion, malwareReason); - process.exit(1); - } - - printPackageClean(parsedPackage.name, resolvedVersion); -} - -async function main() { - const commandLineArgs = process.argv.slice(2); - const { packages, flags } = separatePackagesAndFlags(commandLineArgs); - - if (!packages.length) { - console.log('Usage: pnpm run add [@version] [-- -D]'); - process.exit(1); - } - - printSecurityCheckHeader(); - - for (const packageArgument of packages) { - await validateAndCheckPackage(packageArgument); - } - - console.log('Installing...\n'); - installPackages(packages, flags); -} - -try { - await main(); -} catch (error) { - console.error('Error:', error.message); - process.exit(1); -} diff --git a/scripts/security/lockfile-parser.mjs b/scripts/security/lockfile-parser.mjs deleted file mode 100644 index 6a51511cbd..0000000000 --- a/scripts/security/lockfile-parser.mjs +++ /dev/null @@ -1,133 +0,0 @@ -/*! - * @license - * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * 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. - */ - -/** - * Lockfile parser - extracts package information from pnpm-lock.yaml. - */ - -import { readFileSync } from 'node:fs'; -import { execSync } from 'node:child_process'; - -// ============================================================================ -// PACKAGE NAME PARSING -// ============================================================================ - -function parsePackagePathEntry(fullPath) { - const lastAtIndex = fullPath.lastIndexOf('@'); - - if (lastAtIndex <= 0) { - return null; - } - - const packageName = fullPath.substring(0, lastAtIndex); - const packageVersion = fullPath.substring(lastAtIndex + 1); - - return { name: packageName, version: packageVersion }; -} - -function parsePackageFromDiffLine(line) { - const packagePathMatch = line.match(/^\+\s+'?\/([^']+)'?:/); - - if (!packagePathMatch) { - return null; - } - - const fullPath = packagePathMatch[1]; - const versionMatch = fullPath.match(/@(\d+\.\d+\.\d+[^/]*)/); - - if (!versionMatch) { - return null; - } - - const isScoped = fullPath.startsWith('@'); - const lastAtIndex = fullPath.lastIndexOf('@'); - const packageName = isScoped - ? fullPath.substring(0, lastAtIndex) - : fullPath.split('@')[0]; - - return { name: packageName, version: versionMatch[1] }; -} - -// ============================================================================ -// LOCKFILE READING -// ============================================================================ - -function extractPackagePathFromLine(line) { - const trimmed = line.trim(); - - if (!trimmed.startsWith("'/") && !trimmed.startsWith('/')) { - return null; - } - - const startIndex = trimmed.indexOf('/') + 1; - const endQuoteIndex = trimmed.indexOf("'", startIndex); - const endParenIndex = trimmed.indexOf('(', startIndex); - - let endIndex = trimmed.length; - if (endQuoteIndex > 0) endIndex = Math.min(endIndex, endQuoteIndex); - if (endParenIndex > 0) endIndex = Math.min(endIndex, endParenIndex); - - return trimmed.substring(startIndex, endIndex); -} - -export function readAllPackagesFromLockfile(lockfilePath) { - try { - const lockfileContent = readFileSync(lockfilePath, 'utf-8'); - const packages = []; - const lines = lockfileContent.split('\n'); - - for (const line of lines) { - const packagePath = extractPackagePathFromLine(line); - - if (packagePath) { - const parsedPackage = parsePackagePathEntry(packagePath); - - if (parsedPackage) { - packages.push(parsedPackage); - } - } - } - - return packages; - } catch { - return []; - } -} - -export function readChangedPackagesFromGitDiff() { - try { - const diffOutput = execSync('/usr/bin/git diff --cached pnpm-lock.yaml', { encoding: 'utf-8' }); - const changedPackages = []; - const diffLines = diffOutput.split('\n'); - - for (const line of diffLines) { - const isAddedLine = line.startsWith('+') && !line.startsWith('+++'); - - if (isAddedLine) { - const parsedPackage = parsePackageFromDiffLine(line); - - if (parsedPackage) { - changedPackages.push(parsedPackage); - } - } - } - - return changedPackages; - } catch { - return []; - } -} diff --git a/scripts/security/malware-checker.mjs b/scripts/security/malware-checker.mjs deleted file mode 100644 index ae87515e38..0000000000 --- a/scripts/security/malware-checker.mjs +++ /dev/null @@ -1,294 +0,0 @@ -/*! - * @license - * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * 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. - */ - -/** - * Malware checker - queries OSV and GitHub Advisory databases for known malware. - */ - -const MALWARE_KEYWORDS = ['malware', 'malicious', 'compromised', 'supply chain', 'backdoor']; -const OSV_API_URL = 'https://api.osv.dev/v1/querybatch'; -const OSV_SINGLE_API_URL = 'https://api.osv.dev/v1/query'; -const GITHUB_API_URL = 'https://api.github.com/advisories?ecosystem=npm&type=malware&per_page=100'; -const REQUEST_TIMEOUT_MS = 10000; -const BATCH_SIZE = 1000; - -// ============================================================================ -// UTILITY FUNCTIONS -// ============================================================================ - -function containsMalwareKeyword(text) { - const lowerText = text.toLowerCase(); - return MALWARE_KEYWORDS.some(keyword => lowerText.includes(keyword)); -} - -function splitIntoBatches(items, batchSize) { - const batches = []; - for (let index = 0; index < items.length; index += batchSize) { - batches.push(items.slice(index, index + batchSize)); - } - return batches; -} - -function deduplicateFindings(findings) { - return findings.filter((finding, index, array) => - array.findIndex(other => - other.name === finding.name && other.version === finding.version - ) === index - ); -} - -// ============================================================================ -// OSV API -// ============================================================================ - -function buildOsvQuery(packageName, packageVersion) { - return { - package: { name: packageName, ecosystem: 'npm' }, - version: packageVersion - }; -} - -function buildOsvBatchPayload(packages) { - return { - queries: packages.map(pkg => buildOsvQuery(pkg.name, pkg.version)) - }; -} - -function extractMalwareFromOsvVulnerability(vulnerability) { - const summaryText = [vulnerability.summary || '', vulnerability.details || ''].join(' '); - - if (containsMalwareKeyword(summaryText)) { - return vulnerability.summary || 'Malware detected'; - } - - return null; -} - -async function fetchOsvBatch(packages) { - const response = await fetch(OSV_API_URL, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(buildOsvBatchPayload(packages)), - signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS * 3) - }); - - if (!response.ok) { - return null; - } - - return response.json(); -} - -async function fetchOsvSingle(packageName, packageVersion) { - const response = await fetch(OSV_SINGLE_API_URL, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(buildOsvQuery(packageName, packageVersion)), - signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) - }); - - if (!response.ok) { - return null; - } - - return response.json(); -} - -function processBatchResults(batchResults, packages) { - const findings = []; - const results = batchResults.results || []; - - for (let index = 0; index < results.length; index++) { - const vulnerabilities = results[index].vulns || []; - - for (const vulnerability of vulnerabilities) { - const malwareReason = extractMalwareFromOsvVulnerability(vulnerability); - - if (malwareReason) { - findings.push({ - name: packages[index].name, - version: packages[index].version, - reason: malwareReason, - source: 'OSV' - }); - } - } - } - - return findings; -} - -export async function checkPackagesWithOsv(packages) { - if (!packages.length) { - return []; - } - - const allFindings = []; - const batches = splitIntoBatches(packages, BATCH_SIZE); - - for (const batch of batches) { - try { - const batchResults = await fetchOsvBatch(batch); - - if (batchResults) { - const findings = processBatchResults(batchResults, batch); - allFindings.push(...findings); - } - } catch { - // Network errors are non-fatal - } - } - - return allFindings; -} - -export async function checkSinglePackageWithOsv(packageName, packageVersion) { - try { - const data = await fetchOsvSingle(packageName, packageVersion); - - if (!data) { - return null; - } - - for (const vulnerability of data.vulns || []) { - const malwareReason = extractMalwareFromOsvVulnerability(vulnerability); - - if (malwareReason) { - return malwareReason; - } - } - } catch { - // Network errors are non-fatal - } - - return null; -} - -// ============================================================================ -// GITHUB ADVISORY API -// ============================================================================ - -async function fetchGitHubAdvisories() { - const response = await fetch(GITHUB_API_URL, { - headers: { 'Accept': 'application/vnd.github+json' }, - signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) - }); - - if (!response.ok) { - return null; - } - - return response.json(); -} - -function extractMalwarePackageNames(advisories) { - const malwarePackageNames = new Set(); - - for (const advisory of advisories) { - const vulnerabilities = advisory.vulnerabilities || []; - - for (const vulnerability of vulnerabilities) { - const packageName = vulnerability.package?.name; - - if (packageName) { - malwarePackageNames.add(packageName); - } - } - } - - return malwarePackageNames; -} - -export async function checkPackagesWithGitHub(packages) { - if (!packages.length) { - return []; - } - - const findings = []; - - try { - const advisories = await fetchGitHubAdvisories(); - - if (!advisories) { - return findings; - } - - const malwarePackageNames = extractMalwarePackageNames(advisories); - - for (const pkg of packages) { - if (malwarePackageNames.has(pkg.name)) { - findings.push({ - name: pkg.name, - version: pkg.version, - reason: 'Known malware package', - source: 'GitHub Advisory' - }); - } - } - } catch { - // Network errors are non-fatal - } - - return findings; -} - -export async function checkSinglePackageWithGitHub(packageName) { - try { - const advisories = await fetchGitHubAdvisories(); - - if (!advisories) { - return null; - } - - for (const advisory of advisories) { - const vulnerabilities = advisory.vulnerabilities || []; - - for (const vulnerability of vulnerabilities) { - if (vulnerability.package?.name === packageName) { - return advisory.summary || 'Malware advisory'; - } - } - } - } catch { - // Network errors are non-fatal - } - - return null; -} - -// ============================================================================ -// COMBINED CHECK -// ============================================================================ - -export async function checkPackagesForMalware(packages) { - const [osvFindings, githubFindings] = await Promise.all([ - checkPackagesWithOsv(packages), - checkPackagesWithGitHub(packages) - ]); - - const allFindings = [...osvFindings, ...githubFindings]; - return deduplicateFindings(allFindings); -} - -export async function checkSinglePackageForMalware(packageName, packageVersion) { - const [osvResult, githubResult] = await Promise.all([ - checkSinglePackageWithOsv(packageName, packageVersion), - checkSinglePackageWithGitHub(packageName) - ]); - - return osvResult || githubResult || null; -} diff --git a/scripts/security/report-printer.mjs b/scripts/security/report-printer.mjs deleted file mode 100644 index a26cc1556e..0000000000 --- a/scripts/security/report-printer.mjs +++ /dev/null @@ -1,95 +0,0 @@ -/*! - * @license - * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * 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. - */ - -/** - * Report printer - formats and prints security findings to console. - */ - -const SEPARATOR_CHAR = '='; -const WARNING_CHAR = '!'; -const SEPARATOR_WIDTH = 70; - -// ============================================================================ -// FORMATTING -// ============================================================================ - -function createSeparator(char = SEPARATOR_CHAR) { - return char.repeat(SEPARATOR_WIDTH); -} - -function formatPackageIdentifier(packageName, packageVersion) { - return `${packageName}@${packageVersion}`; -} - -function formatFindingLine(finding) { - const packageId = formatPackageIdentifier(finding.name, finding.version); - return ` ❌ ${packageId}\n ${finding.reason} (${finding.source})`; -} - -// ============================================================================ -// REPORT PRINTING -// ============================================================================ - -export function printMalwareWarning(findings) { - console.error('\n' + createSeparator(WARNING_CHAR)); - console.error('🚨 WARNING: MALICIOUS PACKAGES DETECTED'); - console.error(createSeparator(WARNING_CHAR) + '\n'); - - for (const finding of findings) { - console.error(formatFindingLine(finding) + '\n'); - } - - console.error('Remove these packages immediately:'); - console.error(' pnpm remove \n'); - console.error(createSeparator(WARNING_CHAR) + '\n'); -} - -export function printCommitBlockedWarning(findings) { - console.error(createSeparator()); - console.error('🚨 MALICIOUS PACKAGES DETECTED - COMMIT BLOCKED'); - console.error(createSeparator() + '\n'); - - for (const finding of findings) { - console.error(formatFindingLine(finding) + '\n'); - } - - console.error('Remove these packages before committing:'); - console.error(' pnpm remove \n'); - console.error(createSeparator() + '\n'); -} - -export function printInstallBlockedWarning(packageName, packageVersion, reason) { - console.error(`\n❌ BLOCKED: ${formatPackageIdentifier(packageName, packageVersion)}`); - console.error(` ${reason}\n`); -} - -export function printCheckingMessage(packageCount) { - console.log(`\n🔍 Checking ${packageCount} packages against security databases...\n`); -} - -export function printPackageClean(packageName, packageVersion) { - console.log(` 📦 ${formatPackageIdentifier(packageName, packageVersion)}`); - console.log(` ✅ Clean\n`); -} - -export function printAllPackagesClean() { - console.log('✅ All new packages passed security checks\n'); -} - -export function printSecurityCheckHeader() { - console.log('\n🔒 Checking packages against security databases...\n'); -}