Purpose
August 4, 2026 · View on GitHub
This document describes the database specific additions to the OSV Schema specific to the Malicious Packages repository.
The OSV Schema is a format specification for reporting vulnerabilities in Open Source projects. This format has been chosen to work with existing OSV tooling.
The Malicious Packages repository uses the OSV format to store reports of malicious packages published on open source repositories.
The additions described in this document have two primary functions:
- Annotating reports
- Managing the database
To understand how the standard OSV fields are used, see the Contributing Guide for documentation.
Database Specific Format Overview
The underlying OSV format is a JSON-based encoding format. Additions are expressed in the following informal schema. The exact details of each field are elaborated in the next section. All strings contain UTF-8 text.
{
/* ... other OSV fields ... */
"database_specific": {
"iocs": {
"domains": [ string ],
"urls": [ string ],
"ips": [ string ],
"files": [ {
"paths": [ string ],
"note": string,
"source": string,
"digests": {
"md5": string,
"sha1": string,
"sha256": string,
"tlsh": string,
"ssdeep": string
}
} ],
},
"malicious-packages-origins" : [ {
"source": string,
"sha256": string,
"import_time": string,
"modified_time": string,
"ranges": [ /* OSV range object */ ],
"versions": [ string ]
} ],
/* ... other database specific entries ... */
}
}
Field Details
iocs fields (under development)
The iocs field is a JSON object that stores indicators of compromise about
a given malicious package.
This area of the database specific schema is under active development and subject to change.
iocs.domains[] field
The domains field is a JSON array of containing domains (e.g. example.com)
formatted as ASCII strings. Unicode domains must be converted to Punycode.
iocs.ips[] field
The ips field is a JSON array of strings containing either IPv4 or IPv6
addresses or CIDR blocks. For example 10.1.2.3, 10.1.2.0/24,
2001:db8:a0b:12f0::1, 2001:db8:a0b:12f0::1/32.
iocs.urls[] field
The urls field is a JSON array containing arbitrary URLs strings. For each URL
a scheme/authority should be present.
If the URL contains only a host (e.g. example.com), then add the host to
either domains or ips field instead.
iocs.files[] field
The files field is a JSON array of objects, each describing a single file
associated with the malicious package.
This set records individual files that help identify or attribute the malware,
each tagged with a source describing where it came from: a file extracted from
the published package artifact, a second stage dropped to disk at run time, or a
payload that only ever lived in memory. The published package artifact itself
(the tarball/wheel) does not belong here — it is already identified by the
record's affected.package; this field is for the individual files of interest,
not the archive as a whole.
Each object may contain the following fields. An entry must have at least one
paths entry or one digest under digests.
iocs.files[].paths field
The paths field is an optional JSON array of strings giving the file names at
which the file was observed, relative or absolute — the same content can appear
in several places. Each path is limited to 1024 characters. It may be omitted
when the file never has a stable path (e.g. an in-memory payload identified only
by its digest).
iocs.files[].note field
The note field is an optional free-text string describing the file. It is
limited to 512 characters.
iocs.files[].source field
The source field is an optional string recording where the file came from. It
must be one of:
PACKAGE_ARCHIVE— the file is extracted from the published package artifact.DROPPED— the file was written to disk at run time (e.g. a second stage retrieved from a C2, or content decoded from data embedded in the archive).IN_MEMORY— the file only ever existed in memory and never hit disk.
iocs.files[].digests field
The digests field is an optional JSON object mapping a hash algorithm name to
the file's digest under that algorithm. Recognised algorithms are md5, sha1,
sha256, tlsh and ssdeep. sha256 is preferred and recommended at a
minimum.
md5,sha1,sha256— hex-encoded digests (32, 40 and 64 hex characters respectively).tlsh— a hex-encoded TLSH fuzzy hash (70 hex characters, optionally prefixed with theT1version marker), useful for clustering variants of the same payload.ssdeep— an ssdeep context triggered piecewise hash, of the formblocksize:hash1:hash2.
Hex digests (md5, sha1, sha256, tlsh) may be supplied in any case and
are normalized to lowercase; ssdeep is case-sensitive and left as-is.
malicious-packages-origins fields
The malicious-packages-origins field is a JSON array containing objects that
is used internally to manage the malicious packages database. This data has
little value to consumers of OSV malware.
Each entry in the malicious-packages-origins array describes one origin OSV
report that was ingested and merged together to produce this individual OSV
report.
The field is used to help attribute each source and allow for the automated
ingestion command (./cmd/ingest)
to detect reports that have already been imported. When an origin OSV is
ingested an entry will be added to this array. When OSV for the same package are
merged together the malicious-packages-origins in each source OSV will be
appended together in the merged OSV.
Within each object in the malicious-packages-origins array, the source field
contains a key identifying the specific source where an origin OSV was found.
This key should be specified in the ./config/config.yaml file.
The sha256 field contains a hash of the origin OSV file using the SHA256
algorithm. The source and sha256 fields tuple should be a universally unique
identifier of an origin OSV file.
For origins that have an OSV id set, the modified_time and id are stored
as well to allow for updates to the be detected in the OSV.
The import_time indicates when the original OSV report was imported into the
malicious packages repository.
Finally, the ranges and versions fields are copies of the
affected[0].ranges and affected[0].versions from the origin OSV.
malicious-packages-origins[].source field
The source field contains a string identifying the specific source that
contributed the origin OSV. Can only contain numbers, lowercase characters a-z,
and dashes (regexp: ^[a-z0-9-]+$). The source field must be present.
malicious-packages-origins[].sha256 field
The sha256 field is a string containing a SHA256 hash of the origin OSV
serialized as a hexadecimal string. Valid characters are 0-9, a-f. The sha256
field must be present.
malicious-packages-origins[].import_time field
The import_time field gives the time the origin OSV should be considered to
have been ingested, as an RFC3339-formatted timestamp in UTC (ending in "Z").
The import_time field should be present.
malicious-packages-origins[].id field
The id field is optional. It stores a copy of the ID field in the origin OSV
as a string, if it was present. When used in conjunction with modified_time it
can be used to identify updates to the origin OSV that need to be consumed.
malicious-packages-origins[].modified_time field
The modified_time field stores a copy of the modified time from the origin
OSV, as an RFC3339-formatted timestamp in UTC (ending in "Z"). The
modified_time field should be present.
malicious-packages-origins[].ranges field
The ranges field is optional. It is a copy of the ranges field from the
affected[].ranges field in the origin OSV.
See https://ossf.github.io/osv-schema/#affectedranges-field.
malicious-packages-origins[].versions field
The versions field is optional. It is a copy of the versions field from the
affected[].versions field in the origin OSV.
See https://ossf.github.io/osv-schema/#affectedversions-field.