diff --git a/schema/vulnerability/osv/README.md b/schema/vulnerability/osv/README.md new file mode 100644 index 00000000..e1d1177c --- /dev/null +++ b/schema/vulnerability/osv/README.md @@ -0,0 +1,17 @@ +# `Open Source Vulnerability` JSON Schema + +This schema governs the data shape for a single open source package vulnerability record. + +Obtained from the [Open Source Vulnerability schema repository](https://github.com/ossf/osv-schema/blob/main/validation/schema.json). + +## Updating the schema + +Versioning the JSON schema must be done manually by copying the existing JSON schema into a new `schema-x.y.z.json` file and manually making the necessary updates (or by using an online tool such as https://www.liquid-technologies.com/online-json-to-schema-converter). + +This schema is being versioned based off of the "SchemaVer" guidelines, which slightly diverges from Semantic Versioning to tailor for the purposes of data models. + +Given a version number format `MODEL.REVISION.ADDITION`: + +- `MODEL`: increment when you make a breaking schema change which will prevent interaction with any historical data +- `REVISION`: increment when you make a schema change which may prevent interaction with some historical data +- `ADDITION`: increment when you make a schema change that is compatible with all historical data diff --git a/schema/vulnerability/osv/schema-1.6.1.json b/schema/vulnerability/osv/schema-1.6.1.json new file mode 100644 index 00000000..6c2bc0d6 --- /dev/null +++ b/schema/vulnerability/osv/schema-1.6.1.json @@ -0,0 +1,313 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://raw.githubusercontent.com/ossf/osv-schema/main/validation/schema.json", + "title": "Open Source Vulnerability", + "description": "A schema for describing a vulnerability in an open source package.", + "type": "object", + "properties": { + "schema_version": { + "type": "string" + }, + "id": { + "type": "string" + }, + "modified": { + "$ref": "#/$defs/timestamp" + }, + "published": { + "$ref": "#/$defs/timestamp" + }, + "withdrawn": { + "$ref": "#/$defs/timestamp" + }, + "aliases": { + "type": ["array", "null"], + "items": { + "type": "string" + } + }, + "related": { + "type": "array", + "items": { + "type": "string" + } + }, + "summary": { + "type": "string" + }, + "details": { + "type": "string" + }, + "severity": { + "$ref": "#/$defs/severity" + }, + "affected": { + "type": ["array", "null"], + "items": { + "type": "object", + "properties": { + "package": { + "type": "object", + "properties": { + "ecosystem": { + "type": "string" + }, + "name": { + "type": "string" + }, + "purl": { + "type": "string" + } + }, + "required": [ + "ecosystem", + "name" + ] + }, + "severity": { + "$ref": "#/$defs/severity" + }, + "ranges": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "GIT", + "SEMVER", + "ECOSYSTEM" + ] + }, + "repo": { + "type": "string" + }, + "events": { + "type": "array", + "contains": { + "required": [ + "introduced" + ] + }, + "items": { + "type": "object", + "oneOf": [ + { + "type": "object", + "properties": { + "introduced": { + "type": "string" + } + }, + "required": [ + "introduced" + ] + }, + { + "type": "object", + "properties": { + "fixed": { + "type": "string" + } + }, + "required": [ + "fixed" + ] + }, + { + "type": "object", + "properties": { + "last_affected": { + "type": "string" + } + }, + "required": [ + "last_affected" + ] + }, + { + "type": "object", + "properties": { + "limit": { + "type": "string" + } + }, + "required": [ + "limit" + ] + } + ] + }, + "minItems": 1 + }, + "database_specific": { + "type": "object" + } + }, + "allOf": [ + { + "if": { + "properties": { + "type": { + "const": "GIT" + } + } + }, + "then": { + "required": [ + "repo" + ] + } + }, + { + "if": { + "properties": { + "events": { + "contains": { + "required": ["last_affected"] + } + } + } + }, + "then": { + "not": { + "properties": { + "events": { + "contains": { + "required": ["fixed"] + } + } + } + } + } + } + ], + "required": [ + "type", + "events" + ] + } + }, + "versions": { + "type": "array", + "items": { + "type": "string" + } + }, + "ecosystem_specific": { + "type": "object" + }, + "database_specific": { + "type": "object" + } + } + } + }, + "references": { + "type": ["array", "null"], + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ADVISORY", + "ARTICLE", + "DETECTION", + "DISCUSSION", + "REPORT", + "FIX", + "INTRODUCED", + "GIT", + "PACKAGE", + "EVIDENCE", + "WEB" + ] + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "type", + "url" + ] + } + }, + "credits": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "contact": { + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "type": "string", + "enum": [ + "FINDER", + "REPORTER", + "ANALYST", + "COORDINATOR", + "REMEDIATION_DEVELOPER", + "REMEDIATION_REVIEWER", + "REMEDIATION_VERIFIER", + "TOOL", + "SPONSOR", + "OTHER" + ] + } + }, + "required": [ + "name" + ] + } + }, + "database_specific": { + "type": "object" + } + }, + "required": [ + "id", + "modified" + ], + "$defs": { + "severity": { + "type": ["array", "null"], + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "CVSS_V2", + "CVSS_V3", + "CVSS_V4" + ] + }, + "score": { + "type": "string" + } + }, + "required": [ + "type", + "score" + ] + } + }, + "timestamp": { + "type": "string", + "format": "date-time", + "pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z" + } + }, + "additionalProperties": false +} diff --git a/src/vunnel/schema.py b/src/vunnel/schema.py index bcea77e1..018b1ad3 100644 --- a/src/vunnel/schema.py +++ b/src/vunnel/schema.py @@ -8,6 +8,7 @@ MSRC_SCHEMA_VERSION = "1.0.0" OS_SCHEMA_VERSION = "1.0.0" NVD_SCHEMA_VERSION = "1.0.0" +OSV_SCHEMA_VERSION = "1.6.1" @dataclass(frozen=True) @@ -56,3 +57,10 @@ def NVDSchema(version: str = NVD_SCHEMA_VERSION) -> Schema: version=version, url=f"https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/nvd/schema-{version}.json", ) + + +def OSVSchema(version: str = OSV_SCHEMA_VERSION) -> Schema: + return Schema( + version=version, + url=f"https://raw.githubusercontent.com/anchore/vunnel/main/schema/vulnerability/osv/schema-{version}.json", + )