Skip to content

Commit d28372b

Browse files
authored
fix: Properly detect license evidences like LICEN[CS]E.{Apache,BSD,GPL,MIT} (#1339)
fixes #1337 --------- Signed-off-by: Jan Kowalleck <[email protected]>
1 parent 1952e99 commit d28372b

File tree

14 files changed

+3837
-9
lines changed

14 files changed

+3837
-9
lines changed

HISTORY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
66

77
<!-- unreleased changes go here -->
88

9+
* Fixed
10+
* Properly detect license evidences like `LICEN[CS]E.{Apache,BSD,GPL,MIT}` ([#1337] via [#1339])
11+
12+
[#1337]: https://github.com/CycloneDX/cyclonedx-webpack-plugin/issues/1337
13+
[#1339]: https://github.com/CycloneDX/cyclonedx-webpack-plugin/pull/1339
14+
915
## 3.15.0 - 2024-10-19
1016

1117
* Added

src/_helpers.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Copyright (c) OWASP Foundation. All Rights Reserved.
1818
*/
1919

2020
import { existsSync, readFileSync } from 'fs'
21-
import { dirname, extname, isAbsolute, join, sep } from 'path'
21+
import { dirname, extname, isAbsolute, join, parse, sep } from 'path'
2222

2323
export function isNonNullable<T> (value: T): value is NonNullable<T> {
2424
// NonNullable: not null and not undefined
@@ -92,18 +92,41 @@ export function loadJsonFile (path: string): any {
9292

9393
export type MimeType = string
9494

95+
const MIME_TEXT_PLAIN: MimeType = 'text/plain'
96+
9597
const MAP_TEXT_EXTENSION_MIME: Readonly<Record<string, MimeType>> = {
96-
'': 'text/plain',
97-
'.license': 'text/plain',
98-
'.licence': 'text/plain',
98+
'': MIME_TEXT_PLAIN,
99+
// https://www.iana.org/assignments/media-types/media-types.xhtml
100+
'.csv': 'text/csv',
101+
'.htm': 'text/html',
102+
'.html': 'text/html',
99103
'.md': 'text/markdown',
104+
'.txt': MIME_TEXT_PLAIN,
100105
'.rst': 'text/prs.fallenstein.rst',
101-
'.txt': 'text/plain',
102-
'.xml': 'text/xml' // not `application/xml` -- our scope is text!
106+
'.xml': 'text/xml', // not `application/xml` -- our scope is text!
107+
// add more mime types above this line. pull-requests welcome!
108+
// license-specific files
109+
'.license': MIME_TEXT_PLAIN,
110+
'.licence': MIME_TEXT_PLAIN
103111
} as const
104112

105113
export function getMimeForTextFile (filename: string): MimeType | undefined {
106114
return MAP_TEXT_EXTENSION_MIME[extname(filename).toLowerCase()]
107115
}
108116

117+
const LICENSE_FILENAME_BASE = new Set(['licence', 'license'])
118+
const LICENSE_FILENAME_EXT = new Set([
119+
'.apache',
120+
'.bsd',
121+
'.gpl',
122+
'.mit'
123+
])
124+
125+
export function getMimeForLicenseFile (filename: string): MimeType | undefined {
126+
const { name, ext } = parse(filename.toLowerCase())
127+
return LICENSE_FILENAME_BASE.has(name) && LICENSE_FILENAME_EXT.has(ext)
128+
? MIME_TEXT_PLAIN
129+
: MAP_TEXT_EXTENSION_MIME[ext]
130+
}
131+
109132
// endregion MIME

src/extractor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import * as normalizePackageJson from 'normalize-package-data'
2323
import { dirname, join } from 'path'
2424
import type { Compilation, Module } from 'webpack'
2525

26-
import { getMimeForTextFile, getPackageDescription, isNonNullable, type PackageDescription, structuredClonePolyfill } from './_helpers'
26+
import { getMimeForLicenseFile, getPackageDescription, isNonNullable, type PackageDescription, structuredClonePolyfill } from './_helpers'
2727

2828
type WebpackLogger = Compilation['logger']
2929

@@ -148,7 +148,7 @@ export class Extractor {
148148
continue
149149
}
150150

151-
const contentType = getMimeForTextFile(pci.name)
151+
const contentType = getMimeForLicenseFile(pci.name)
152152
if (contentType === undefined) {
153153
continue
154154
}

tests/integration/__snapshots__/index.test.js.snap

Lines changed: 2129 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/index.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,25 @@ const testSetups = [
214214
file: 'dist/.well-known/sbom'
215215
}
216216
]
217+
},
218+
{
219+
dir: 'regression-issue1337',
220+
packageManager: 'npm',
221+
purpose: 'regression: find license evidence like `LICENSE.MIT`',
222+
results: [ // paths relative to `dir`
223+
{
224+
format: 'xml',
225+
file: 'dist/.bom/bom.xml'
226+
},
227+
{
228+
format: 'json',
229+
file: 'dist/.bom/bom.json'
230+
},
231+
{
232+
format: 'json',
233+
file: 'dist/.well-known/sbom'
234+
}
235+
]
217236
}
218237
// endregion regression
219238
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
** linguist-vendored
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*
2+
!/.gitignore
3+
!/.gitattributes
4+
!/README.md
5+
!/.npmrc
6+
!/package.json
7+
!/package-lock.json
8+
!/webpack.config.js
9+
!/src
10+
!/src/*
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
; see the docs: https://docs.npmjs.com/cli/v9/using-npm/config
2+
3+
package-lock=true
4+
lockfile-version=3
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Test: regression [issue#1337]
2+
3+
This setup is intended to create reproducible results (SBoM).
4+
It might install outdated, unmaintained or vulnerable components, for showcasing purposes.
5+
6+
----
7+
8+
this setup is a regression test for [issue#1337]:
9+
use packages with license files like `LICENSE.BSD` and such.
10+
11+
[issue#1337]: https://github.com/CycloneDX/cyclonedx-webpack-plugin/issues/1337

0 commit comments

Comments
 (0)