Skip to content

feat: implement OSV format #288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ export interface ExtendedStrategy<
) => Promise<(VulnFormat | StandardVulnerability)[]>;
}

export type BaseStrategyFormat = "Standard";
export type BaseStrategyFormat =
| "Standard"
| "OSV";

export interface BaseStrategyOptions {
useFormat?: BaseStrategyFormat;
Expand All @@ -127,6 +129,7 @@ Where `dependencies` is the dependencies **Map()** object of the NodeSecure Scan

### Formats
- [Standard](./docs/formats/standard.md)
- [OSV](./docs/formats/osv.md) (**Work In Progress**)

### Databases
- [OSV](./docs/database/osv.md)
Expand Down
28 changes: 1 addition & 27 deletions docs/database/osv.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,7 @@ Lean more at [osv.dev](https://osv.dev/)

## Format

The OSV interface is exported as root like `StandardVulnerability`.

```ts
export interface OSV {
schema_version: string;
id: string;
modified: string;
published: string;
withdraw: string;
aliases: string[];
related: string[];
summary: string;
details: string;
severity: OSVSeverity[];
affected: OSVAffected[];
references: {
type: OSVReferenceType;
url: string;
}[];
credits: {
name: string;
contact: string[];
type: OSVCreditType;
}[];
database_specific: Record<string, any>;
}
```
See the [OSV format](../formats/osv.md) documentation.

## API

Expand Down
83 changes: 83 additions & 0 deletions docs/formats/osv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# OSV vulnerability format

See [Open Source Vulnerability format](https://ossf.github.io/osv-schema/)

```ts
export interface OSV {
schema_version: string;
id: string;
modified: string;
published: string;
withdraw: string;
aliases: string[];
upstream: string[];
related: string[];
summary: string;
details: string;
severity: OSVSeverity[];
affected: OSVAffected[];
references: {
type: OSVReferenceType;
url: string;
}[];
credits: {
name: string;
contact: string[];
type: OSVCreditType;
}[];
database_specific: Record<string, any>;
}

export type OSVReferenceType = "ADVISORY" |
"ARTICLE" |
"DETECTION" |
"DISCUSSION" |
"REPORT" |
"FIX" |
"GIT" |
"INTRODUCED" |
"PACKAGE" |
"EVIDENCE" |
"WEB";

export type OSVCreditType = "FINDER" |
"REPORTER" |
"ANALYST" |
"COORDINATOR" |
"REMEDIATION_DEVELOPER" |
"REMEDIATION_REVIEWER" |
"REMEDIATION_VERIFIER" |
"TOOL" |
"SPONSOR" |
"OTHER";

export interface OSVAffected {
package: {
ecosystem: "npm",
name: string;
purl: string;
};
severity: OSVSeverity[];
ranges: OSVRange[];
versions: string[];
ecosystem_specific: Record<string, any>;
database_specific: Record<string, any>;
}

export interface OSVRange {
type: string;
repo: string;
events: {
introduced?: string;
fixed?: string;
last_affected?: string;
limit?: string;
}[];
database_specific: Record<string, any>;
}

export interface OSVSeverity {
type: string;
score: string;
}
```
12 changes: 11 additions & 1 deletion src/formats/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ import {
standardVulnerabilityMapper,
type StandardizeKind
} from "./standard/index.js";
import {
osvVulnerabilityMapper,
type OSVKind
} from "./osv/index.js";

export function formatVulnsPayload(
format: BaseStrategyFormat | null = null
) {
return function formatVulnerabilities(
strategy: StandardizeKind,
strategy: StandardizeKind | OSVKind,
vulnerabilities: any[]
) {
if (format === "Standard") {
Expand All @@ -19,6 +23,12 @@ export function formatVulnsPayload(
vulnerabilities
);
}
if (format === "OSV") {
return osvVulnerabilityMapper(
strategy,
vulnerabilities
);
}

// identity function
return vulnerabilities;
Expand Down
22 changes: 19 additions & 3 deletions src/formats/osv/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// Import Internal Dependencies
import { OSV_VULN_MAPPERS } from "./mappers.js";

/**
* @see https://ossf.github.io/osv-schema/
*/
export interface OSV {
schema_version: string;
schema_version?: string;
id: string;
modified: string;
published: string;
withdraw: string;
withdraw?: string;
aliases: string[];
related: string[];
upstream: string[];
related?: string[];
summary: string;
details: string;
severity: OSVSeverity[];
Expand Down Expand Up @@ -78,3 +81,16 @@ export interface OSVSeverity {
type: string;
score: string;
}

export type OSVKind = keyof typeof OSV_VULN_MAPPERS;

export function osvVulnerabilityMapper(
strategy: OSVKind,
vulnerabilities: any[]
): OSV[] {
if (!(strategy in OSV_VULN_MAPPERS)) {
return [];
}

return vulnerabilities.map(OSV_VULN_MAPPERS[strategy]);
}
41 changes: 41 additions & 0 deletions src/formats/osv/mappers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Import Internal Dependencies
import { VULN_MODE } from "../../constants.js";

import type { OSV } from "./index.js";
import type {
SonatypeVulnerability,
SnykVulnerability,
NpmAuditAdvisory,
PnpmAuditAdvisory
} from "../../index.js";

function mapFromNPM(
_vuln: NpmAuditAdvisory
): OSV {
throw new Error("Not Implemented Yet");
}

function mapFromPnpm(
_vuln: PnpmAuditAdvisory
): OSV {
throw new Error("Not Implemented Yet");
}

function mapFromSnyk(
_vuln: SnykVulnerability
): OSV {
throw new Error("Not Implemented Yet");
}

function mapFromSonatype(
_vuln: SonatypeVulnerability
): OSV {
throw new Error("Not Implemented Yet");
}

export const OSV_VULN_MAPPERS = Object.freeze({
[VULN_MODE.GITHUB_ADVISORY]: mapFromNPM,
"github-advisory_pnpm": mapFromPnpm,
[VULN_MODE.SNYK]: mapFromSnyk,
[VULN_MODE.SONATYPE]: mapFromSonatype
});
7 changes: 6 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import {
type Kind
} from "./constants.js";

import {
formatVulnsPayload
} from "./formats/index.js";

import type {
SnykVulnerability
} from "./formats/snyk/index.js";
Expand Down Expand Up @@ -121,5 +125,6 @@ export type {
SnykVulnerability,
SonatypeVulnerability,

OSV
OSV,
formatVulnsPayload
};
4 changes: 3 additions & 1 deletion src/strategies/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import type { Dependencies } from "./scanner.js";
import type { StandardVulnerability } from "../../formats/standard/index.js";
import type { Kind } from "../../constants.js";

export type BaseStrategyFormat = "Standard";
export type BaseStrategyFormat =
| "Standard"
| "OSV";

export interface BaseStrategyOptions {
useFormat?: BaseStrategyFormat;
Expand Down
Loading