[WIP] CycloneDX v2.0 Specification - #652
Conversation
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
| // Pattern for markdown links at the end | ||
| const markdownLinkPattern = /\]\([^)]+\)$/; | ||
|
|
||
| return urlPattern.test(text) || markdownLinkPattern.test(text); |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
| // Pattern for markdown links at the end | ||
| const markdownLinkPattern = /\]\([^)]+\)$/; | ||
|
|
||
| return urlPattern.test(text) || markdownLinkPattern.test(text); |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
Signed-off-by: Steve Springett <steve@springett.us>
| const absoluteRootPath = path.resolve(rootSchemaPath); | ||
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
The best fix is to validate CLI-supplied paths against an explicit trusted base directory before any filesystem access. Keep current behavior (accept relative or absolute inputs) but enforce that both modelsDirectory and rootSchemaPath resolve inside a chosen safe root (here: process.cwd(), which is a sensible default for CLI execution). This prevents path traversal / arbitrary path targeting while preserving normal usage from project root.
In tools/src/main/js/bundler/bundle-schemas.js, update bundleSchemas so that:
- Compute
safeRoot = path.resolve(process.cwd()). - Resolve both inputs relative to that root:
path.resolve(safeRoot, input). - Add a helper check that ensures resolved paths are within
safeRootusingpath.relativeand rejecting absolute/outside results. - Throw a clear error before calling
fs.accessif validation fails.
No new dependencies are required; use built-in path utilities only.
| @@ -179,9 +179,19 @@ | ||
|
|
||
| async function bundleSchemas(modelsDirectory, rootSchemaPath, options = {}) { | ||
| try { | ||
| const absoluteModelsDir = path.resolve(modelsDirectory); | ||
| const absoluteRootPath = path.resolve(rootSchemaPath); | ||
| const safeRoot = path.resolve(process.cwd()); | ||
| const absoluteModelsDir = path.resolve(safeRoot, modelsDirectory); | ||
| const absoluteRootPath = path.resolve(safeRoot, rootSchemaPath); | ||
|
|
||
| const isPathWithinRoot = (targetPath, rootPath) => { | ||
| const rel = path.relative(rootPath, targetPath); | ||
| return rel && !rel.startsWith('..') && !path.isAbsolute(rel); | ||
| }; | ||
|
|
||
| if (!isPathWithinRoot(absoluteModelsDir, safeRoot) || !isPathWithinRoot(absoluteRootPath, safeRoot)) { | ||
| throw new Error(`Input paths must be within the working directory: ${safeRoot}`); | ||
| } | ||
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); |
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
To fix this safely without changing intended behavior too much, validate that the user-provided rootSchemaPath resolves to a file inside the provided modelsDirectory (the natural safe root in this script). Keep path.resolve, then add a containment check using path.relative (safer than naive startsWith for cross-platform behavior). Reject any path that is outside the models directory or resolves to a different drive/root on Windows.
Concrete changes in tools/src/main/js/bundler/bundle-schemas.js:
- In
bundleSchemasright after:const absoluteModelsDir = path.resolve(modelsDirectory);const absoluteRootPath = path.resolve(rootSchemaPath);
- Add:
const relativeRootToModels = path.relative(absoluteModelsDir, absoluteRootPath);- guard that throws if
relativeRootToModelsstarts with'..', is absolute, or (optionally) equals''(directory itself).
- Keep existing
fs.accesschecks after validation.
No new imports or dependencies are needed; path is already imported.
| @@ -182,6 +182,15 @@ | ||
| const absoluteModelsDir = path.resolve(modelsDirectory); | ||
| const absoluteRootPath = path.resolve(rootSchemaPath); | ||
|
|
||
| // Ensure the root schema path stays within the models directory. | ||
| const relativeRootToModels = path.relative(absoluteModelsDir, absoluteRootPath); | ||
| if ( | ||
| relativeRootToModels.startsWith('..') || | ||
| path.isAbsolute(relativeRootToModels) | ||
| ) { | ||
| throw new Error(`Root schema path must be within models directory: ${absoluteModelsDir}`); | ||
| } | ||
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); |
| console.log(`Output (minified): ${minifiedPath}\n`); | ||
|
|
||
| // Read all schema files in the models directory | ||
| const files = await fs.readdir(absoluteModelsDir); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
The best fix is to constrain both CLI-provided paths to a trusted root directory after normalization, and reject anything outside that root.
In this file, a practical trusted root is process.cwd() for CLI execution (current project/workspace). This preserves existing behavior for normal relative project paths, while blocking unexpected absolute/out-of-tree paths.
What to change
In tools/src/main/js/bundler/bundle-schemas.js, inside bundleSchemas(...) right after:
const absoluteModelsDir = path.resolve(modelsDirectory);const absoluteRootPath = path.resolve(rootSchemaPath);
add:
- A
trustedRootderived frompath.resolve(process.cwd()). - A helper check using
path.relative(trustedRoot, candidate)to ensure candidate is inside root. - Throw an error if either resolved path is outside trusted root.
This avoids relying on string prefix tricks and works cross-platform.
No new dependencies are required.
| @@ -181,7 +181,17 @@ | ||
| try { | ||
| const absoluteModelsDir = path.resolve(modelsDirectory); | ||
| const absoluteRootPath = path.resolve(rootSchemaPath); | ||
| const trustedRoot = path.resolve(process.cwd()); | ||
|
|
||
| const isPathWithinRoot = (candidatePath) => { | ||
| const relativePath = path.relative(trustedRoot, candidatePath); | ||
| return relativePath && !relativePath.startsWith('..') && !path.isAbsolute(relativePath); | ||
| }; | ||
|
|
||
| if (!isPathWithinRoot(absoluteModelsDir) || !isPathWithinRoot(absoluteRootPath)) { | ||
| throw new Error(`Input paths must be within project directory: ${trustedRoot}`); | ||
| } | ||
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); |
| const schemaPath = path.join(absoluteModelsDir, file); | ||
| console.log(` Reading ${file}...`); | ||
|
|
||
| const content = await fs.readFile(schemaPath, 'utf8'); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
Use a safe-root containment check for user-provided paths before any filesystem operations. The best fix here is to define an allowed base directory (current working directory is a practical default for this CLI), normalize both CLI paths with path.resolve, then reject execution unless both resolved paths stay inside that base. Also use fs.realpath to canonicalize symlinks before the containment check to avoid symlink traversal bypasses.
Concretely in tools/src/main/js/bundler/bundle-schemas.js:
- In
bundleSchemas(...)near lines 182–187, after resolving input paths, add:const allowedBaseDir = path.resolve(process.cwd());- a small helper to test containment safely.
await fs.realpath(...)for bothabsoluteModelsDirandabsoluteRootPath.- throw an error if either canonical path is outside
allowedBaseDir.
- Keep existing behavior otherwise (same outputs, same schema processing), only adding validation gates before
readdir/readFile.
No new dependency is required.
| @@ -181,14 +181,31 @@ | ||
| try { | ||
| const absoluteModelsDir = path.resolve(modelsDirectory); | ||
| const absoluteRootPath = path.resolve(rootSchemaPath); | ||
| const allowedBaseDir = path.resolve(process.cwd()); | ||
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); | ||
|
|
||
| const rootSchemaFilename = path.basename(absoluteRootPath); | ||
| const rootSchemaDir = path.dirname(absoluteRootPath); | ||
| // Resolve symlinks/canonical paths and enforce allowed base directory containment | ||
| const canonicalModelsDir = await fs.realpath(absoluteModelsDir); | ||
| const canonicalRootPath = await fs.realpath(absoluteRootPath); | ||
|
|
||
| const isPathWithin = (baseDir, targetPath) => { | ||
| const relative = path.relative(baseDir, targetPath); | ||
| return relative && !relative.startsWith('..') && !path.isAbsolute(relative); | ||
| }; | ||
|
|
||
| if ( | ||
| !isPathWithin(allowedBaseDir, canonicalModelsDir) || | ||
| !isPathWithin(allowedBaseDir, canonicalRootPath) | ||
| ) { | ||
| throw new Error(`Input paths must be within the working directory: ${allowedBaseDir}`); | ||
| } | ||
|
|
||
| const rootSchemaFilename = path.basename(canonicalRootPath); | ||
| const rootSchemaDir = path.dirname(canonicalRootPath); | ||
|
|
||
| console.log(`Models directory: ${absoluteModelsDir}`); | ||
| console.log(`Root schema: ${absoluteRootPath}`); | ||
|
|
|
|
||
| // Read the root schema | ||
| console.log(`\nReading root schema...`); | ||
| const rootContent = await fs.readFile(absoluteRootPath, 'utf8'); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
To fix this without changing intended functionality, constrain user-provided paths to a safe base directory (current working directory) after canonicalization. Specifically:
- In
bundleSchemas, canonicalizemodelsDirectoryandrootSchemaPathwithpath.resolve. - Canonicalize a trusted base root (e.g.,
process.cwd()). - Verify both resolved paths are within that base root using
path.relative(...)and reject paths that escape (..prefix or absolute relative result). - Keep existing
fs.accesschecks and subsequent logic unchanged.
This is the safest minimal change in tools/src/main/js/bundler/bundle-schemas.js around lines 180–188, requiring no new dependencies and preserving current behavior for normal in-repo usage.
| @@ -179,9 +179,19 @@ | ||
|
|
||
| async function bundleSchemas(modelsDirectory, rootSchemaPath, options = {}) { | ||
| try { | ||
| const allowedRoot = path.resolve(process.cwd()); | ||
| const absoluteModelsDir = path.resolve(modelsDirectory); | ||
| const absoluteRootPath = path.resolve(rootSchemaPath); | ||
|
|
||
| const modelsRelative = path.relative(allowedRoot, absoluteModelsDir); | ||
| const rootRelative = path.relative(allowedRoot, absoluteRootPath); | ||
| const modelsOutsideRoot = modelsRelative.startsWith('..') || path.isAbsolute(modelsRelative); | ||
| const rootOutsideRoot = rootRelative.startsWith('..') || path.isAbsolute(rootRelative); | ||
|
|
||
| if (modelsOutsideRoot || rootOutsideRoot) { | ||
| throw new Error(`Input paths must be within the working directory: ${allowedRoot}`); | ||
| } | ||
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); |
| // Write bundled (pretty) version | ||
| console.log('\nWriting bundled schema...'); | ||
| const prettyJson = JSON.stringify(finalSchema, null, 2); | ||
| await fs.writeFile(bundledPath, prettyJson); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
To fix this safely without changing intended functionality, validate that output paths remain within an allowed base directory derived from the provided models directory.
General approach: normalize paths, compute candidate output paths, then enforce containment using path.relative (or prefix checks on normalized absolute paths) before writing files.
Best concrete fix in tools/src/main/js/bundler/bundle-schemas.js:
- In
bundleSchemas, after resolvingabsoluteModelsDirandabsoluteRootPath, computeallowedOutputRoot = absoluteModelsDir. - Validate
absoluteRootPathis insideallowedOutputRoot(prevents choosing a root schema outside safe workspace). - After computing
bundledPathandminifiedPath, validate each is still withinallowedOutputRoot. - If validation fails, throw an error and abort.
- No new dependency is required; use built-in
path.relative.
This keeps existing behavior for valid inputs while preventing path traversal / arbitrary write locations.
| @@ -186,6 +186,13 @@ | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); | ||
|
|
||
| // Constrain all reads/writes to stay under the models directory | ||
| const allowedOutputRoot = absoluteModelsDir; | ||
| const rootPathRelative = path.relative(allowedOutputRoot, absoluteRootPath); | ||
| if (rootPathRelative.startsWith('..') || path.isAbsolute(rootPathRelative)) { | ||
| throw new Error(`Root schema path must be within models directory: ${allowedOutputRoot}`); | ||
| } | ||
|
|
||
| const rootSchemaFilename = path.basename(absoluteRootPath); | ||
| const rootSchemaDir = path.dirname(absoluteRootPath); | ||
|
|
||
| @@ -200,6 +207,15 @@ | ||
| const bundledPath = path.join(rootSchemaDir, bundledFilename); | ||
| const minifiedPath = path.join(rootSchemaDir, minifiedFilename); | ||
|
|
||
| const bundledRelative = path.relative(allowedOutputRoot, bundledPath); | ||
| const minifiedRelative = path.relative(allowedOutputRoot, minifiedPath); | ||
| if ( | ||
| bundledRelative.startsWith('..') || path.isAbsolute(bundledRelative) || | ||
| minifiedRelative.startsWith('..') || path.isAbsolute(minifiedRelative) | ||
| ) { | ||
| throw new Error(`Refusing to write output outside models directory: ${allowedOutputRoot}`); | ||
| } | ||
|
|
||
| console.log(`Output (bundled): ${bundledPath}`); | ||
| console.log(`Output (minified): ${minifiedPath}\n`); | ||
|
|
| console.log('\nWriting bundled schema...'); | ||
| const prettyJson = JSON.stringify(finalSchema, null, 2); | ||
| await fs.writeFile(bundledPath, prettyJson); | ||
| const bundledStats = await fs.stat(bundledPath); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
The best fix is to enforce that all computed output paths remain inside the normalized models directory (safe root), and reject execution otherwise. This preserves existing functionality for valid inputs while preventing path traversal / arbitrary write locations from user-provided rootSchemaPath.
In tools/src/main/js/bundler/bundle-schemas.js, inside bundleSchemas(...) right after computing bundledPath and minifiedPath, add a containment check:
- Normalize the trusted root with a trailing separator (e.g.,
absoluteModelsDir + path.sep). - Normalize candidate output paths with
path.resolve(...). - Verify each output path is either exactly the root directory or starts with the root+separator.
- Throw an error if either path escapes the root.
This requires no new dependency and no import changes.
| @@ -200,6 +200,20 @@ | ||
| const bundledPath = path.join(rootSchemaDir, bundledFilename); | ||
| const minifiedPath = path.join(rootSchemaDir, minifiedFilename); | ||
|
|
||
| // Ensure output files remain within the models directory | ||
| const safeRoot = path.resolve(absoluteModelsDir); | ||
| const safeRootWithSep = safeRoot.endsWith(path.sep) ? safeRoot : `${safeRoot}${path.sep}`; | ||
| const resolvedBundledPath = path.resolve(bundledPath); | ||
| const resolvedMinifiedPath = path.resolve(minifiedPath); | ||
| const bundledInSafeRoot = | ||
| resolvedBundledPath === safeRoot || resolvedBundledPath.startsWith(safeRootWithSep); | ||
| const minifiedInSafeRoot = | ||
| resolvedMinifiedPath === safeRoot || resolvedMinifiedPath.startsWith(safeRootWithSep); | ||
|
|
||
| if (!bundledInSafeRoot || !minifiedInSafeRoot) { | ||
| throw new Error('Output schema paths must be within the models directory'); | ||
| } | ||
|
|
||
| console.log(`Output (bundled): ${bundledPath}`); | ||
| console.log(`Output (minified): ${minifiedPath}\n`); | ||
|
|
| const lineCount = minifiedJson.split('\n').length; | ||
| console.log(` Minified JSON is on ${lineCount} line(s)`); | ||
|
|
||
| await fs.writeFile(minifiedPath, minifiedJson); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
The best fix is to constrain all file operations to a trusted base directory, then verify normalized paths remain inside that base before read/write. Here, the natural trusted root is modelsDirectory (already a required input and intended schema workspace). Keep existing behavior, but add a containment check after resolving paths:
-
Resolve and normalize:
absoluteModelsDir = path.resolve(modelsDirectory)absoluteRootPath = path.resolve(rootSchemaPath)
-
Enforce
absoluteRootPathis insideabsoluteModelsDirusingpath.relative:- reject if
relativePathis absolute or starts with..
- reject if
-
Build output paths and re-check containment for
bundledPathandminifiedPaththe same way before writing.
This change should be made in tools/src/main/js/bundler/bundle-schemas.js within bundleSchemas(...), near lines 182–201, adding a small helper function in the same file (above bundleSchemas) to avoid duplicate logic.
| @@ -16,6 +16,11 @@ | ||
| return typeof value === 'object' && value !== null; | ||
| } | ||
|
|
||
| function isPathInside(parentPath, childPath) { | ||
| const relative = path.relative(parentPath, childPath); | ||
| return relative && !relative.startsWith('..') && !path.isAbsolute(relative); | ||
| } | ||
|
|
||
| /** | ||
| * Resolve a JSON Pointer (RFC6901) against an object. Returns { ok: boolean, value?: any, error?: string } | ||
| */ | ||
| @@ -182,6 +187,10 @@ | ||
| const absoluteModelsDir = path.resolve(modelsDirectory); | ||
| const absoluteRootPath = path.resolve(rootSchemaPath); | ||
|
|
||
| if (!isPathInside(absoluteModelsDir, absoluteRootPath)) { | ||
| throw new Error('Root schema path must be within the models directory.'); | ||
| } | ||
|
|
||
| // Verify paths exist | ||
| await fs.access(absoluteModelsDir); | ||
| await fs.access(absoluteRootPath); | ||
| @@ -197,9 +206,13 @@ | ||
| const bundledFilename = `${baseFilename}-bundled.schema.json`; | ||
| const minifiedFilename = `${baseFilename}-bundled.min.schema.json`; | ||
|
|
||
| const bundledPath = path.join(rootSchemaDir, bundledFilename); | ||
| const minifiedPath = path.join(rootSchemaDir, minifiedFilename); | ||
| const bundledPath = path.resolve(rootSchemaDir, bundledFilename); | ||
| const minifiedPath = path.resolve(rootSchemaDir, minifiedFilename); | ||
|
|
||
| if (!isPathInside(absoluteModelsDir, bundledPath) || !isPathInside(absoluteModelsDir, minifiedPath)) { | ||
| throw new Error('Output schema paths must be within the models directory.'); | ||
| } | ||
|
|
||
| console.log(`Output (bundled): ${bundledPath}`); | ||
| console.log(`Output (minified): ${minifiedPath}\n`); | ||
|
|
| console.log(` Minified JSON is on ${lineCount} line(s)`); | ||
|
|
||
| await fs.writeFile(minifiedPath, minifiedJson); | ||
| const minifiedStats = await fs.stat(minifiedPath); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 11 hours ago
To fix this safely without changing intended functionality, validate that the computed output files remain within the same directory as the resolved root schema path before writing/stat-ing them. In general: resolve and normalize all relevant paths, then enforce a root boundary check using path.relative (or equivalent) to reject traversal/out-of-root targets.
Best fix in this file:
- In
bundleSchemas(around lines 200–201 wherebundledPathandminifiedPathare built), compute resolved output paths and verify both are contained inrootSchemaDir. - Add a small helper function (near existing helpers) to check directory containment robustly:
const relative = path.relative(baseDir, candidatePath)- Reject if
relativeis empty? (empty is fine for same path), starts with.., orpath.isAbsolute(relative).
- Throw an error if validation fails, before any file write/read on those paths.
- Keep existing behavior (outputs next to root schema) intact.
No new dependencies are needed.
| @@ -16,6 +16,11 @@ | ||
| return typeof value === 'object' && value !== null; | ||
| } | ||
|
|
||
| function isPathWithinDirectory(baseDir, targetPath) { | ||
| const relative = path.relative(baseDir, targetPath); | ||
| return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative)); | ||
| } | ||
|
|
||
| /** | ||
| * Resolve a JSON Pointer (RFC6901) against an object. Returns { ok: boolean, value?: any, error?: string } | ||
| */ | ||
| @@ -197,9 +202,13 @@ | ||
| const bundledFilename = `${baseFilename}-bundled.schema.json`; | ||
| const minifiedFilename = `${baseFilename}-bundled.min.schema.json`; | ||
|
|
||
| const bundledPath = path.join(rootSchemaDir, bundledFilename); | ||
| const minifiedPath = path.join(rootSchemaDir, minifiedFilename); | ||
| const bundledPath = path.resolve(rootSchemaDir, bundledFilename); | ||
| const minifiedPath = path.resolve(rootSchemaDir, minifiedFilename); | ||
|
|
||
| if (!isPathWithinDirectory(rootSchemaDir, bundledPath) || !isPathWithinDirectory(rootSchemaDir, minifiedPath)) { | ||
| throw new Error('Resolved output path escapes the root schema directory'); | ||
| } | ||
|
|
||
| console.log(`Output (bundled): ${bundledPath}`); | ||
| console.log(`Output (minified): ${minifiedPath}\n`); | ||
|
|
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
…ment patterns. Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Co-authored-by: Jan Kowalleck <jan.kowalleck@owasp.org> Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
move those docgen for schema-v1 to own dir, tp path the way for new docs tools
# Conflicts: # docgen/schema-v1/json/gen.sh
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
| }, | ||
| "keywords": ["json-schema", "ajv", "bundle"], | ||
| "author": "", | ||
| "license": "MIT", |
There was a problem hiding this comment.
MIT? not Apache-2.0 with NOTICE file?
chore: set default permissions
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Steve Springett <steve@springett.us>
Co-authored-by: Jan Kowalleck <jan.kowalleck@owasp.org> Signed-off-by: Steve Springett <steve@springett.us>
Co-authored-by: Jan Kowalleck <jan.kowalleck@owasp.org> Signed-off-by: Steve Springett <steve@springett.us>
…commended in https://github.com/CycloneDX/specification/pull/980/changes#r3784287089 Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Signed-off-by: Steve Springett <steve@springett.us>
Important
WORK IN PROGRESS
see Milestone for progress: https://github.com/CycloneDX/specification/milestone/2
BREAKING Changes
To be explained further.
Reasoning: Downstream spec users may build ontop of JSON schema.
To be explained further.
... TBC ...
Added
... TBD ...
Chaned
... TBD ...
Removed
... TBD ...
Misc
... TBD ...