Skip to content

Commit d743523

Browse files
committed
feat: implement OSV format
1 parent 7915664 commit d743523

File tree

8 files changed

+168
-34
lines changed

8 files changed

+168
-34
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ export interface ExtendedStrategy<
105105
) => Promise<(VulnFormat | StandardVulnerability)[]>;
106106
}
107107

108-
export type BaseStrategyFormat = "Standard";
108+
export type BaseStrategyFormat =
109+
| "Standard"
110+
| "OSV";
109111

110112
export interface BaseStrategyOptions {
111113
useFormat?: BaseStrategyFormat;
@@ -127,6 +129,7 @@ Where `dependencies` is the dependencies **Map()** object of the NodeSecure Scan
127129
128130
### Formats
129131
- [Standard](./docs/formats/standard.md)
132+
- [OSV](./docs/formats/osv.md) (**Work In Progress**)
130133

131134
### Databases
132135
- [OSV](./docs/database/osv.md)

docs/database/osv.md

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,7 @@ Lean more at [osv.dev](https://osv.dev/)
88

99
## Format
1010

11-
The OSV interface is exported as root like `StandardVulnerability`.
12-
13-
```ts
14-
export interface OSV {
15-
schema_version: string;
16-
id: string;
17-
modified: string;
18-
published: string;
19-
withdraw: string;
20-
aliases: string[];
21-
related: string[];
22-
summary: string;
23-
details: string;
24-
severity: OSVSeverity[];
25-
affected: OSVAffected[];
26-
references: {
27-
type: OSVReferenceType;
28-
url: string;
29-
}[];
30-
credits: {
31-
name: string;
32-
contact: string[];
33-
type: OSVCreditType;
34-
}[];
35-
database_specific: Record<string, any>;
36-
}
37-
```
11+
See the [OSV format](../formats/osv.md) documentation.
3812

3913
## API
4014

docs/formats/osv.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# OSV vulnerability format
2+
3+
See [Open Source Vulnerability format](https://ossf.github.io/osv-schema/)
4+
5+
```ts
6+
export interface OSV {
7+
schema_version: string;
8+
id: string;
9+
modified: string;
10+
published: string;
11+
withdraw: string;
12+
aliases: string[];
13+
upstream: string[];
14+
related: string[];
15+
summary: string;
16+
details: string;
17+
severity: OSVSeverity[];
18+
affected: OSVAffected[];
19+
references: {
20+
type: OSVReferenceType;
21+
url: string;
22+
}[];
23+
credits: {
24+
name: string;
25+
contact: string[];
26+
type: OSVCreditType;
27+
}[];
28+
database_specific: Record<string, any>;
29+
}
30+
31+
export type OSVReferenceType = "ADVISORY" |
32+
"ARTICLE" |
33+
"DETECTION" |
34+
"DISCUSSION" |
35+
"REPORT" |
36+
"FIX" |
37+
"GIT" |
38+
"INTRODUCED" |
39+
"PACKAGE" |
40+
"EVIDENCE" |
41+
"WEB";
42+
43+
export type OSVCreditType = "FINDER" |
44+
"REPORTER" |
45+
"ANALYST" |
46+
"COORDINATOR" |
47+
"REMEDIATION_DEVELOPER" |
48+
"REMEDIATION_REVIEWER" |
49+
"REMEDIATION_VERIFIER" |
50+
"TOOL" |
51+
"SPONSOR" |
52+
"OTHER";
53+
54+
export interface OSVAffected {
55+
package: {
56+
ecosystem: "npm",
57+
name: string;
58+
purl: string;
59+
};
60+
severity: OSVSeverity[];
61+
ranges: OSVRange[];
62+
versions: string[];
63+
ecosystem_specific: Record<string, any>;
64+
database_specific: Record<string, any>;
65+
}
66+
67+
export interface OSVRange {
68+
type: string;
69+
repo: string;
70+
events: {
71+
introduced?: string;
72+
fixed?: string;
73+
last_affected?: string;
74+
limit?: string;
75+
}[];
76+
database_specific: Record<string, any>;
77+
}
78+
79+
export interface OSVSeverity {
80+
type: string;
81+
score: string;
82+
}
83+
```

src/formats/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ import {
55
standardVulnerabilityMapper,
66
type StandardizeKind
77
} from "./standard/index.js";
8+
import {
9+
osvVulnerabilityMapper,
10+
type OSVKind
11+
} from "./osv/index.js";
812

913
export function formatVulnsPayload(
1014
format: BaseStrategyFormat | null = null
1115
) {
1216
return function formatVulnerabilities(
13-
strategy: StandardizeKind,
17+
strategy: StandardizeKind | OSVKind,
1418
vulnerabilities: any[]
1519
) {
1620
if (format === "Standard") {
@@ -19,6 +23,12 @@ export function formatVulnsPayload(
1923
vulnerabilities
2024
);
2125
}
26+
if (format === "OSV") {
27+
return osvVulnerabilityMapper(
28+
strategy,
29+
vulnerabilities
30+
);
31+
}
2232

2333
// identity function
2434
return vulnerabilities;

src/formats/osv/index.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
// Import Internal Dependencies
2+
import { OSV_VULN_MAPPERS } from "./mappers.js";
13

24
/**
35
* @see https://ossf.github.io/osv-schema/
46
*/
57
export interface OSV {
6-
schema_version: string;
8+
schema_version?: string;
79
id: string;
810
modified: string;
911
published: string;
10-
withdraw: string;
12+
withdraw?: string;
1113
aliases: string[];
12-
related: string[];
14+
upstream: string[];
15+
related?: string[];
1316
summary: string;
1417
details: string;
1518
severity: OSVSeverity[];
@@ -78,3 +81,16 @@ export interface OSVSeverity {
7881
type: string;
7982
score: string;
8083
}
84+
85+
export type OSVKind = keyof typeof OSV_VULN_MAPPERS;
86+
87+
export function osvVulnerabilityMapper(
88+
strategy: OSVKind,
89+
vulnerabilities: any[]
90+
): OSV[] {
91+
if (!(strategy in OSV_VULN_MAPPERS)) {
92+
return [];
93+
}
94+
95+
return vulnerabilities.map(OSV_VULN_MAPPERS[strategy]);
96+
}

src/formats/osv/mappers.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Import Internal Dependencies
2+
import { VULN_MODE } from "../../constants.js";
3+
4+
import type { OSV } from "./index.js";
5+
import type {
6+
SonatypeVulnerability,
7+
SnykVulnerability,
8+
NpmAuditAdvisory,
9+
PnpmAuditAdvisory
10+
} from "../../index.js";
11+
12+
function mapFromNPM(
13+
_vuln: NpmAuditAdvisory
14+
): OSV {
15+
throw new Error("Not Implemented Yet");
16+
}
17+
18+
function mapFromPnpm(
19+
_vuln: PnpmAuditAdvisory
20+
): OSV {
21+
throw new Error("Not Implemented Yet");
22+
}
23+
24+
function mapFromSnyk(
25+
_vuln: SnykVulnerability
26+
): OSV {
27+
throw new Error("Not Implemented Yet");
28+
}
29+
30+
function mapFromSonatype(
31+
_vuln: SonatypeVulnerability
32+
): OSV {
33+
throw new Error("Not Implemented Yet");
34+
}
35+
36+
export const OSV_VULN_MAPPERS = Object.freeze({
37+
[VULN_MODE.GITHUB_ADVISORY]: mapFromNPM,
38+
"github-advisory_pnpm": mapFromPnpm,
39+
[VULN_MODE.SNYK]: mapFromSnyk,
40+
[VULN_MODE.SONATYPE]: mapFromSonatype
41+
});

src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import {
2828
type Kind
2929
} from "./constants.js";
3030

31+
import {
32+
formatVulnsPayload
33+
} from "./formats/index.js";
34+
3135
import type {
3236
SnykVulnerability
3337
} from "./formats/snyk/index.js";
@@ -121,5 +125,6 @@ export type {
121125
SnykVulnerability,
122126
SonatypeVulnerability,
123127

124-
OSV
128+
OSV,
129+
formatVulnsPayload
125130
};

src/strategies/types/api.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import type { Dependencies } from "./scanner.js";
33
import type { StandardVulnerability } from "../../formats/standard/index.js";
44
import type { Kind } from "../../constants.js";
55

6-
export type BaseStrategyFormat = "Standard";
6+
export type BaseStrategyFormat =
7+
| "Standard"
8+
| "OSV";
79

810
export interface BaseStrategyOptions {
911
useFormat?: BaseStrategyFormat;

0 commit comments

Comments
 (0)