@socketsecurity/cli-with-sentry 1.7.0 → 1.8.1
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/CHANGELOG.md +15 -0
- package/README.md +5 -5
- package/dist/cli.js +268 -213
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +4 -4
- package/dist/constants.js.map +1 -1
- package/dist/manifest-scripts/maven-extension/coana-maven-extension.jar +0 -0
- package/dist/manifest-scripts/socket-facts.init.gradle +2 -65
- package/dist/manifest-scripts/socket-facts.plugin.scala +75 -41
- package/dist/tsconfig.dts.tsbuildinfo +1 -1
- package/dist/types/commands/fix/coana-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/generated-socket-facts.d.mts +4 -2
- package/dist/types/commands/fix/generated-socket-facts.d.mts.map +1 -1
- package/dist/types/commands/manifest/scripts/assemble.d.mts +1 -5
- package/dist/types/commands/manifest/scripts/assemble.d.mts.map +1 -1
- package/dist/types/commands/manifest/scripts/facts.d.mts +15 -9
- package/dist/types/commands/manifest/scripts/facts.d.mts.map +1 -1
- package/dist/types/commands/manifest/scripts/records.d.mts +2 -7
- package/dist/types/commands/manifest/scripts/records.d.mts.map +1 -1
- package/dist/types/commands/manifest/scripts/run.d.mts.map +1 -1
- package/dist/types/commands/manifest/scripts/sidecar.d.mts +3 -1
- package/dist/types/commands/manifest/scripts/sidecar.d.mts.map +1 -1
- package/external/blessed/vendor/tng.js +1 -1
- package/external/blessed-contrib/lib/widget/charts/bar.js +2 -2
- package/external/blessed-contrib/lib/widget/charts/line.js +2 -2
- package/external/blessed-contrib/lib/widget/table.js +3 -3
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [1.8.1](https://github.com/SocketDev/socket-cli/releases/tag/v1.8.1) - 2026-10-12
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Updated the Coana CLI to v `15.12.7`.
|
|
11
|
+
|
|
12
|
+
## [1.8.0](https://github.com/SocketDev/socket-cli/releases/tag/v1.8.0) - 2026-10-12
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Socket facts for Maven, Gradle and sbt builds now record each subproject's own dependency tree, so a package is attributed only to the subprojects that actually pull it in.
|
|
16
|
+
- `socket fix` now accepts existing Socket facts files instead of asking you to delete them first.
|
|
17
|
+
- Updated the Coana CLI to v `15.12.5`.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Socket facts for sbt builds now match sbt's own classpaths: dependencies pulled in by a version-conflict winner are no longer dropped, and sibling subprojects appear only in the configurations that actually depend on them.
|
|
21
|
+
|
|
7
22
|
## [1.7.0](https://github.com/SocketDev/socket-cli/releases/tag/v1.7.0) - 2026-10-09
|
|
8
23
|
|
|
9
24
|
### Changed
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Socket CLI
|
|
2
2
|
|
|
3
3
|
[](https://socket.dev/npm/package/socket)
|
|
4
|
-
[](https://twitter.com/SocketSecurity)
|
|
5
|
+
[](https://bsky.app/profile/socket.dev)
|
|
6
6
|
|
|
7
7
|
CLI for [Socket.dev](https://socket.dev) — scan dependencies, audit packages, apply security patches, and gate installs from your terminal or CI. This is the 1.x line of the published `socket` package on npm.
|
|
8
8
|
|
|
@@ -171,8 +171,8 @@ MIT
|
|
|
171
171
|
<br/>
|
|
172
172
|
<div align="center">
|
|
173
173
|
<picture>
|
|
174
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.
|
|
175
|
-
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.
|
|
176
|
-
<img width="324" height="104" alt="Socket" src="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.
|
|
174
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.1/assets/fleet/socket-combomark-dark.svg">
|
|
175
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.1/assets/fleet/socket-combomark-light.svg">
|
|
176
|
+
<img width="324" height="104" alt="Socket" src="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.1/assets/fleet/socket-combomark-light.svg">
|
|
177
177
|
</picture>
|
|
178
178
|
</div>
|
package/dist/cli.js
CHANGED
|
@@ -1857,8 +1857,12 @@ withPaths = true) {
|
|
|
1857
1857
|
};
|
|
1858
1858
|
acc.set(factsFile, {
|
|
1859
1859
|
components: facts.components.map(paths),
|
|
1860
|
-
projects: (facts.projects ?? []).map(
|
|
1860
|
+
projects: (facts.projects ?? []).map(({
|
|
1861
|
+
children: _children,
|
|
1862
|
+
...proj
|
|
1863
|
+
}) => ({
|
|
1861
1864
|
...paths(proj),
|
|
1865
|
+
dependencies: [...(artifactPaths.directDependenciesByProject.get(proj.id) ?? [])],
|
|
1862
1866
|
classpath: [...(artifactPaths.classpathByProject.get(proj.id) ?? [])]
|
|
1863
1867
|
}))
|
|
1864
1868
|
});
|
|
@@ -2670,16 +2674,17 @@ function renderResolutionErrorReport(failures, scannedConfigs = [], tool = 'grad
|
|
|
2670
2674
|
}
|
|
2671
2675
|
|
|
2672
2676
|
const PURL_TYPE_MAVEN = 'maven';
|
|
2673
|
-
function assembleFacts(parsed, opts) {
|
|
2677
|
+
function assembleFacts(parsed, opts = {}) {
|
|
2674
2678
|
const fileExists = opts.fileExists ?? fs$1.existsSync;
|
|
2675
2679
|
const perRoot = buildPerRoot(parsed);
|
|
2676
|
-
const
|
|
2677
|
-
|
|
2678
|
-
finalNodes
|
|
2679
|
-
} = mergeById(perRoot);
|
|
2680
|
+
const finalNodes = mergeById(perRoot);
|
|
2681
|
+
const graphs = buildSubprojectGraphs(perRoot);
|
|
2680
2682
|
const tool = parsed.tool || 'gradle';
|
|
2681
|
-
const components = buildComponents(finalNodes
|
|
2682
|
-
const
|
|
2683
|
+
const components = buildComponents(finalNodes);
|
|
2684
|
+
const {
|
|
2685
|
+
dependencies,
|
|
2686
|
+
projects
|
|
2687
|
+
} = buildDependencyGraph(parsed, graphs, components);
|
|
2683
2688
|
const metadata = {
|
|
2684
2689
|
format: 'socket-facts-sbom',
|
|
2685
2690
|
tool,
|
|
@@ -2691,7 +2696,8 @@ function assembleFacts(parsed, opts) {
|
|
|
2691
2696
|
const facts = projects.length ? {
|
|
2692
2697
|
metadata,
|
|
2693
2698
|
projects,
|
|
2694
|
-
components
|
|
2699
|
+
components,
|
|
2700
|
+
dependencies
|
|
2695
2701
|
} : {
|
|
2696
2702
|
metadata,
|
|
2697
2703
|
components
|
|
@@ -2699,7 +2705,7 @@ function assembleFacts(parsed, opts) {
|
|
|
2699
2705
|
return {
|
|
2700
2706
|
facts,
|
|
2701
2707
|
report: buildReport(parsed),
|
|
2702
|
-
artifactPaths: buildArtifactPaths(finalNodes, [...parsed.projects.values()],
|
|
2708
|
+
artifactPaths: buildArtifactPaths(finalNodes, [...parsed.projects.values()], graphs, fileExists)
|
|
2703
2709
|
};
|
|
2704
2710
|
}
|
|
2705
2711
|
|
|
@@ -2758,17 +2764,15 @@ function buildPerRoot(parsed) {
|
|
|
2758
2764
|
// reachability, which needs each subproject's exact classpath.
|
|
2759
2765
|
function mergeById(perRoot) {
|
|
2760
2766
|
const finalNodes = new Map();
|
|
2761
|
-
const
|
|
2762
|
-
for (const [rootId, {
|
|
2767
|
+
for (const {
|
|
2763
2768
|
nodes,
|
|
2764
2769
|
prod
|
|
2765
|
-
}
|
|
2770
|
+
} of perRoot.values()) {
|
|
2766
2771
|
for (const [coordId, node] of nodes) {
|
|
2767
2772
|
let fn = finalNodes.get(coordId);
|
|
2768
2773
|
if (!fn) {
|
|
2769
2774
|
fn = {
|
|
2770
2775
|
coord: node.coord,
|
|
2771
|
-
children: new Set(),
|
|
2772
2776
|
prod: false,
|
|
2773
2777
|
direct: false,
|
|
2774
2778
|
project: node.project,
|
|
@@ -2782,56 +2786,14 @@ function mergeById(perRoot) {
|
|
|
2782
2786
|
if (node.direct) {
|
|
2783
2787
|
fn.direct = true;
|
|
2784
2788
|
}
|
|
2785
|
-
for (const c of node.children) {
|
|
2786
|
-
fn.children.add(c);
|
|
2787
|
-
}
|
|
2788
2789
|
for (const t of node.targets) {
|
|
2789
2790
|
fn.targets.add(t);
|
|
2790
2791
|
}
|
|
2791
|
-
if (node.direct) {
|
|
2792
|
-
let d = directByRoot.get(rootId);
|
|
2793
|
-
if (!d) {
|
|
2794
|
-
d = new Set();
|
|
2795
|
-
directByRoot.set(rootId, d);
|
|
2796
|
-
}
|
|
2797
|
-
d.add(coordId);
|
|
2798
|
-
}
|
|
2799
|
-
}
|
|
2800
|
-
}
|
|
2801
|
-
return {
|
|
2802
|
-
finalNodes,
|
|
2803
|
-
directByRoot
|
|
2804
|
-
};
|
|
2805
|
-
}
|
|
2806
|
-
function buildManifestFilesById(parsed, directByRoot, perRoot, factsFileName) {
|
|
2807
|
-
const buildFilesByCoord = new Map();
|
|
2808
|
-
for (const [rootId, ids] of directByRoot) {
|
|
2809
|
-
const root = perRoot.get(rootId);
|
|
2810
|
-
const project = parsed.projects.get(root?.projectKey ?? '');
|
|
2811
|
-
for (const id of ids) {
|
|
2812
|
-
let set = buildFilesByCoord.get(id);
|
|
2813
|
-
if (!set) {
|
|
2814
|
-
set = new Set();
|
|
2815
|
-
buildFilesByCoord.set(id, set);
|
|
2816
|
-
}
|
|
2817
|
-
const coord = root?.nodes.get(id)?.coord;
|
|
2818
|
-
// Without a known declaring script, the project's build file, even one
|
|
2819
|
-
// absent on disk: its presence marks the dependency direct here.
|
|
2820
|
-
const declared = coord && project?.declaredIn.get(`${coord.group}:${coord.name}`);
|
|
2821
|
-
const files = declared ?? [...(project?.buildFiles ?? []), ...(project?.missingBuildFiles ?? [])];
|
|
2822
|
-
for (const f of files) {
|
|
2823
|
-
set.add(f);
|
|
2824
|
-
}
|
|
2825
2792
|
}
|
|
2826
2793
|
}
|
|
2827
|
-
return
|
|
2828
|
-
0: id,
|
|
2829
|
-
1: buildFiles
|
|
2830
|
-
}) => [id, [...(factsFileName ? [factsFileName] : []), ...[...buildFiles].sort()].map(file => ({
|
|
2831
|
-
file
|
|
2832
|
-
}))]));
|
|
2794
|
+
return finalNodes;
|
|
2833
2795
|
}
|
|
2834
|
-
function buildComponents(finalNodes
|
|
2796
|
+
function buildComponents(finalNodes) {
|
|
2835
2797
|
return [...finalNodes.keys()].sort().map(id => {
|
|
2836
2798
|
const fn = finalNodes.get(id);
|
|
2837
2799
|
const c = fn.coord;
|
|
@@ -2865,92 +2827,188 @@ function buildComponents(finalNodes, manifestFilesById) {
|
|
|
2865
2827
|
if (fn.project) {
|
|
2866
2828
|
comp.firstParty = true;
|
|
2867
2829
|
}
|
|
2868
|
-
if (fn.children.size) {
|
|
2869
|
-
comp.dependencies = [...fn.children].sort();
|
|
2870
|
-
}
|
|
2871
|
-
const manifestFiles = manifestFilesById.get(id);
|
|
2872
|
-
if (manifestFiles) {
|
|
2873
|
-
comp.manifestFiles = manifestFiles;
|
|
2874
|
-
}
|
|
2875
2830
|
return comp;
|
|
2876
2831
|
});
|
|
2877
2832
|
}
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2833
|
+
|
|
2834
|
+
// One graph per subproject, its configurations merged.
|
|
2835
|
+
function buildSubprojectGraphs(perRoot) {
|
|
2836
|
+
const graphs = new Map();
|
|
2837
|
+
for (const {
|
|
2838
|
+
nodes,
|
|
2839
|
+
projectKey
|
|
2840
|
+
} of perRoot.values()) {
|
|
2841
|
+
let g = graphs.get(projectKey);
|
|
2842
|
+
if (!g) {
|
|
2843
|
+
g = {
|
|
2844
|
+
children: new Map(),
|
|
2845
|
+
direct: new Set()
|
|
2846
|
+
};
|
|
2847
|
+
graphs.set(projectKey, g);
|
|
2886
2848
|
}
|
|
2887
|
-
for (const
|
|
2888
|
-
set.
|
|
2849
|
+
for (const [coordId, node] of nodes) {
|
|
2850
|
+
let set = g.children.get(coordId);
|
|
2851
|
+
if (!set) {
|
|
2852
|
+
set = new Set();
|
|
2853
|
+
g.children.set(coordId, set);
|
|
2854
|
+
}
|
|
2855
|
+
for (const c of node.children) {
|
|
2856
|
+
set.add(c);
|
|
2857
|
+
}
|
|
2858
|
+
if (node.direct) {
|
|
2859
|
+
g.direct.add(coordId);
|
|
2860
|
+
}
|
|
2889
2861
|
}
|
|
2890
2862
|
}
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
}
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2863
|
+
return graphs;
|
|
2864
|
+
}
|
|
2865
|
+
|
|
2866
|
+
// Equal subtrees share an entry; partition refinement (coarsest bisimulation)
|
|
2867
|
+
// keeps that exact on cycles too.
|
|
2868
|
+
function buildDependencyGraph(parsed, graphs, components) {
|
|
2869
|
+
const componentIndex = new Map(components.map((c, i) => [c.id, i]));
|
|
2870
|
+
const vertexIds = new Map();
|
|
2871
|
+
const labels = [];
|
|
2872
|
+
const edges = [];
|
|
2873
|
+
const vertex = (projectKey, coordId) => {
|
|
2874
|
+
const key = `${projectKey}\t${coordId}`;
|
|
2875
|
+
let v = vertexIds.get(key);
|
|
2876
|
+
if (v === undefined) {
|
|
2877
|
+
v = labels.length;
|
|
2878
|
+
vertexIds.set(key, v);
|
|
2879
|
+
labels.push(componentIndex.get(coordId));
|
|
2880
|
+
edges.push([]);
|
|
2881
|
+
}
|
|
2882
|
+
return v;
|
|
2883
|
+
};
|
|
2884
|
+
for (const [projectKey, {
|
|
2885
|
+
children
|
|
2886
|
+
}] of graphs) {
|
|
2887
|
+
for (const [coordId, kids] of children) {
|
|
2888
|
+
const v = vertex(projectKey, coordId);
|
|
2889
|
+
for (const c of kids) {
|
|
2890
|
+
edges[v].push(vertex(projectKey, c));
|
|
2891
|
+
}
|
|
2911
2892
|
}
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2895
|
+
// Each round splits blocks by their children's blocks; a round that splits
|
|
2896
|
+
// nothing is stable.
|
|
2897
|
+
let block = [...labels];
|
|
2898
|
+
let blockCount = new Set(block).size;
|
|
2899
|
+
for (;;) {
|
|
2900
|
+
const ids = new Map();
|
|
2901
|
+
block = block.map((b, v) => {
|
|
2902
|
+
const childBlocks = [...new Set(edges[v].map(c => block[c]))].sort((x, y) => x - y);
|
|
2903
|
+
const sig = `${b}:${childBlocks.join(',')}`;
|
|
2904
|
+
let id = ids.get(sig);
|
|
2905
|
+
if (id === undefined) {
|
|
2906
|
+
id = ids.size;
|
|
2907
|
+
ids.set(sig, id);
|
|
2908
|
+
}
|
|
2909
|
+
return id;
|
|
2910
|
+
});
|
|
2911
|
+
if (ids.size === blockCount) {
|
|
2912
|
+
break;
|
|
2913
|
+
}
|
|
2914
|
+
blockCount = ids.size;
|
|
2915
|
+
}
|
|
2916
|
+
const byComponent = (a, b) => componentIndex.get(a) - componentIndex.get(b);
|
|
2917
|
+
const projects = [...parsed.projects.values()].map(p => ({
|
|
2918
|
+
p,
|
|
2919
|
+
roots: treeRoots(p.projectKey, graphs.get(p.projectKey), byComponent)
|
|
2920
|
+
})).sort((a, b) => {
|
|
2921
|
+
const ka = `${a.p.dir} ${a.p.group}:${a.p.name}`;
|
|
2922
|
+
const kb = `${b.p.dir} ${b.p.group}:${b.p.name}`;
|
|
2917
2923
|
return ka < kb ? -1 : ka > kb ? 1 : 0;
|
|
2918
2924
|
});
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
const
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
if (!set) {
|
|
2929
|
-
set = new Set();
|
|
2930
|
-
idsByProjectKey.set(projectKey, set);
|
|
2925
|
+
|
|
2926
|
+
// Post-order over the sorted projects, so the numbering is stable.
|
|
2927
|
+
const indexOfBlock = new Map();
|
|
2928
|
+
const vertexOfBlock = new Map();
|
|
2929
|
+
const dependencies = [];
|
|
2930
|
+
const visit = v => {
|
|
2931
|
+
const b = block[v];
|
|
2932
|
+
if (vertexOfBlock.has(b)) {
|
|
2933
|
+
return;
|
|
2931
2934
|
}
|
|
2932
|
-
|
|
2933
|
-
|
|
2935
|
+
vertexOfBlock.set(b, v);
|
|
2936
|
+
for (const c of [...edges[v]].sort((x, y) => labels[x] - labels[y])) {
|
|
2937
|
+
visit(c);
|
|
2938
|
+
}
|
|
2939
|
+
indexOfBlock.set(b, dependencies.length);
|
|
2940
|
+
dependencies.push({
|
|
2941
|
+
component: labels[v]
|
|
2942
|
+
});
|
|
2943
|
+
};
|
|
2944
|
+
const indexOf = v => indexOfBlock.get(block[v]);
|
|
2945
|
+
for (const {
|
|
2946
|
+
p,
|
|
2947
|
+
roots
|
|
2948
|
+
} of projects) {
|
|
2949
|
+
for (const coordId of roots) {
|
|
2950
|
+
visit(vertex(p.projectKey, coordId));
|
|
2934
2951
|
}
|
|
2935
2952
|
}
|
|
2936
|
-
const
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
if (!set) {
|
|
2941
|
-
set = new Set();
|
|
2942
|
-
classpathByProject.set(key, set);
|
|
2953
|
+
for (const [b, v] of vertexOfBlock) {
|
|
2954
|
+
const children = [...new Set(edges[v].map(indexOf))].sort((x, y) => x - y);
|
|
2955
|
+
if (children.length) {
|
|
2956
|
+
dependencies[indexOfBlock.get(b)].children = children;
|
|
2943
2957
|
}
|
|
2944
|
-
|
|
2945
|
-
|
|
2958
|
+
}
|
|
2959
|
+
return {
|
|
2960
|
+
dependencies,
|
|
2961
|
+
projects: projects.map(({
|
|
2962
|
+
p,
|
|
2963
|
+
roots
|
|
2964
|
+
}) => {
|
|
2965
|
+
const entry = {
|
|
2966
|
+
id: p.projectKey,
|
|
2967
|
+
type: PURL_TYPE_MAVEN,
|
|
2968
|
+
namespace: p.group,
|
|
2969
|
+
name: p.name,
|
|
2970
|
+
...(p.version ? {
|
|
2971
|
+
version: p.version
|
|
2972
|
+
} : {}),
|
|
2973
|
+
subprojectDir: p.dir,
|
|
2974
|
+
children: roots.map(coordId => indexOf(vertex(p.projectKey, coordId))).sort((x, y) => x - y)
|
|
2975
|
+
};
|
|
2976
|
+
if (p.buildFiles.length) {
|
|
2977
|
+
entry.manifestFiles = [...new Set(p.buildFiles)].sort().map(file => ({
|
|
2978
|
+
file
|
|
2979
|
+
}));
|
|
2980
|
+
}
|
|
2981
|
+
return entry;
|
|
2982
|
+
})
|
|
2983
|
+
};
|
|
2984
|
+
}
|
|
2985
|
+
function treeRoots(projectKey, graph, byComponent) {
|
|
2986
|
+
if (!graph) {
|
|
2987
|
+
return [];
|
|
2988
|
+
}
|
|
2989
|
+
const roots = [...graph.direct].sort(byComponent);
|
|
2990
|
+
const reached = new Set();
|
|
2991
|
+
const stack = [...roots];
|
|
2992
|
+
while (stack.length) {
|
|
2993
|
+
const id = stack.pop();
|
|
2994
|
+
if (!reached.has(id)) {
|
|
2995
|
+
reached.add(id);
|
|
2996
|
+
stack.push(...graph.children.get(id));
|
|
2946
2997
|
}
|
|
2947
2998
|
}
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
}
|
|
2999
|
+
const unreached = [...graph.children.keys()].filter(id => !reached.has(id));
|
|
3000
|
+
if (unreached.length) {
|
|
3001
|
+
throw new Error(`Resolved dependencies of ${projectKey} are not reachable from its direct dependencies: ${unreached.sort(byComponent).join(', ')}`);
|
|
3002
|
+
}
|
|
3003
|
+
return roots;
|
|
3004
|
+
}
|
|
3005
|
+
function byProject(projects, graphs, ids) {
|
|
3006
|
+
return new Map(projects.map(p => {
|
|
3007
|
+
const g = graphs.get(p.projectKey);
|
|
3008
|
+
return [p.projectKey, g ? [...ids(g)].sort() : []];
|
|
3009
|
+
}));
|
|
2952
3010
|
}
|
|
2953
|
-
function buildArtifactPaths(finalNodes, projects,
|
|
3011
|
+
function buildArtifactPaths(finalNodes, projects, graphs, fileExists) {
|
|
2954
3012
|
const pathsById = new Map();
|
|
2955
3013
|
for (const [id, fn] of finalNodes) {
|
|
2956
3014
|
if (!fn.project) {
|
|
@@ -2970,7 +3028,8 @@ function buildArtifactPaths(finalNodes, projects, perRoot, fileExists) {
|
|
|
2970
3028
|
}
|
|
2971
3029
|
return {
|
|
2972
3030
|
pathsById,
|
|
2973
|
-
classpathByProject:
|
|
3031
|
+
classpathByProject: byProject(projects, graphs, g => g.children.keys()),
|
|
3032
|
+
directDependenciesByProject: byProject(projects, graphs, g => g.direct)
|
|
2974
3033
|
};
|
|
2975
3034
|
}
|
|
2976
3035
|
function buildReport(parsed) {
|
|
@@ -3146,8 +3205,7 @@ function serializeExcludePathPatterns(paths) {
|
|
|
3146
3205
|
// project projectKey group name version dir
|
|
3147
3206
|
// projectSrc projectKey path (--with-files only)
|
|
3148
3207
|
// projectTgt projectKey path (--with-files only)
|
|
3149
|
-
// projectBuild projectKey path
|
|
3150
|
-
// declared projectKey group name path (script declaring the dependency; build-root-relative)
|
|
3208
|
+
// projectBuild projectKey path (build-root-relative; may be absent on disk)
|
|
3151
3209
|
// root rootId projectKey config prod(0|1)
|
|
3152
3210
|
// node rootId coordId group name version ext classifier direct(0|1) project
|
|
3153
3211
|
// edge rootId parentCoordId childCoordId
|
|
@@ -3222,9 +3280,7 @@ function parseRecords(text) {
|
|
|
3222
3280
|
dir: '',
|
|
3223
3281
|
sources: [],
|
|
3224
3282
|
targets: [],
|
|
3225
|
-
buildFiles: []
|
|
3226
|
-
missingBuildFiles: [],
|
|
3227
|
-
declaredIn: new Map()
|
|
3283
|
+
buildFiles: []
|
|
3228
3284
|
};
|
|
3229
3285
|
result.projects.set(key, p);
|
|
3230
3286
|
}
|
|
@@ -3268,17 +3324,7 @@ function parseRecords(text) {
|
|
|
3268
3324
|
break;
|
|
3269
3325
|
case 'projectBuild':
|
|
3270
3326
|
if (f[2]) {
|
|
3271
|
-
|
|
3272
|
-
(f[3] === 'missing' ? p.missingBuildFiles : p.buildFiles).push(f[2]);
|
|
3273
|
-
}
|
|
3274
|
-
break;
|
|
3275
|
-
case 'declared':
|
|
3276
|
-
if (f[4]) {
|
|
3277
|
-
const {
|
|
3278
|
-
declaredIn
|
|
3279
|
-
} = project(f[1] ?? '');
|
|
3280
|
-
const ga = `${f[2] ?? ''}:${f[3] ?? ''}`;
|
|
3281
|
-
declaredIn.set(ga, [...(declaredIn.get(ga) ?? []), f[4]]);
|
|
3327
|
+
project(f[1] ?? '').buildFiles.push(f[2]);
|
|
3282
3328
|
}
|
|
3283
3329
|
break;
|
|
3284
3330
|
case 'root':
|
|
@@ -3419,9 +3465,7 @@ async function assembleFromRecords(tool, out, recordsFile) {
|
|
|
3419
3465
|
artifactPaths,
|
|
3420
3466
|
facts,
|
|
3421
3467
|
report
|
|
3422
|
-
} = assembleFacts(parsed
|
|
3423
|
-
factsFileName
|
|
3424
|
-
});
|
|
3468
|
+
} = assembleFacts(parsed);
|
|
3425
3469
|
return {
|
|
3426
3470
|
buildRoot: parsed.buildRoot || undefined,
|
|
3427
3471
|
code: out.code,
|
|
@@ -8868,49 +8912,75 @@ async function getFixEnv() {
|
|
|
8868
8912
|
};
|
|
8869
8913
|
}
|
|
8870
8914
|
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
excludePaths,
|
|
8875
|
-
tmpDir
|
|
8876
|
-
}) {
|
|
8877
|
-
const {
|
|
8878
|
-
factsPaths,
|
|
8879
|
-
resolvedPathsSidecar
|
|
8880
|
-
} = await runDynamicSbomInference({
|
|
8881
|
-
cwd,
|
|
8882
|
-
excludePaths,
|
|
8883
|
-
sbtTmpDir: undefined,
|
|
8884
|
-
sidecar: true,
|
|
8885
|
-
withFiles: false
|
|
8915
|
+
async function backUp(sources, dir) {
|
|
8916
|
+
await fs.mkdir(dir, {
|
|
8917
|
+
recursive: true
|
|
8886
8918
|
});
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
await fs.writeFile(sidecarFile, JSON.stringify(resolvedPathsSidecar));
|
|
8890
|
-
}
|
|
8891
|
-
const paths = factsPaths.map(p => path.resolve(cwd, p));
|
|
8892
|
-
const backups = await Promise.all(paths.map(async (source, index) => {
|
|
8893
|
-
const backup = path.join(tmpDir, `${index}.json`);
|
|
8919
|
+
return await Promise.all(sources.map(async (source, index) => {
|
|
8920
|
+
const backup = path.join(dir, `${index}.json`);
|
|
8894
8921
|
await fs.copyFile(source, backup);
|
|
8895
8922
|
return {
|
|
8896
8923
|
backup,
|
|
8897
8924
|
source
|
|
8898
8925
|
};
|
|
8899
8926
|
}));
|
|
8927
|
+
}
|
|
8928
|
+
async function restoreAll(backups) {
|
|
8929
|
+
await Promise.all(backups.map(({
|
|
8930
|
+
backup,
|
|
8931
|
+
source
|
|
8932
|
+
}) => fs.copyFile(backup, source)));
|
|
8933
|
+
}
|
|
8934
|
+
|
|
8935
|
+
// Backed up so each fix attempt sees the pre-fix build after `git clean`, and
|
|
8936
|
+
// facts files already present are left as they were found.
|
|
8937
|
+
async function generateSocketFactsForFix({
|
|
8938
|
+
cwd,
|
|
8939
|
+
excludePaths,
|
|
8940
|
+
findFactsPaths,
|
|
8941
|
+
tmpDir
|
|
8942
|
+
}) {
|
|
8943
|
+
const existingPaths = await findFactsPaths();
|
|
8944
|
+
const originals = await backUp(existingPaths, path.join(tmpDir, 'existing'));
|
|
8945
|
+
const existing = new Set(existingPaths);
|
|
8946
|
+
const reset = async written => {
|
|
8947
|
+
await Promise.all(written.filter(p => !existing.has(p)).map(p => fs.rm(p, {
|
|
8948
|
+
force: true
|
|
8949
|
+
})));
|
|
8950
|
+
await restoreAll(originals);
|
|
8951
|
+
};
|
|
8952
|
+
let paths;
|
|
8953
|
+
let sidecarFile;
|
|
8954
|
+
try {
|
|
8955
|
+
const {
|
|
8956
|
+
factsPaths,
|
|
8957
|
+
resolvedPathsSidecar
|
|
8958
|
+
} = await runDynamicSbomInference({
|
|
8959
|
+
cwd,
|
|
8960
|
+
excludePaths,
|
|
8961
|
+
sbtTmpDir: undefined,
|
|
8962
|
+
sidecar: true,
|
|
8963
|
+
withFiles: false
|
|
8964
|
+
});
|
|
8965
|
+
paths = factsPaths.map(p => path.resolve(cwd, p));
|
|
8966
|
+
if (resolvedPathsSidecar) {
|
|
8967
|
+
sidecarFile = path.join(tmpDir, 'sidecar.json');
|
|
8968
|
+
await fs.writeFile(sidecarFile, JSON.stringify(resolvedPathsSidecar));
|
|
8969
|
+
}
|
|
8970
|
+
} catch (e) {
|
|
8971
|
+
// A failed build root aborts inference after others wrote their facts.
|
|
8972
|
+
await reset(await findFactsPaths());
|
|
8973
|
+
throw e;
|
|
8974
|
+
}
|
|
8975
|
+
const generated = new Set(paths);
|
|
8976
|
+
const backups = [...originals.filter(({
|
|
8977
|
+
source
|
|
8978
|
+
}) => !generated.has(source)), ...(await backUp(paths, path.join(tmpDir, 'generated')))];
|
|
8900
8979
|
return {
|
|
8901
8980
|
paths,
|
|
8902
8981
|
sidecarFile,
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
force: true
|
|
8906
|
-
})));
|
|
8907
|
-
},
|
|
8908
|
-
async restore() {
|
|
8909
|
-
await Promise.all(backups.map(({
|
|
8910
|
-
backup,
|
|
8911
|
-
source
|
|
8912
|
-
}) => fs.copyFile(backup, source)));
|
|
8913
|
-
}
|
|
8982
|
+
remove: () => reset(paths),
|
|
8983
|
+
restore: () => restoreAll(backups)
|
|
8914
8984
|
};
|
|
8915
8985
|
}
|
|
8916
8986
|
|
|
@@ -9121,51 +9191,36 @@ async function coanaFixWithFacts(fixConfig, factsSlot) {
|
|
|
9121
9191
|
// sibling manifest's references). --exclude stays separate as a hidden
|
|
9122
9192
|
// legacy escape hatch for the narrower "fix-application only" semantic.
|
|
9123
9193
|
const coanaExcludePatterns = [...exclude, ...excludePaths];
|
|
9124
|
-
const findScanFilepaths = () => utils.getPackageFilesForScan(['.'], supportedFiles, {
|
|
9194
|
+
const findScanFilepaths = async () => (await utils.getPackageFilesForScan(['.'], supportedFiles, {
|
|
9125
9195
|
additionalIgnores,
|
|
9126
9196
|
config: socketConfig,
|
|
9127
9197
|
cwd
|
|
9128
|
-
})
|
|
9198
|
+
})).filter(p => !utils.isReachabilityReportPath(p, {
|
|
9199
|
+
cwd,
|
|
9200
|
+
outputPath: constants.DOT_SOCKET_DOT_FACTS_JSON
|
|
9201
|
+
}));
|
|
9129
9202
|
const scanFilepaths = await findScanFilepaths();
|
|
9130
|
-
// Facts files are analysis artifacts and must be removed before re-running fix.
|
|
9131
|
-
const factsFiles = scanFilepaths.filter(utils.isSocketFactsFile);
|
|
9132
|
-
if (factsFiles.length) {
|
|
9133
|
-
if (!silence) {
|
|
9134
|
-
spinner?.stop();
|
|
9135
|
-
}
|
|
9136
|
-
return {
|
|
9137
|
-
ok: false,
|
|
9138
|
-
message: 'Found Socket facts files in manifest files',
|
|
9139
|
-
cause: `Delete the following ${words.pluralize('file', factsFiles.length)} before running socket fix again:\n` + factsFiles.map(p => ` - ${p}`).join('\n')
|
|
9140
|
-
};
|
|
9141
|
-
}
|
|
9142
9203
|
if (factsSlot) {
|
|
9143
9204
|
if (!silence) {
|
|
9144
9205
|
spinner?.stop();
|
|
9145
9206
|
logger.logger.info('Generating Socket facts for Gradle, sbt and Maven builds ...');
|
|
9146
9207
|
}
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
const partial = (await findScanFilepaths()).filter(utils.isSocketFactsFile);
|
|
9156
|
-
await Promise.all(partial.map(p => fs$1.promises.rm(p, {
|
|
9157
|
-
force: true
|
|
9158
|
-
})));
|
|
9159
|
-
throw e;
|
|
9160
|
-
}
|
|
9161
|
-
scanFilepaths.push(...factsSlot.generated.paths);
|
|
9208
|
+
factsSlot.generated = await generateSocketFactsForFix({
|
|
9209
|
+
cwd,
|
|
9210
|
+
excludePaths,
|
|
9211
|
+
findFactsPaths: async () => (await findScanFilepaths()).filter(utils.isSocketFactsFile),
|
|
9212
|
+
tmpDir: factsSlot.tmpDir
|
|
9213
|
+
});
|
|
9214
|
+
const known = new Set(scanFilepaths);
|
|
9215
|
+
scanFilepaths.push(...factsSlot.generated.paths.filter(p => !known.has(p)));
|
|
9162
9216
|
if (!silence) {
|
|
9163
9217
|
spinner?.start();
|
|
9164
9218
|
}
|
|
9165
9219
|
}
|
|
9166
9220
|
const sidecarFile = factsSlot?.generated?.sidecarFile;
|
|
9167
|
-
// Discovery only needs which artifacts the facts files resolve
|
|
9168
|
-
// fixes
|
|
9221
|
+
// Discovery only needs which artifacts the facts files resolve. Applying
|
|
9222
|
+
// fixes reads each project's tree; a Coana predating facts trees can only
|
|
9223
|
+
// tell from the sidecar's classpaths which projects resolve an artifact.
|
|
9169
9224
|
const discoveryFlags = factsSlot ? ['--maven-use-only-socket-facts'] : [];
|
|
9170
9225
|
const factsFlags = [...discoveryFlags, ...(sidecarFile ? ['--compute-artifacts-sidecar', sidecarFile] : [])];
|
|
9171
9226
|
const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, scanFilepaths, {
|
|
@@ -24505,5 +24560,5 @@ process.on('unhandledRejection', async (reason, promise) => {
|
|
|
24505
24560
|
// eslint-disable-next-line n/no-process-exit
|
|
24506
24561
|
process.exit(1);
|
|
24507
24562
|
});
|
|
24508
|
-
//# debugId=
|
|
24563
|
+
//# debugId=e5b43908-d002-4c63-b2f7-4c7336aacdb4
|
|
24509
24564
|
//# sourceMappingURL=cli.js.map
|