@preventive/triage 1.0.0-alpha.35 → 1.0.0-alpha.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/dependency-paths.d.ts +2 -0
- package/client/dependency-paths.js +24 -0
- package/common/managed/report-content.ts +31 -1
- package/out/client-managed-import.js +41 -41
- package/out/client-managed.js +67 -67
- package/out/view.js +164 -164
- package/package.json +3 -1
- package/server-managed/bundle-build-worker.js +27 -6
- package/server-managed/bundle-build.ts +4 -2
- package/server-managed/http.ts +57 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Match whole path segments, using the same directory precedence as the
|
|
2
|
+
// findings dependency filter. Less-specific directory names can be own source.
|
|
3
|
+
export function isDependencyFile(file, directory) {
|
|
4
|
+
if (typeof file !== 'string') return false
|
|
5
|
+
const path = file.replaceAll('\\', '/')
|
|
6
|
+
return path.startsWith(`${directory}/`) || path.includes(`/${directory}/`)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function dependencyDirectory(reports) {
|
|
10
|
+
let vendor = false
|
|
11
|
+
for (const report of reports) {
|
|
12
|
+
for (const group of report.groups ?? []) {
|
|
13
|
+
for (const finding of group) {
|
|
14
|
+
if (isDependencyFile(finding.file, 'node_modules')) return 'node_modules'
|
|
15
|
+
if (isDependencyFile(finding.file, 'vendor')) vendor = true
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
for (const file of Object.keys(report.tree ?? {})) {
|
|
19
|
+
if (isDependencyFile(file, 'node_modules')) return 'node_modules'
|
|
20
|
+
if (isDependencyFile(file, 'vendor')) vendor = true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return vendor ? 'vendor' : 'dependencies'
|
|
24
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { parseLinkedFindings } from '../../client/linked-findings.js'
|
|
2
|
-
import {
|
|
2
|
+
import { dependencyDirectory, isDependencyFile } from '../../client/dependency-paths.js'
|
|
3
|
+
import { detectFormat, loadFindings, parseCodexCsvToScans, readReport, reportEntries, reportRepoGithub } from '@preventive/report'
|
|
4
|
+
import { commonFileDirectory } from './repository-alias.ts'
|
|
3
5
|
|
|
4
6
|
// A managed blob retains one server identity even when a CSV contains several
|
|
5
7
|
// scans. Keep all their findings (and upstream ids) under that identity. CSV
|
|
@@ -40,3 +42,31 @@ export function managedFindingSourcePaths(findings: unknown[]): Set<string> {
|
|
|
40
42
|
}
|
|
41
43
|
return paths
|
|
42
44
|
}
|
|
45
|
+
|
|
46
|
+
// The report's own findings, in either entry shape, outside the dependency
|
|
47
|
+
// directory the local report view would choose: node_modules, else vendor,
|
|
48
|
+
// else dependencies.
|
|
49
|
+
function ownFindings(data: unknown) {
|
|
50
|
+
const objects = (reportEntries(data) ?? []).flat().filter((finding): finding is { file?: unknown } => finding != null && typeof finding === 'object')
|
|
51
|
+
const directory = dependencyDirectory([{ groups: [objects], tree: (data as { tree?: unknown } | null)?.tree }])
|
|
52
|
+
return { directory, own: objects.filter(finding => !isDependencyFile(finding.file, directory)) }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Findings name the repository of their own file. Like the local report view,
|
|
56
|
+
// a report without its own repository belongs to the one repository named by
|
|
57
|
+
// its own findings (Claude Security and Codex exports name one on every finding).
|
|
58
|
+
export function findingsRepository(data: unknown): string | null {
|
|
59
|
+
const repos = new Map<string, string>()
|
|
60
|
+
for (const finding of ownFindings(data).own) {
|
|
61
|
+
const github = reportRepoGithub(finding)
|
|
62
|
+
if (github) repos.set(github.toLowerCase(), github)
|
|
63
|
+
}
|
|
64
|
+
return repos.size === 1 ? [...repos.values()][0]! : null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// The directory shared by the files the report's own findings cite, for alias
|
|
68
|
+
// matching. Dependency paths, including cited evidence, cannot hide it.
|
|
69
|
+
export function ownFileDirectory(data: unknown): string {
|
|
70
|
+
const { directory, own } = ownFindings(data)
|
|
71
|
+
return commonFileDirectory([...managedFindingSourcePaths(own)].filter(path => !isDependencyFile(path, directory)))
|
|
72
|
+
}
|