AXLR / Catalog / security

sbom_check

Check a software bill of materials in CycloneDX JSON (1.4, 1.5, 1.6) or SPDX JSON (2.2, 2.3): the fields each specification requires, components without a version, purl or licence, duplicate components, bom-refs and SPDXIDs, dangling dependency and relationship references, the NTIA minimum elements, and a licence summary with SPDX ids counted and checked against the bundled SPDX License List (deprecated and unknown ids), NOASSERTION, NONE, LicenseRef- and expressions.

Install

/tools install sbom_check
/tools install sbom_check@1.0.0

In a console session, or let the model find it in normal mode: axlr_catalog describes it and axlr_install_tool asks for the same install card. The card reads catalog axlr · sbom_check 1.0.0 · verified once the index signature, the manifest digest and every file digest check out. Then the model runs it with axlr_run_tool sbom_check; each run is approved as a local_exec.

Arguments

One JSON object on stdin, validated against the schema before the program starts.

nametyperequireddefaultmeaning
sbomobjectnoThe SBOM as a JSON object
sbom_textstringnoOr the SBOM as JSON text
pathstringnoOr a relative path to the JSON file
max_listintegerno100Longest list of component names per category. ≥ 0
Input schema (JSON)
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "sbom": {
      "type": "object",
      "description": "The SBOM as a JSON object"
    },
    "sbom_text": {
      "type": "string",
      "description": "Or the SBOM as JSON text"
    },
    "path": {
      "type": "string",
      "description": "Or a relative path to the JSON file"
    },
    "max_list": {
      "type": "integer",
      "minimum": 0,
      "default": 100,
      "description": "Longest list of component names per category"
    }
  }
}

Example

Input

{
  "sbom": {
    "bomFormat": "CycloneDX",
    "specVersion": "1.5",
    "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
    "version": 1,
    "components": [
      {
        "type": "library",
        "name": "acme-library"
      }
    ]
  }
}

Output (stdout)

{
  "format": "CycloneDX",
  "spec_version": "1.5",
  "valid": true,
  "errors": [],
  "components": {
    "count": 1,
    "without_version": {
      "count": 1,
      "names": [
        "acme-library"
      ]
    }
  }
}

Files

The command the install card registers is python3 sbom_check.py, run in the workspace with PATH and HOME as its only environment. Each file's SHA-256 is in the signed index; the console checks them before showing the card and again before writing.

sbom_check.py · sha256 40bc8918604ca9e1326b91b38ecb057365ce2b88e825589b5bfcaaebff382250
#!/usr/bin/env python3
"""Check a software bill of materials in CycloneDX JSON (spec 1.4, 1.5, 1.6) or SPDX JSON
(2.2, 2.3): the fields each specification requires, components without a version, a purl or
a licence, duplicate components and identifiers, dangling references, and a licence summary
(SPDX ids counted and checked against the bundled SPDX License List, NOASSERTION, NONE,
LicenseRef-, free-text names, expressions).

Input (JSON on stdin):
  sbom       the SBOM as a JSON object
  sbom_text  or the SBOM as JSON text
  path       or a relative path to a JSON file in the working directory
  max_list   longest list of component names to return per category (default 100)
"""
import json
import pathlib
import re
import sys

HERE = pathlib.Path(__file__).resolve().parent
CDX_TYPES = {
    "1.4": {"application", "framework", "library", "container", "operating-system", "device", "firmware", "file"},
}
CDX_TYPES["1.5"] = CDX_TYPES["1.4"] | {"platform", "device-driver", "machine-learning-model", "data"}
CDX_TYPES["1.6"] = CDX_TYPES["1.5"] | {"cryptographic-asset"}
CDX_HASHES = {"MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512", "SHA3-256", "SHA3-384", "SHA3-512", "BLAKE2b-256",
              "BLAKE2b-384", "BLAKE2b-512", "BLAKE3"}
UUID_URN = re.compile(r"^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$")
PURL = re.compile(r"^pkg:[A-Za-z.+-][A-Za-z0-9.+-]*/[^@?#\s]+(@[^?#\s]+)?(\?[^#\s]*)?(#\S*)?$")
DATETIME = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$")
SPDX_ID = re.compile(r"^SPDXRef-[A-Za-z0-9.-]+$")
SPDX_CHECKSUMS = {"SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "MD2", "MD4", "MD5", "MD6", "SHA3-256", "SHA3-384",
                  "SHA3-512", "BLAKE2b-256", "BLAKE2b-384", "BLAKE2b-512", "BLAKE3", "ADLER32"}


def fail(message):
    print(json.dumps({"error": message}))
    sys.exit(2)


def load_license_list():
    try:
        data = json.loads((HERE / "spdx_licenses.json").read_text(encoding="utf-8"))
    except (OSError, ValueError):
        return {}, {}, None
    licenses = {key.lower(): (key, value) for key, value in data["licenses"].items()}
    exceptions = {key.lower(): (key, value) for key, value in data["exceptions"].items()}
    meta = {"version": data.get("license_list_version"), "release_date": data.get("release_date"), "source": data.get("source_url"),
            "fetched": data.get("fetched")}
    return licenses, exceptions, meta


class Report:
    def __init__(self, max_list):
        self.errors, self.warnings = [], []
        self.max_list = max_list
        self.components = []  # dicts: name, version, purl, has_license, supplier, path, ref
        self.license_counts, self.ref_counts, self.name_counts = {}, {}, {}
        self.unknown_ids, self.deprecated_ids, self.exception_ids = {}, {}, {}
        self.noassertion = self.none = self.expressions = 0

    def error(self, path, message):
        self.errors.append({"path": path, "message": message})

    def warn(self, path, message):
        self.warnings.append({"path": path, "message": message})


def bump(table, key):
    table[key] = table.get(key, 0) + 1


def tokenize(expression):
    return re.findall(r"\(|\)|[^\s()]+", expression)


def check_expression(report, expression, path, licenses, exceptions, refs_known=None):
    """SPDX license expression (SPDX 2.3 Annex D): ids, LicenseRef-, WITH exceptions, AND / OR, parentheses."""
    text = expression.strip()
    if text == "NOASSERTION":
        report.noassertion += 1
        return
    if text == "NONE":
        report.none += 1
        return
    tokens = tokenize(text)
    if not tokens:
        report.error(path, "empty licence expression")
        return
    operators = [t for t in tokens if t.upper() in ("AND", "OR", "WITH")]
    if operators:
        report.expressions += 1
        if not (all(t.isupper() for t in operators) or all(t.islower() for t in operators)):
            report.warn(path, "licence expression operators must be all upper case or all lower case")
    depth, expect_operand, after_with = 0, True, False
    for token in tokens:
        upper = token.upper()
        if token == "(":
            if not expect_operand:
                report.error(path, f"licence expression {text!r}: '(' where an operator was expected")
                return
            depth += 1
        elif token == ")":
            depth -= 1
            if depth < 0 or expect_operand:
                report.error(path, f"licence expression {text!r}: unbalanced or empty parentheses")
                return
        elif upper in ("AND", "OR", "WITH"):
            if expect_operand:
                report.error(path, f"licence expression {text!r}: operator {token} without an operand")
                return
            expect_operand, after_with = True, upper == "WITH"
        else:
            if not expect_operand:
                report.error(path, f"licence expression {text!r}: two licences without an operator between them")
                return
            if after_with:
                found = exceptions.get(token.lower())
                if found:
                    bump(report.exception_ids, found[0])
                elif not token.startswith(("AdditionRef-", "DocumentRef-")):
                    bump(report.unknown_ids, token)
            elif token.startswith(("LicenseRef-", "DocumentRef-")):
                bump(report.ref_counts, token)
                if refs_known is not None and token.startswith("LicenseRef-") and token not in refs_known:
                    report.error(path, f"{token} is not defined in hasExtractedLicensingInfos")
            else:
                base = token[:-1] if token.endswith("+") else token
                found = licenses.get(base.lower())
                if found:
                    bump(report.license_counts, found[0] + ("+" if token.endswith("+") else ""))
                    if found[1].get("deprecated"):
                        bump(report.deprecated_ids, found[0])
                elif licenses:
                    bump(report.unknown_ids, token)
                else:
                    bump(report.license_counts, token)
            expect_operand, after_with = False, False
    if depth != 0 or expect_operand:
        report.error(path, f"licence expression {text!r} is incomplete or has unbalanced parentheses")


def cyclonedx(bom, report, licenses, exceptions):
    path = ""
    spec = bom.get("specVersion")
    if bom.get("bomFormat") != "CycloneDX":
        report.error("/bomFormat", "bomFormat must be \"CycloneDX\"")
    if not isinstance(spec, str):
        report.error("/specVersion", "specVersion is required (a string such as \"1.5\")")
        spec = "1.6"
    elif spec not in CDX_TYPES:
        report.error("/specVersion", f"specVersion {spec} is not supported here (1.4, 1.5 or 1.6)")
        spec = "1.6"
    serial = bom.get("serialNumber")
    if serial is None:
        report.warn("/serialNumber", "no serialNumber: recommended (urn:uuid:...) so that BOM versions can be told apart")
    elif not isinstance(serial, str) or not UUID_URN.match(serial):
        report.error("/serialNumber", "serialNumber must be an RFC 4122 URN: urn:uuid:xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx")
    version = bom.get("version", 1)
    if isinstance(version, bool) or not isinstance(version, int) or version < 1:
        report.error("/version", "version must be an integer >= 1")
    metadata = bom.get("metadata", {})
    if not isinstance(metadata, dict):
        report.error("/metadata", "metadata must be an object")
        metadata = {}
    timestamp = metadata.get("timestamp")
    if timestamp is None:
        report.warn("/metadata/timestamp", "no metadata.timestamp (an NTIA minimum element)")
    elif not isinstance(timestamp, str) or not DATETIME.match(timestamp):
        report.error("/metadata/timestamp", "metadata.timestamp must be an ISO 8601 date-time")
    if not (metadata.get("authors") or metadata.get("manufacture") or metadata.get("manufacturer") or metadata.get("supplier") or metadata.get("tools")):
        report.warn("/metadata", "no metadata.authors, supplier or tools: the author of the SBOM data is an NTIA minimum element")
    refs = {}

    def walk(component, where):
        if not isinstance(component, dict):
            report.error(where, "a component must be an object")
            return
        ctype, name = component.get("type"), component.get("name")
        if not isinstance(ctype, str):
            report.error(where + "/type", "type is required")
        elif ctype not in CDX_TYPES[spec]:
            report.error(where + "/type", f"type {ctype!r} is not allowed in CycloneDX {spec}")
        if not isinstance(name, str) or not name:
            report.error(where + "/name", "name is required")
        ref = component.get("bom-ref")
        if ref is not None:
            if not isinstance(ref, str) or not ref:
                report.error(where + "/bom-ref", "bom-ref must be a non-empty string")
            elif ref in refs:
                report.error(where + "/bom-ref", f"duplicate bom-ref {ref!r} (also at {refs[ref]})")
            else:
                refs[ref] = where
        version_value = component.get("version")
        if version_value is not None and not isinstance(version_value, str):
            report.error(where + "/version", "version must be a string")
        purl = component.get("purl")
        if purl is not None and (not isinstance(purl, str) or not PURL.match(purl)):
            report.error(where + "/purl", "purl is not a valid package URL (pkg:type/namespace/name@version)")
        has_license = False
        entries = component.get("licenses")
        if entries is not None:
            if not isinstance(entries, list):
                report.error(where + "/licenses", "licenses must be an array")
                entries = []
            if any(isinstance(e, dict) and "expression" in e for e in entries) and len(entries) > 1:
                report.error(where + "/licenses", "an expression must be the only item of licenses")
            for index, entry in enumerate(entries):
                at = f"{where}/licenses/{index}"
                if not isinstance(entry, dict) or len({"license", "expression"} & set(entry)) != 1:
                    report.error(at, "each licenses item must have exactly one of license or expression")
                    continue
                has_license = True
                if "expression" in entry:
                    if isinstance(entry["expression"], str):
                        check_expression(report, entry["expression"], at + "/expression", licenses, exceptions)
                    else:
                        report.error(at + "/expression", "expression must be a string")
                else:
                    lic = entry["license"]
                    if not isinstance(lic, dict) or len({"id", "name"} & set(lic)) != 1:
                        report.error(at + "/license", "license must have exactly one of id or name")
                        continue
                    if "id" in lic:
                        lid = lic["id"]
                        found = licenses.get(str(lid).lower())
                        if found:
                            bump(report.license_counts, found[0])
                            if found[1].get("deprecated"):
                                bump(report.deprecated_ids, found[0])
                        else:
                            report.error(at + "/license/id", f"{lid!r} is not an SPDX License List id (use name for other licences)")
                            bump(report.unknown_ids, str(lid))
                    else:
                        lname = str(lic["name"])
                        if lname.upper() == "NOASSERTION":
                            report.noassertion += 1
                        else:
                            bump(report.name_counts, lname)
                            if licenses.get(lname.lower()):
                                report.warn(at + "/license/name", f"{lname!r} is an SPDX id: put it in id rather than name")
        hashes = component.get("hashes", [])
        if isinstance(hashes, list):
            for index, entry in enumerate(hashes):
                if not isinstance(entry, dict) or entry.get("alg") not in CDX_HASHES or not isinstance(entry.get("content"), str):
                    report.error(f"{where}/hashes/{index}", "hash needs alg (MD5, SHA-1, SHA-256, ...) and content")
        supplier = component.get("supplier") or component.get("publisher") or component.get("author") or component.get("manufacturer")
        report.components.append({"name": name if isinstance(name, str) else None, "version": version_value if isinstance(version_value, str) else None,
                                  "purl": purl if isinstance(purl, str) else None, "has_license": has_license,
                                  "supplier": bool(supplier), "path": where, "ref": ref, "unique_id": bool(purl or component.get("cpe") or component.get("swid"))})
        for index, child in enumerate(component.get("components", []) if isinstance(component.get("components", []), list) else []):
            walk(child, f"{where}/components/{index}")

    meta_component = metadata.get("component")
    if meta_component is not None:
        walk(meta_component, "/metadata/component")
        primary = report.components.pop() if report.components and report.components[-1]["path"] == "/metadata/component" else None
    else:
        primary = None
        report.warn("/metadata/component", "no metadata.component: the BOM does not say what it describes")
    components = bom.get("components", [])
    if not isinstance(components, list):
        report.error("/components", "components must be an array")
        components = []
    for index, component in enumerate(components):
        walk(component, f"/components/{index}")
    dependencies = bom.get("dependencies")
    has_dependencies = isinstance(dependencies, list) and bool(dependencies)
    if isinstance(dependencies, list):
        for index, dep in enumerate(dependencies):
            if not isinstance(dep, dict) or not isinstance(dep.get("ref"), str):
                report.error(f"/dependencies/{index}", "a dependency needs ref")
                continue
            for target in [dep["ref"]] + [d for d in dep.get("dependsOn", []) if isinstance(d, str)]:
                if target not in refs:
                    report.error(f"/dependencies/{index}", f"{target!r} is not the bom-ref of any component")
    return {"format": "CycloneDX", "spec_version": spec, "serial_number": serial if isinstance(serial, str) else None,
            "describes": primary["name"] if primary else None, "has_dependencies": has_dependencies,
            "timestamp": bool(timestamp)}


def spdx(doc, report, licenses, exceptions):
    version = doc.get("spdxVersion")
    if version not in ("SPDX-2.2", "SPDX-2.3"):
        report.error("/spdxVersion", f"spdxVersion must be SPDX-2.2 or SPDX-2.3 (found {version!r})")
        version = "SPDX-2.3"
    v23 = version == "SPDX-2.3"
    if doc.get("dataLicense") != "CC0-1.0":
        report.error("/dataLicense", "dataLicense must be CC0-1.0 (SPDX 2.x clause 6.2)")
    if doc.get("SPDXID") != "SPDXRef-DOCUMENT":
        report.error("/SPDXID", "the document SPDXID must be SPDXRef-DOCUMENT (clause 6.3)")
    if not isinstance(doc.get("name"), str) or not doc.get("name"):
        report.error("/name", "name is required (clause 6.4)")
    namespace = doc.get("documentNamespace")
    if not isinstance(namespace, str) or not re.match(r"^[a-zA-Z][a-zA-Z0-9+.-]*:\S+$", namespace or ""):
        report.error("/documentNamespace", "documentNamespace is required: a unique absolute URI (clause 6.5)")
    elif "#" in namespace:
        report.error("/documentNamespace", "documentNamespace must not contain '#'")
    creation = doc.get("creationInfo")
    timestamp = False
    if not isinstance(creation, dict):
        report.error("/creationInfo", "creationInfo is required with created and creators (clauses 6.8 and 6.9)")
    else:
        created = creation.get("created")
        if not isinstance(created, str) or not re.match(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$", created):
            report.error("/creationInfo/created", "created is required as YYYY-MM-DDThh:mm:ssZ (clause 6.9)")
        else:
            timestamp = True
        creators = creation.get("creators")
        if not isinstance(creators, list) or not creators:
            report.error("/creationInfo/creators", "creators is required: one or more 'Tool: ', 'Organization: ' or 'Person: ' entries (clause 6.8)")
        else:
            for index, creator in enumerate(creators):
                if not isinstance(creator, str) or not re.match(r"^(Tool|Organization|Person): \S", creator):
                    report.error(f"/creationInfo/creators/{index}", "a creator must start with 'Tool: ', 'Organization: ' or 'Person: '")
    known_refs = set()
    for index, info in enumerate(doc.get("hasExtractedLicensingInfos", []) or []):
        lid = info.get("licenseId") if isinstance(info, dict) else None
        if not isinstance(lid, str) or not lid.startswith("LicenseRef-"):
            report.error(f"/hasExtractedLicensingInfos/{index}", "licenseId must start with LicenseRef-")
        else:
            known_refs.add(lid)
            if not info.get("extractedText"):
                report.error(f"/hasExtractedLicensingInfos/{index}", "extractedText is required")
    ids = {"SPDXRef-DOCUMENT": "/"}
    packages = doc.get("packages", [])
    if not isinstance(packages, list):
        report.error("/packages", "packages must be an array")
        packages = []
    for index, package in enumerate(packages):
        at = f"/packages/{index}"
        if not isinstance(package, dict):
            report.error(at, "a package must be an object")
            continue
        name = package.get("name")
        if not isinstance(name, str) or not name:
            report.error(at + "/name", "name is required (clause 7.1)")
        sid = package.get("SPDXID")
        if not isinstance(sid, str) or not SPDX_ID.match(sid):
            report.error(at + "/SPDXID", "SPDXID is required: SPDXRef- followed by letters, digits, '.' or '-' (clause 7.2)")
        elif sid in ids:
            report.error(at + "/SPDXID", f"duplicate SPDXID {sid} (also at {ids[sid]})")
        else:
            ids[sid] = at
        location = package.get("downloadLocation")
        if not isinstance(location, str) or not location:
            report.error(at + "/downloadLocation", "downloadLocation is required: a URL, NONE or NOASSERTION (clause 7.7)")
        files_analyzed = package.get("filesAnalyzed", True)
        if files_analyzed is True and "packageVerificationCode" not in package:
            report.error(at + "/packageVerificationCode", "packageVerificationCode is required when filesAnalyzed is true, its default (clause 7.9); set filesAnalyzed false if files were not analysed")
        has_license = False
        for field in ("licenseConcluded", "licenseDeclared"):
            if field in package:
                if isinstance(package[field], str):
                    check_expression(report, package[field], f"{at}/{field}", licenses, exceptions, known_refs)
                    if package[field] not in ("NOASSERTION", "NONE"):
                        has_license = True
                else:
                    report.error(f"{at}/{field}", f"{field} must be a licence expression string")
            elif not v23:
                report.error(f"{at}/{field}", f"{field} is required in SPDX 2.2 (clauses 7.13 and 7.15); NOASSERTION is allowed")
        if "copyrightText" not in package and not v23:
            report.error(at + "/copyrightText", "copyrightText is required in SPDX 2.2 (clause 7.17); NOASSERTION is allowed")
        purls = []
        for rindex, ref in enumerate(package.get("externalRefs", []) or []):
            if not isinstance(ref, dict) or not all(isinstance(ref.get(k), str) for k in ("referenceCategory", "referenceType", "referenceLocator")):
                report.error(f"{at}/externalRefs/{rindex}", "externalRefs need referenceCategory, referenceType and referenceLocator")
                continue
            if ref["referenceType"] == "purl":
                purls.append(ref["referenceLocator"])
                if not PURL.match(ref["referenceLocator"]):
                    report.error(f"{at}/externalRefs/{rindex}", "purl is not a valid package URL")
                category = ref["referenceCategory"]
                expected = "PACKAGE-MANAGER" if v23 else "PACKAGE_MANAGER"
                if category.replace("_", "-") != "PACKAGE-MANAGER":
                    report.warn(f"{at}/externalRefs/{rindex}", f"purl references belong to the {expected} category")
        for cindex, checksum in enumerate(package.get("checksums", []) or []):
            if not isinstance(checksum, dict) or checksum.get("algorithm") not in SPDX_CHECKSUMS or not isinstance(checksum.get("checksumValue"), str):
                report.error(f"{at}/checksums/{cindex}", "checksum needs algorithm (SHA1, SHA256, ...) and checksumValue")
        version_info = package.get("versionInfo")
        report.components.append({"name": name if isinstance(name, str) else None, "version": version_info if isinstance(version_info, str) else None,
                                  "purl": purls[0] if purls else None, "has_license": has_license, "supplier": bool(package.get("supplier") or package.get("originator")),
                                  "path": at, "ref": sid, "unique_id": bool(purls or package.get("externalRefs"))})
    for index, file in enumerate(doc.get("files", []) or []):
        at = f"/files/{index}"
        if not isinstance(file, dict):
            report.error(at, "a file must be an object")
            continue
        if not isinstance(file.get("fileName"), str):
            report.error(at + "/fileName", "fileName is required (clause 8.1)")
        sid = file.get("SPDXID")
        if not isinstance(sid, str) or not SPDX_ID.match(sid):
            report.error(at + "/SPDXID", "SPDXID is required (clause 8.2)")
        elif sid in ids:
            report.error(at + "/SPDXID", f"duplicate SPDXID {sid} (also at {ids[sid]})")
        else:
            ids[sid] = at
        checksums = file.get("checksums")
        if not isinstance(checksums, list) or not any(isinstance(c, dict) and c.get("algorithm") == "SHA1" for c in checksums):
            report.error(at + "/checksums", "a SHA1 checksum is required for every file (clause 8.4)")
        if isinstance(file.get("licenseConcluded"), str):
            check_expression(report, file["licenseConcluded"], at + "/licenseConcluded", licenses, exceptions, known_refs)
        elif not v23:
            report.error(at + "/licenseConcluded", "licenseConcluded is required in SPDX 2.2 (clause 8.5)")
        if "copyrightText" not in file and not v23:
            report.error(at + "/copyrightText", "copyrightText is required in SPDX 2.2 (clause 8.8)")
        for lindex, item in enumerate(file.get("licenseInfoInFiles", []) or []):
            if isinstance(item, str):
                check_expression(report, item, f"{at}/licenseInfoInFiles/{lindex}", licenses, exceptions, known_refs)
    for index, snippet in enumerate(doc.get("snippets", []) or []):
        if isinstance(snippet, dict) and isinstance(snippet.get("SPDXID"), str):
            ids.setdefault(snippet["SPDXID"], f"/snippets/{index}")
    relationships = doc.get("relationships", []) or []
    describes = list(doc.get("documentDescribes", []) or [])
    has_dependencies = False
    for index, rel in enumerate(relationships):
        at = f"/relationships/{index}"
        if not isinstance(rel, dict) or not all(isinstance(rel.get(k), str) for k in ("spdxElementId", "relationshipType", "relatedSpdxElement")):
            report.error(at, "a relationship needs spdxElementId, relationshipType and relatedSpdxElement")
            continue
        for key in ("spdxElementId", "relatedSpdxElement"):
            target = rel[key]
            if target not in ids and target not in ("NONE", "NOASSERTION") and not target.startswith("DocumentRef-"):
                report.error(at + "/" + key, f"{target} is not the SPDXID of any element of the document")
        if rel["relationshipType"] == "DESCRIBES" and rel["spdxElementId"] == "SPDXRef-DOCUMENT":
            describes.append(rel["relatedSpdxElement"])
        if "DEPENDS_ON" in rel["relationshipType"] or "DEPENDENCY_OF" in rel["relationshipType"] or rel["relationshipType"] == "CONTAINS":
            has_dependencies = True
    for target in doc.get("documentDescribes", []) or []:
        if target not in ids:
            report.error("/documentDescribes", f"{target} is not the SPDXID of any element")
    if not describes and (packages or doc.get("files")):
        report.error("/relationships", "the document must DESCRIBE at least one element (a DESCRIBES relationship from SPDXRef-DOCUMENT or documentDescribes)")
    return {"format": "SPDX", "spec_version": version[5:], "document_namespace": namespace if isinstance(namespace, str) else None,
            "describes": describes, "has_dependencies": has_dependencies, "timestamp": timestamp}


def main():
    try:
        request = json.load(sys.stdin)
    except ValueError as error:
        fail(f"stdin is not JSON: {error}")
    if not isinstance(request, dict):
        fail("stdin must be a JSON object")
    unknown = sorted(set(request) - {"sbom", "sbom_text", "path", "max_list"})
    if unknown:
        fail(f"unknown field: {unknown[0]}")
    given = [k for k in ("sbom", "sbom_text", "path") if k in request]
    if len(given) != 1:
        fail("give exactly one of sbom (object), sbom_text (JSON text) or path (relative)")
    if "sbom" in request:
        document = request["sbom"]
    else:
        if "path" in request:
            path = request["path"]
            if not isinstance(path, str) or not path or path.startswith(("/", "\\", "~")) or ".." in re.split(r"[\\/]", path) or re.match(r"^[A-Za-z]:", path):
                fail("path must be a relative path inside the working directory, without '..'")
            target = pathlib.Path(path)
            if not target.is_file():
                fail(f"no such file: {path}")
            if target.stat().st_size > 20_000_000:
                fail("the file is larger than 20 MB")
            text = target.read_text(encoding="utf-8", errors="replace")
        else:
            text = request["sbom_text"]
            if not isinstance(text, str):
                fail("sbom_text must be a string")
        try:
            document = json.loads(text)
        except ValueError as error:
            fail(f"the SBOM is not valid JSON: {error}")
    if not isinstance(document, dict):
        fail("the SBOM must be a JSON object")
    max_list = request.get("max_list", 100)
    if isinstance(max_list, bool) or not isinstance(max_list, int) or max_list < 0:
        fail("max_list must be an integer >= 0")
    licenses, exceptions, meta = load_license_list()
    report = Report(max_list)
    if "bomFormat" in document or "specVersion" in document:
        info = cyclonedx(document, report, licenses, exceptions)
    elif "spdxVersion" in document:
        info = spdx(document, report, licenses, exceptions)
    else:
        fail("not a CycloneDX (bomFormat, specVersion) or SPDX (spdxVersion) JSON document")

    comps = report.components

    def names(items):
        labels = [c["name"] or c["path"] for c in items]
        return labels[:max_list]

    no_version = [c for c in comps if not c["version"]]
    no_purl = [c for c in comps if not c["purl"]]
    no_license = [c for c in comps if not c["has_license"]]
    no_supplier = [c for c in comps if not c["supplier"]]
    groups = {}
    for c in comps:
        if c["name"]:
            groups.setdefault((c["name"].lower(), c["version"] or ""), []).append(c["path"])
    duplicates = [{"name": key[0], "version": key[1] or None, "paths": paths} for key, paths in sorted(groups.items()) if len(paths) > 1]
    purl_groups = {}
    for c in comps:
        if c["purl"]:
            purl_groups.setdefault(c["purl"], []).append(c["path"])
    duplicate_purls = [{"purl": key, "paths": paths} for key, paths in sorted(purl_groups.items()) if len(paths) > 1]
    if duplicates:
        report.warn("/components", f"{len(duplicates)} component name and version pairs appear more than once")
    ntia = {
        "supplier_name": bool(comps) and not no_supplier,
        "component_name": all(c["name"] for c in comps),
        "version": bool(comps) and not no_version,
        "unique_identifiers": bool(comps) and all(c["unique_id"] for c in comps),
        "dependency_relationship": info["has_dependencies"],
        "author_of_sbom_data": not any(w["path"] == "/metadata" for w in report.warnings) if info["format"] == "CycloneDX" else not any(e["path"].startswith("/creationInfo") for e in report.errors),
        "timestamp": info["timestamp"],
    }
    output = dict(info)
    output.update({
        "valid": not report.errors,
        "error_count": len(report.errors),
        "errors": report.errors,
        "warnings": report.warnings,
        "components": {
            "count": len(comps),
            "without_version": {"count": len(no_version), "names": names(no_version)},
            "without_purl": {"count": len(no_purl), "names": names(no_purl)},
            "without_license": {"count": len(no_license), "names": names(no_license)},
            "without_supplier": {"count": len(no_supplier)},
            "duplicates": duplicates[:max_list],
            "duplicate_purls": duplicate_purls[:max_list],
        },
        "licenses": {
            "spdx_ids": dict(sorted(report.license_counts.items(), key=lambda kv: (-kv[1], kv[0]))),
            "license_refs": dict(sorted(report.ref_counts.items())),
            "names_not_spdx": dict(sorted(report.name_counts.items())),
            "exceptions": dict(sorted(report.exception_ids.items())),
            "noassertion": report.noassertion,
            "none": report.none,
            "expressions": report.expressions,
            "unknown_ids": dict(sorted(report.unknown_ids.items())),
            "deprecated_ids": dict(sorted(report.deprecated_ids.items())),
        },
        "ntia_minimum_elements": ntia,
        "license_list": meta,
        "note": "Structural checks of the fields the specification requires, not full JSON Schema validation.",
    })
    print(json.dumps(output))


if __name__ == "__main__":
    main()
spdx_licenses.json · sha256 6d0262d39a85fee5691f19f7d304cce8df8bc4055b8ed9d7e5ebdd35a6221add
{
  "title": "SPDX License List identifiers",
  "license_list_version": "3.29.0",
  "release_date": "2026-09-16",
  "source_url": "https://github.com/spdx/license-list-data",
  "fetched": "2026-10-18",
  "licenses": {
    "0BSD": {"deprecated": false, "osi": true},
    "3D-Slicer-1.0": {"deprecated": false, "osi": false},
    "AAL": {"deprecated": false, "osi": true},
    "Abstyles": {"deprecated": false, "osi": false},
    "AdaCore-doc": {"deprecated": false, "osi": false},
    "Adobe-2006": {"deprecated": false, "osi": false},
    "Adobe-Display-PostScript": {"deprecated": false, "osi": false},
    "Adobe-Glyph": {"deprecated": false, "osi": false},
    "Adobe-Utopia": {"deprecated": false, "osi": false},
    "ADSL": {"deprecated": false, "osi": false},
    "Advanced-Cryptics-Dictionary": {"deprecated": false, "osi": false},
    "AFL-1.1": {"deprecated": false, "osi": true},
    "AFL-1.2": {"deprecated": false, "osi": true},
    "AFL-2.0": {"deprecated": false, "osi": true},
    "AFL-2.1": {"deprecated": false, "osi": true},
    "AFL-3.0": {"deprecated": false, "osi": true},
    "Afmparse": {"deprecated": false, "osi": false},
    "AGPL-1.0": {"deprecated": true, "osi": false},
    "AGPL-1.0-only": {"deprecated": false, "osi": false},
    "AGPL-1.0-or-later": {"deprecated": false, "osi": false},
    "AGPL-3.0": {"deprecated": true, "osi": true},
    "AGPL-3.0-only": {"deprecated": false, "osi": true},
    "AGPL-3.0-or-later": {"deprecated": false, "osi": true},
    "Aladdin": {"deprecated": false, "osi": false},
    "ALGLIB-Documentation": {"deprecated": false, "osi": true},
    "AMD-newlib": {"deprecated": false, "osi": false},
    "AMDPLPA": {"deprecated": false, "osi": false},
    "AML": {"deprecated": false, "osi": false},
    "AML-glslang": {"deprecated": false, "osi": false},
    "AMPAS": {"deprecated": false, "osi": false},
    "ANTLR-PD": {"deprecated": false, "osi": false},
    "ANTLR-PD-fallback": {"deprecated": false, "osi": false},
    "any-OSI": {"deprecated": false, "osi": false},
    "any-OSI-perl-modules": {"deprecated": false, "osi": false},
    "Apache-1.0": {"deprecated": false, "osi": false},
    "Apache-1.1": {"deprecated": false, "osi": true},
    "Apache-2.0": {"deprecated": false, "osi": true},
    "APAFML": {"deprecated": false, "osi": false},
    "APL-1.0": {"deprecated": false, "osi": true},
    "App-s2p": {"deprecated": false, "osi": false},
    "APSL-1.0": {"deprecated": false, "osi": true},
    "APSL-1.1": {"deprecated": false, "osi": true},
    "APSL-1.2": {"deprecated": false, "osi": true},
    "APSL-2.0": {"deprecated": false, "osi": true},
    "Arphic-1999": {"deprecated": false, "osi": false},
    "Artistic-1.0": {"deprecated": false, "osi": true},
    "Artistic-1.0-cl8": {"deprecated": false, "osi": true},
    "Artistic-1.0-Perl": {"deprecated": false, "osi": true},
    "Artistic-2.0": {"deprecated": false, "osi": true},
    "Artistic-dist": {"deprecated": false, "osi": false},
    "Aspell-RU": {"deprecated": false, "osi": false},
    "ASWF-Digital-Assets-1.0": {"deprecated": false, "osi": false},
    "ASWF-Digital-Assets-1.1": {"deprecated": false, "osi": false},
    "atc-game": {"deprecated": false, "osi": false},
    "Baekmuk": {"deprecated": false, "osi": false},
    "Bahyph": {"deprecated": false, "osi": false},
    "Barr": {"deprecated": false, "osi": false},
    "bcrypt-Solar-Designer": {"deprecated": false, "osi": false},
    "Beerware": {"deprecated": false, "osi": false},
    "Bitstream-Charter": {"deprecated": false, "osi": false},
    "Bitstream-Vera": {"deprecated": false, "osi": false},
    "BitTorrent-1.0": {"deprecated": false, "osi": false},
    "BitTorrent-1.1": {"deprecated": false, "osi": false},
    "blessing": {"deprecated": false, "osi": false},
    "BlueOak-1.0.0": {"deprecated": false, "osi": true},
    "Boehm-GC": {"deprecated": false, "osi": false},
    "Boehm-GC-without-fee": {"deprecated": false, "osi": false},
    "BOLA-1.1": {"deprecated": false, "osi": false},
    "Borceux": {"deprecated": false, "osi": false},
    "Brian-Gladman-2-Clause": {"deprecated": false, "osi": false},
    "Brian-Gladman-3-Clause": {"deprecated": false, "osi": false},
    "Brian-Gladman-3-Clause-no-conversion": {"deprecated": false, "osi": false},
    "BSD-1-Clause": {"deprecated": false, "osi": true},
    "BSD-2-Clause": {"deprecated": false, "osi": true},
    "BSD-2-Clause-Darwin": {"deprecated": false, "osi": false},
    "BSD-2-Clause-first-lines": {"deprecated": false, "osi": false},
    "BSD-2-Clause-FreeBSD": {"deprecated": true, "osi": false},
    "BSD-2-Clause-NetBSD": {"deprecated": true, "osi": false},
    "BSD-2-Clause-Patent": {"deprecated": false, "osi": true},
    "BSD-2-Clause-pkgconf-disclaimer": {"deprecated": false, "osi": false},
    "BSD-2-Clause-pos-unchanged": {"deprecated": false, "osi": false},
    "BSD-2-Clause-Views": {"deprecated": false, "osi": false},
    "BSD-3-Clause": {"deprecated": false, "osi": true},
    "BSD-3-Clause-acpica": {"deprecated": false, "osi": false},
    "BSD-3-Clause-Attribution": {"deprecated": false, "osi": false},
    "BSD-3-Clause-Clear": {"deprecated": false, "osi": false},
    "BSD-3-Clause-flex": {"deprecated": false, "osi": false},
    "BSD-3-Clause-HP": {"deprecated": false, "osi": false},
    "BSD-3-Clause-LBNL": {"deprecated": false, "osi": true},
    "BSD-3-Clause-Modification": {"deprecated": false, "osi": false},
    "BSD-3-Clause-No-Military-License": {"deprecated": false, "osi": false},
    "BSD-3-Clause-No-Nuclear-License": {"deprecated": false, "osi": false},
    "BSD-3-Clause-No-Nuclear-License-2014": {"deprecated": false, "osi": false},
    "BSD-3-Clause-No-Nuclear-Warranty": {"deprecated": false, "osi": false},
    "BSD-3-Clause-Open-MPI": {"deprecated": false, "osi": true},
    "BSD-3-Clause-OpenWebUI": {"deprecated": false, "osi": false},
    "BSD-3-Clause-Sun": {"deprecated": false, "osi": false},
    "BSD-3-Clause-Tso": {"deprecated": false, "osi": false},
    "BSD-4-Clause": {"deprecated": false, "osi": false},
    "BSD-4-Clause-Shortened": {"deprecated": false, "osi": false},
    "BSD-4-Clause-UC": {"deprecated": false, "osi": false},
    "BSD-4.3RENO": {"deprecated": false, "osi": false},
    "BSD-4.3TAHOE": {"deprecated": false, "osi": false},
    "BSD-Advertising-Acknowledgement": {"deprecated": false, "osi": false},
    "BSD-ask-to-endorse": {"deprecated": false, "osi": true},
    "BSD-Attribution-HPND-disclaimer": {"deprecated": false, "osi": false},
    "BSD-Inferno-Nettverk": {"deprecated": false, "osi": false},
    "BSD-Mark-Modifications": {"deprecated": false, "osi": false},
    "BSD-Protection": {"deprecated": false, "osi": false},
    "BSD-Source-alt-GPL": {"deprecated": false, "osi": false},
    "BSD-Source-beginning-file": {"deprecated": false, "osi": false},
    "BSD-Source-Code": {"deprecated": false, "osi": false},
    "BSD-Source-Code-no-disclaimer": {"deprecated": false, "osi": false},
    "BSD-Systemics": {"deprecated": false, "osi": false},
    "BSD-Systemics-W3Works": {"deprecated": false, "osi": false},
    "BSL-1.0": {"deprecated": false, "osi": true},
    "Buddy": {"deprecated": false, "osi": false},
    "Bugroff": {"deprecated": false, "osi": false},
    "BUSL-1.1": {"deprecated": false, "osi": false},
    "bzip2-1.0.5": {"deprecated": true, "osi": false},
    "bzip2-1.0.6": {"deprecated": false, "osi": false},
    "C-UDA-1.0": {"deprecated": false, "osi": false},
    "CAL-1.0": {"deprecated": false, "osi": true},
    "CAL-1.0-Combined-Work-Exception": {"deprecated": false, "osi": true},
    "Caldera": {"deprecated": false, "osi": false},
    "Caldera-no-preamble": {"deprecated": false, "osi": false},
    "CAPEC-tou": {"deprecated": false, "osi": false},
    "Catharon": {"deprecated": false, "osi": false},
    "CATOSL-1.1": {"deprecated": false, "osi": true},
    "CC-BY-1.0": {"deprecated": false, "osi": false},
    "CC-BY-2.0": {"deprecated": false, "osi": false},
    "CC-BY-2.5": {"deprecated": false, "osi": false},
    "CC-BY-2.5-AU": {"deprecated": false, "osi": false},
    "CC-BY-3.0": {"deprecated": false, "osi": false},
    "CC-BY-3.0-AT": {"deprecated": false, "osi": false},
    "CC-BY-3.0-AU": {"deprecated": false, "osi": false},
    "CC-BY-3.0-DE": {"deprecated": false, "osi": false},
    "CC-BY-3.0-IGO": {"deprecated": false, "osi": false},
    "CC-BY-3.0-NL": {"deprecated": false, "osi": false},
    "CC-BY-3.0-US": {"deprecated": false, "osi": false},
    "CC-BY-4.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-1.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-2.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-2.5": {"deprecated": false, "osi": false},
    "CC-BY-NC-3.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-3.0-DE": {"deprecated": false, "osi": false},
    "CC-BY-NC-3.0-IGO": {"deprecated": false, "osi": false},
    "CC-BY-NC-4.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-ND-1.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-ND-2.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-ND-2.5": {"deprecated": false, "osi": false},
    "CC-BY-NC-ND-3.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-ND-3.0-DE": {"deprecated": false, "osi": false},
    "CC-BY-NC-ND-3.0-IGO": {"deprecated": false, "osi": false},
    "CC-BY-NC-ND-4.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-1.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-2.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-2.0-DE": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-2.0-FR": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-2.0-UK": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-2.5": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-3.0": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-3.0-DE": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-3.0-IGO": {"deprecated": false, "osi": false},
    "CC-BY-NC-SA-4.0": {"deprecated": false, "osi": false},
    "CC-BY-ND-1.0": {"deprecated": false, "osi": false},
    "CC-BY-ND-2.0": {"deprecated": false, "osi": false},
    "CC-BY-ND-2.5": {"deprecated": false, "osi": false},
    "CC-BY-ND-3.0": {"deprecated": false, "osi": false},
    "CC-BY-ND-3.0-DE": {"deprecated": false, "osi": false},
    "CC-BY-ND-4.0": {"deprecated": false, "osi": false},
    "CC-BY-SA-1.0": {"deprecated": false, "osi": false},
    "CC-BY-SA-2.0": {"deprecated": false, "osi": false},
    "CC-BY-SA-2.0-UK": {"deprecated": false, "osi": false},
    "CC-BY-SA-2.1-JP": {"deprecated": false, "osi": false},
    "CC-BY-SA-2.5": {"deprecated": false, "osi": false},
    "CC-BY-SA-3.0": {"deprecated": false, "osi": false},
    "CC-BY-SA-3.0-AT": {"deprecated": false, "osi": false},
    "CC-BY-SA-3.0-DE": {"deprecated": false, "osi": false},
    "CC-BY-SA-3.0-IGO": {"deprecated": false, "osi": false},
    "CC-BY-SA-4.0": {"deprecated": false, "osi": false},
    "CC-PDDC": {"deprecated": false, "osi": false},
    "CC-PDM-1.0": {"deprecated": false, "osi": false},
    "CC-SA-1.0": {"deprecated": false, "osi": false},
    "CC0-1.0": {"deprecated": false, "osi": false},
    "CDDL-1.0": {"deprecated": false, "osi": true},
    "CDDL-1.1": {"deprecated": false, "osi": true},
    "CDL-1.0": {"deprecated": false, "osi": false},
    "CDLA-Permissive-1.0": {"deprecated": false, "osi": false},
    "CDLA-Permissive-2.0": {"deprecated": false, "osi": false},
    "CDLA-Sharing-1.0": {"deprecated": false, "osi": false},
    "CECILL-1.0": {"deprecated": false, "osi": false},
    "CECILL-1.1": {"deprecated": false, "osi": false},
    "CECILL-2.0": {"deprecated": false, "osi": false},
    "CECILL-2.1": {"deprecated": false, "osi": true},
    "CECILL-B": {"deprecated": false, "osi": false},
    "CECILL-C": {"deprecated": false, "osi": false},
    "CERN-OHL-1.1": {"deprecated": false, "osi": false},
    "CERN-OHL-1.2": {"deprecated": false, "osi": false},
    "CERN-OHL-P-2.0": {"deprecated": false, "osi": true},
    "CERN-OHL-S-2.0": {"deprecated": false, "osi": true},
    "CERN-OHL-W-2.0": {"deprecated": false, "osi": true},
    "CFITSIO": {"deprecated": false, "osi": false},
    "check-cvs": {"deprecated": false, "osi": false},
    "checkmk": {"deprecated": false, "osi": false},
    "ClArtistic": {"deprecated": false, "osi": false},
    "Clips": {"deprecated": false, "osi": false},
    "CMU-Mach": {"deprecated": false, "osi": false},
    "CMU-Mach-nodoc": {"deprecated": false, "osi": false},
    "CNRI-Jython": {"deprecated": false, "osi": false},
    "CNRI-Python": {"deprecated": false, "osi": true},
    "CNRI-Python-GPL-Compatible": {"deprecated": false, "osi": true},
    "COIL-1.0": {"deprecated": false, "osi": false},
    "Community-Spec-1.0": {"deprecated": false, "osi": false},
    "Condor-1.1": {"deprecated": false, "osi": false},
    "copyleft-next-0.3.0": {"deprecated": false, "osi": false},
    "copyleft-next-0.3.1": {"deprecated": false, "osi": false},
    "Cornell-Lossless-JPEG": {"deprecated": false, "osi": false},
    "CPAL-1.0": {"deprecated": false, "osi": true},
    "CPL-1.0": {"deprecated": false, "osi": true},
    "CPOL-1.02": {"deprecated": false, "osi": false},
    "Cronyx": {"deprecated": false, "osi": false},
    "Crossword": {"deprecated": false, "osi": false},
    "CryptoSwift": {"deprecated": false, "osi": false},
    "CrystalStacker": {"deprecated": false, "osi": false},
    "CUA-OPL-1.0": {"deprecated": false, "osi": true},
    "Cube": {"deprecated": false, "osi": false},
    "curl": {"deprecated": false, "osi": true},
    "cve-tou": {"deprecated": false, "osi": false},
    "D-FSL-1.0": {"deprecated": false, "osi": false},
    "DEC-3-Clause": {"deprecated": false, "osi": false},
    "diffmark": {"deprecated": false, "osi": false},
    "DL-DE-BY-2.0": {"deprecated": false, "osi": false},
    "DL-DE-ZERO-2.0": {"deprecated": false, "osi": false},
    "DOC": {"deprecated": false, "osi": false},
    "DocBook-DTD": {"deprecated": false, "osi": false},
    "DocBook-Schema": {"deprecated": false, "osi": false},
    "DocBook-Stylesheet": {"deprecated": false, "osi": false},
    "DocBook-XML": {"deprecated": false, "osi": false},
    "Dotseqn": {"deprecated": false, "osi": false},
    "DRL-1.0": {"deprecated": false, "osi": false},
    "DRL-1.1": {"deprecated": false, "osi": false},
    "DSDP": {"deprecated": false, "osi": false},
    "dtoa": {"deprecated": false, "osi": false},
    "dvipdfm": {"deprecated": false, "osi": false},
    "ECL-1.0": {"deprecated": false, "osi": true},
    "ECL-2.0": {"deprecated": false, "osi": true},
    "eCos-2.0": {"deprecated": true, "osi": false},
    "EFL-1.0": {"deprecated": false, "osi": true},
    "EFL-2.0": {"deprecated": false, "osi": true},
    "eGenix": {"deprecated": false, "osi": false},
    "Elastic-2.0": {"deprecated": false, "osi": false},
    "Entessa": {"deprecated": false, "osi": true},
    "EPICS": {"deprecated": false, "osi": false},
    "EPL-1.0": {"deprecated": false, "osi": true},
    "EPL-2.0": {"deprecated": false, "osi": true},
    "ErlPL-1.1": {"deprecated": false, "osi": false},
    "ESA-PL-permissive-2.4": {"deprecated": false, "osi": false},
    "ESA-PL-strong-copyleft-2.4": {"deprecated": false, "osi": false},
    "ESA-PL-weak-copyleft-2.4": {"deprecated": false, "osi": false},
    "etalab-2.0": {"deprecated": false, "osi": false},
    "EUDatagrid": {"deprecated": false, "osi": true},
    "EUPL-1.0": {"deprecated": false, "osi": false},
    "EUPL-1.1": {"deprecated": false, "osi": true},
    "EUPL-1.2": {"deprecated": false, "osi": true},
    "Eurosym": {"deprecated": false, "osi": false},
    "Fair": {"deprecated": false, "osi": true},
    "FBM": {"deprecated": false, "osi": false},
    "FDK-AAC": {"deprecated": false, "osi": false},
    "FDK-MPEG-H": {"deprecated": false, "osi": false},
    "Ferguson-Twofish": {"deprecated": false, "osi": false},
    "Frameworx-1.0": {"deprecated": false, "osi": true},
    "FreeBSD-DOC": {"deprecated": false, "osi": false},
    "FreeImage": {"deprecated": false, "osi": false},
    "FSFAP": {"deprecated": false, "osi": false},
    "FSFAP-no-warranty-disclaimer": {"deprecated": false, "osi": false},
    "FSFUL": {"deprecated": false, "osi": false},
    "FSFULLR": {"deprecated": false, "osi": false},
    "FSFULLRSD": {"deprecated": false, "osi": false},
    "FSFULLRWD": {"deprecated": false, "osi": false},
    "FSL-1.1-ALv2": {"deprecated": false, "osi": false},
    "FSL-1.1-MIT": {"deprecated": false, "osi": false},
    "FTL": {"deprecated": false, "osi": false},
    "Furuseth": {"deprecated": false, "osi": false},
    "fwlw": {"deprecated": false, "osi": false},
    "Game-Programming-Gems": {"deprecated": false, "osi": false},
    "GCR-docs": {"deprecated": false, "osi": false},
    "GD": {"deprecated": false, "osi": false},
    "generic-xts": {"deprecated": false, "osi": false},
    "GFDL-1.1": {"deprecated": true, "osi": false},
    "GFDL-1.1-invariants-only": {"deprecated": false, "osi": false},
    "GFDL-1.1-invariants-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.1-no-invariants-only": {"deprecated": false, "osi": false},
    "GFDL-1.1-no-invariants-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.1-only": {"deprecated": false, "osi": false},
    "GFDL-1.1-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.2": {"deprecated": true, "osi": false},
    "GFDL-1.2-invariants-only": {"deprecated": false, "osi": false},
    "GFDL-1.2-invariants-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.2-no-invariants-only": {"deprecated": false, "osi": false},
    "GFDL-1.2-no-invariants-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.2-only": {"deprecated": false, "osi": false},
    "GFDL-1.2-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.3": {"deprecated": true, "osi": false},
    "GFDL-1.3-invariants-only": {"deprecated": false, "osi": false},
    "GFDL-1.3-invariants-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.3-no-invariants-only": {"deprecated": false, "osi": false},
    "GFDL-1.3-no-invariants-or-later": {"deprecated": false, "osi": false},
    "GFDL-1.3-only": {"deprecated": false, "osi": false},
    "GFDL-1.3-or-later": {"deprecated": false, "osi": false},
    "Giftware": {"deprecated": false, "osi": false},
    "GL2PS": {"deprecated": false, "osi": false},
    "Glide": {"deprecated": false, "osi": false},
    "Glulxe": {"deprecated": false, "osi": false},
    "GLWTPL": {"deprecated": false, "osi": false},
    "gnuplot": {"deprecated": false, "osi": false},
    "GPL-1.0": {"deprecated": true, "osi": false},
    "GPL-1.0+": {"deprecated": true, "osi": false},
    "GPL-1.0-only": {"deprecated": false, "osi": false},
    "GPL-1.0-or-later": {"deprecated": false, "osi": false},
    "GPL-2.0": {"deprecated": true, "osi": true},
    "GPL-2.0+": {"deprecated": true, "osi": true},
    "GPL-2.0-only": {"deprecated": false, "osi": true},
    "GPL-2.0-or-later": {"deprecated": false, "osi": true},
    "GPL-2.0-with-autoconf-exception": {"deprecated": true, "osi": false},
    "GPL-2.0-with-bison-exception": {"deprecated": true, "osi": false},
    "GPL-2.0-with-classpath-exception": {"deprecated": true, "osi": false},
    "GPL-2.0-with-font-exception": {"deprecated": true, "osi": false},
    "GPL-2.0-with-GCC-exception": {"deprecated": true, "osi": false},
    "GPL-3.0": {"deprecated": true, "osi": true},
    "GPL-3.0+": {"deprecated": true, "osi": true},
    "GPL-3.0-only": {"deprecated": false, "osi": true},
    "GPL-3.0-or-later": {"deprecated": false, "osi": true},
    "GPL-3.0-with-autoconf-exception": {"deprecated": true, "osi": false},
    "GPL-3.0-with-GCC-exception": {"deprecated": true, "osi": true},
    "Graphics-Gems": {"deprecated": false, "osi": false},
    "gSOAP-1.3b": {"deprecated": false, "osi": false},
    "gtkbook": {"deprecated": false, "osi": false},
    "Gutmann": {"deprecated": false, "osi": false},
    "HaskellReport": {"deprecated": false, "osi": false},
    "HDF5": {"deprecated": false, "osi": false},
    "hdparm": {"deprecated": false, "osi": false},
    "HIDAPI": {"deprecated": false, "osi": false},
    "Hippocratic-2.1": {"deprecated": false, "osi": false},
    "Hippocratic-3.0-core": {"deprecated": false, "osi": false},
    "HP-1986": {"deprecated": false, "osi": false},
    "HP-1989": {"deprecated": false, "osi": false},
    "HPND": {"deprecated": false, "osi": true},
    "HPND-DEC": {"deprecated": false, "osi": false},
    "HPND-doc": {"deprecated": false, "osi": false},
    "HPND-doc-sell": {"deprecated": false, "osi": false},
    "HPND-export-US": {"deprecated": false, "osi": false},
    "HPND-export-US-acknowledgement": {"deprecated": false, "osi": false},
    "HPND-export-US-modify": {"deprecated": false, "osi": false},
    "HPND-export2-US": {"deprecated": false, "osi": false},
    "HPND-Fenneberg-Livingston": {"deprecated": false, "osi": false},
    "HPND-INRIA-IMAG": {"deprecated": false, "osi": false},
    "HPND-Intel": {"deprecated": false, "osi": false},
    "HPND-Kevlin-Henney": {"deprecated": false, "osi": false},
    "HPND-Markus-Kuhn": {"deprecated": false, "osi": false},
    "HPND-merchantability-variant": {"deprecated": false, "osi": false},
    "HPND-MIT-disclaimer": {"deprecated": false, "osi": false},
    "HPND-Netrek": {"deprecated": false, "osi": false},
    "HPND-Pbmplus": {"deprecated": false, "osi": false},
    "HPND-sell-MIT-disclaimer-xserver": {"deprecated": false, "osi": false},
    "HPND-sell-regexpr": {"deprecated": false, "osi": false},
    "HPND-sell-variant": {"deprecated": false, "osi": false},
    "HPND-sell-variant-critical-systems": {"deprecated": false, "osi": false},
    "HPND-sell-variant-MIT-disclaimer": {"deprecated": false, "osi": false},
    "HPND-sell-variant-MIT-disclaimer-rev": {"deprecated": false, "osi": false},
    "HPND-SMC": {"deprecated": false, "osi": false},
    "HPND-UC": {"deprecated": false, "osi": false},
    "HPND-UC-export-US": {"deprecated": false, "osi": false},
    "HTMLTIDY": {"deprecated": false, "osi": false},
    "hyphen-bulgarian": {"deprecated": false, "osi": false},
    "IBM-pibs": {"deprecated": false, "osi": false},
    "ICU": {"deprecated": false, "osi": true},
    "IEC-Code-Components-EULA": {"deprecated": false, "osi": false},
    "IJG": {"deprecated": false, "osi": false},
    "IJG-short": {"deprecated": false, "osi": false},
    "ImageMagick": {"deprecated": false, "osi": false},
    "iMatix": {"deprecated": false, "osi": false},
    "Imlib2": {"deprecated": false, "osi": false},
    "Info-ZIP": {"deprecated": false, "osi": false},
    "Informatica": {"deprecated": false, "osi": false},
    "Inner-Net-2.0": {"deprecated": false, "osi": false},
    "InnoSetup": {"deprecated": false, "osi": false},
    "Intel": {"deprecated": false, "osi": true},
    "Intel-ACPI": {"deprecated": false, "osi": false},
    "Interbase-1.0": {"deprecated": false, "osi": false},
    "IPA": {"deprecated": false, "osi": true},
    "IPL-1.0": {"deprecated": false, "osi": true},
    "ISC": {"deprecated": false, "osi": true},
    "ISC-Veillard": {"deprecated": false, "osi": false},
    "ISO-permission": {"deprecated": false, "osi": false},
    "Jam": {"deprecated": false, "osi": true},
    "JasPer-2.0": {"deprecated": false, "osi": false},
    "jove": {"deprecated": false, "osi": false},
    "JPL-image": {"deprecated": false, "osi": false},
    "JPNIC": {"deprecated": false, "osi": false},
    "JSON": {"deprecated": false, "osi": false},
    "Kastrup": {"deprecated": false, "osi": false},
    "Kazlib": {"deprecated": false, "osi": false},
    "Knuth-CTAN": {"deprecated": false, "osi": false},
    "LAL-1.2": {"deprecated": false, "osi": false},
    "LAL-1.3": {"deprecated": false, "osi": false},
    "Latex2e": {"deprecated": false, "osi": false},
    "Latex2e-translated-notice": {"deprecated": false, "osi": false},
    "Leptonica": {"deprecated": false, "osi": false},
    "LGPL-2.0": {"deprecated": true, "osi": true},
    "LGPL-2.0+": {"deprecated": true, "osi": true},
    "LGPL-2.0-only": {"deprecated": false, "osi": true},
    "LGPL-2.0-or-later": {"deprecated": false, "osi": true},
    "LGPL-2.1": {"deprecated": true, "osi": true},
    "LGPL-2.1+": {"deprecated": true, "osi": true},
    "LGPL-2.1-only": {"deprecated": false, "osi": true},
    "LGPL-2.1-or-later": {"deprecated": false, "osi": true},
    "LGPL-3.0": {"deprecated": true, "osi": true},
    "LGPL-3.0+": {"deprecated": true, "osi": true},
    "LGPL-3.0-only": {"deprecated": false, "osi": true},
    "LGPL-3.0-or-later": {"deprecated": false, "osi": true},
    "LGPLLR": {"deprecated": false, "osi": false},
    "Libpng": {"deprecated": false, "osi": false},
    "libpng-1.6.35": {"deprecated": false, "osi": false},
    "libpng-2.0": {"deprecated": false, "osi": false},
    "libselinux-1.0": {"deprecated": false, "osi": false},
    "libtiff": {"deprecated": false, "osi": false},
    "libutil-David-Nugent": {"deprecated": false, "osi": false},
    "LiLiQ-P-1.1": {"deprecated": false, "osi": true},
    "LiLiQ-R-1.1": {"deprecated": false, "osi": true},
    "LiLiQ-Rplus-1.1": {"deprecated": false, "osi": true},
    "Linux-man-pages-1-para": {"deprecated": false, "osi": false},
    "Linux-man-pages-copyleft": {"deprecated": false, "osi": false},
    "Linux-man-pages-copyleft-2-para": {"deprecated": false, "osi": false},
    "Linux-man-pages-copyleft-var": {"deprecated": false, "osi": false},
    "Linux-OpenIB": {"deprecated": false, "osi": false},
    "LOOP": {"deprecated": false, "osi": false},
    "LPD-document": {"deprecated": false, "osi": false},
    "LPL-1.0": {"deprecated": false, "osi": true},
    "LPL-1.02": {"deprecated": false, "osi": true},
    "LPPL-1.0": {"deprecated": false, "osi": false},
    "LPPL-1.1": {"deprecated": false, "osi": false},
    "LPPL-1.2": {"deprecated": false, "osi": false},
    "LPPL-1.3a": {"deprecated": false, "osi": false},
    "LPPL-1.3c": {"deprecated": false, "osi": true},
    "lsof": {"deprecated": false, "osi": false},
    "Lucida-Bitmap-Fonts": {"deprecated": false, "osi": false},
    "LZMA-SDK-9.11-to-9.20": {"deprecated": false, "osi": false},
    "LZMA-SDK-9.22": {"deprecated": false, "osi": false},
    "Mackerras-3-Clause": {"deprecated": false, "osi": false},
    "Mackerras-3-Clause-acknowledgment": {"deprecated": false, "osi": false},
    "magaz": {"deprecated": false, "osi": false},
    "mailprio": {"deprecated": false, "osi": false},
    "MakeIndex": {"deprecated": false, "osi": false},
    "man2html": {"deprecated": false, "osi": false},
    "Martin-Birgmeier": {"deprecated": false, "osi": false},
    "McPhee-slideshow": {"deprecated": false, "osi": false},
    "metamail": {"deprecated": false, "osi": false},
    "Minpack": {"deprecated": false, "osi": false},
    "MIPS": {"deprecated": false, "osi": false},
    "MirOS": {"deprecated": false, "osi": true},
    "MIT": {"deprecated": false, "osi": true},
    "MIT-0": {"deprecated": false, "osi": true},
    "MIT-advertising": {"deprecated": false, "osi": false},
    "MIT-Click": {"deprecated": false, "osi": false},
    "MIT-CMU": {"deprecated": false, "osi": false},
    "MIT-enna": {"deprecated": false, "osi": false},
    "MIT-feh": {"deprecated": false, "osi": false},
    "MIT-Festival": {"deprecated": false, "osi": false},
    "MIT-Khronos-old": {"deprecated": false, "osi": false},
    "MIT-Modern-Variant": {"deprecated": false, "osi": true},
    "MIT-open-group": {"deprecated": false, "osi": false},
    "MIT-STK": {"deprecated": false, "osi": false},
    "MIT-testregex": {"deprecated": false, "osi": false},
    "MIT-Wu": {"deprecated": false, "osi": false},
    "MITNFA": {"deprecated": false, "osi": false},
    "MMIXware": {"deprecated": false, "osi": false},
    "MMPL-1.0.1": {"deprecated": false, "osi": false},
    "Motosoto": {"deprecated": false, "osi": true},
    "MPEG-SSG": {"deprecated": false, "osi": false},
    "mpi-permissive": {"deprecated": false, "osi": false},
    "mpich2": {"deprecated": false, "osi": false},
    "MPL-1.0": {"deprecated": false, "osi": true},
    "MPL-1.1": {"deprecated": false, "osi": true},
    "MPL-2.0": {"deprecated": false, "osi": true},
    "MPL-2.0-no-copyleft-exception": {"deprecated": false, "osi": true},
    "mplus": {"deprecated": false, "osi": false},
    "MS-LPL": {"deprecated": false, "osi": false},
    "MS-PL": {"deprecated": false, "osi": true},
    "MS-RL": {"deprecated": false, "osi": true},
    "MTLL": {"deprecated": false, "osi": false},
    "MulanPSL-1.0": {"deprecated": false, "osi": false},
    "MulanPSL-2.0": {"deprecated": false, "osi": true},
    "Multics": {"deprecated": false, "osi": true},
    "Mup": {"deprecated": false, "osi": false},
    "MVT-1.1": {"deprecated": false, "osi": false},
    "NAIST-2003": {"deprecated": false, "osi": false},
    "NASA-1.3": {"deprecated": false, "osi": true},
    "Naumen": {"deprecated": false, "osi": true},
    "NBPL-1.0": {"deprecated": false, "osi": false},
    "NCBI-PD": {"deprecated": false, "osi": false},
    "NCGL-UK-2.0": {"deprecated": false, "osi": false},
    "NCL": {"deprecated": false, "osi": false},
    "NCSA": {"deprecated": false, "osi": true},
    "Net-SNMP": {"deprecated": true, "osi": false},
    "NetCDF": {"deprecated": false, "osi": false},
    "Newsletr": {"deprecated": false, "osi": false},
    "NGPL": {"deprecated": false, "osi": true},
    "ngrep": {"deprecated": false, "osi": false},
    "NICTA-1.0": {"deprecated": false, "osi": false},
    "NIST-PD": {"deprecated": false, "osi": false},
    "NIST-PD-fallback": {"deprecated": false, "osi": false},
    "NIST-PD-TNT": {"deprecated": false, "osi": false},
    "NIST-Software": {"deprecated": false, "osi": false},
    "NLOD-1.0": {"deprecated": false, "osi": false},
    "NLOD-2.0": {"deprecated": false, "osi": false},
    "NLPL": {"deprecated": false, "osi": false},
    "Nokia": {"deprecated": false, "osi": true},
    "NOSL": {"deprecated": false, "osi": false},
    "Noweb": {"deprecated": false, "osi": false},
    "NPL-1.0": {"deprecated": false, "osi": false},
    "NPL-1.1": {"deprecated": false, "osi": false},
    "NPOSL-3.0": {"deprecated": false, "osi": true},
    "NRL": {"deprecated": false, "osi": false},
    "NTIA-PD": {"deprecated": false, "osi": false},
    "NTP": {"deprecated": false, "osi": true},
    "NTP-0": {"deprecated": false, "osi": false},
    "Nunit": {"deprecated": true, "osi": false},
    "O-UDA-1.0": {"deprecated": false, "osi": false},
    "OAR": {"deprecated": false, "osi": false},
    "OCCT-PL": {"deprecated": false, "osi": false},
    "OCLC-2.0": {"deprecated": false, "osi": true},
    "ODbL-1.0": {"deprecated": false, "osi": false},
    "ODC-By-1.0": {"deprecated": false, "osi": false},
    "OFFIS": {"deprecated": false, "osi": false},
    "OFL-1.0": {"deprecated": false, "osi": false},
    "OFL-1.0-no-RFN": {"deprecated": false, "osi": false},
    "OFL-1.0-RFN": {"deprecated": false, "osi": false},
    "OFL-1.1": {"deprecated": false, "osi": true},
    "OFL-1.1-no-RFN": {"deprecated": false, "osi": true},
    "OFL-1.1-RFN": {"deprecated": false, "osi": true},
    "OGC-1.0": {"deprecated": false, "osi": false},
    "OGDL-Taiwan-1.0": {"deprecated": false, "osi": false},
    "OGL-Canada-2.0": {"deprecated": false, "osi": false},
    "OGL-UK-1.0": {"deprecated": false, "osi": false},
    "OGL-UK-2.0": {"deprecated": false, "osi": false},
    "OGL-UK-3.0": {"deprecated": false, "osi": false},
    "OGTSL": {"deprecated": false, "osi": true},
    "OLDAP-1.1": {"deprecated": false, "osi": false},
    "OLDAP-1.2": {"deprecated": false, "osi": false},
    "OLDAP-1.3": {"deprecated": false, "osi": false},
    "OLDAP-1.4": {"deprecated": false, "osi": false},
    "OLDAP-2.0": {"deprecated": false, "osi": false},
    "OLDAP-2.0.1": {"deprecated": false, "osi": false},
    "OLDAP-2.1": {"deprecated": false, "osi": false},
    "OLDAP-2.2": {"deprecated": false, "osi": false},
    "OLDAP-2.2.1": {"deprecated": false, "osi": false},
    "OLDAP-2.2.2": {"deprecated": false, "osi": false},
    "OLDAP-2.3": {"deprecated": false, "osi": false},
    "OLDAP-2.4": {"deprecated": false, "osi": false},
    "OLDAP-2.5": {"deprecated": false, "osi": false},
    "OLDAP-2.6": {"deprecated": false, "osi": false},
    "OLDAP-2.7": {"deprecated": false, "osi": false},
    "OLDAP-2.8": {"deprecated": false, "osi": true},
    "OLFL-1.3": {"deprecated": false, "osi": true},
    "OML": {"deprecated": false, "osi": false},
    "OpenMDW-1.0": {"deprecated": false, "osi": false},
    "OpenPBS-2.3": {"deprecated": false, "osi": false},
    "OpenSSL": {"deprecated": false, "osi": false},
    "OpenSSL-standalone": {"deprecated": false, "osi": false},
    "OpenVision": {"deprecated": false, "osi": false},
    "OPL-1.0": {"deprecated": false, "osi": false},
    "OPL-UK-3.0": {"deprecated": false, "osi": false},
    "OPUBL-1.0": {"deprecated": false, "osi": false},
    "OSC-1.0": {"deprecated": false, "osi": true},
    "OSET-PL-2.1": {"deprecated": false, "osi": true},
    "OSL-1.0": {"deprecated": false, "osi": true},
    "OSL-1.1": {"deprecated": false, "osi": false},
    "OSL-2.0": {"deprecated": false, "osi": true},
    "OSL-2.1": {"deprecated": false, "osi": true},
    "OSL-3.0": {"deprecated": false, "osi": true},
    "OSSP": {"deprecated": false, "osi": false},
    "PADL": {"deprecated": false, "osi": false},
    "ParaType-Free-Font-1.3": {"deprecated": false, "osi": false},
    "Parity-6.0.0": {"deprecated": false, "osi": false},
    "Parity-7.0.0": {"deprecated": false, "osi": false},
    "PDDL-1.0": {"deprecated": false, "osi": false},
    "PHP-3.0": {"deprecated": false, "osi": true},
    "PHP-3.01": {"deprecated": false, "osi": true},
    "Pixar": {"deprecated": false, "osi": false},
    "pkgconf": {"deprecated": false, "osi": false},
    "Plexus": {"deprecated": false, "osi": false},
    "pnmstitch": {"deprecated": false, "osi": false},
    "PolyForm-Noncommercial-1.0.0": {"deprecated": false, "osi": false},
    "PolyForm-Small-Business-1.0.0": {"deprecated": false, "osi": false},
    "PostgreSQL": {"deprecated": false, "osi": true},
    "PPL": {"deprecated": false, "osi": false},
    "PSF-2.0": {"deprecated": false, "osi": false},
    "psfrag": {"deprecated": false, "osi": false},
    "psutils": {"deprecated": false, "osi": false},
    "Python-2.0": {"deprecated": false, "osi": true},
    "Python-2.0.1": {"deprecated": false, "osi": true},
    "python-ldap": {"deprecated": false, "osi": false},
    "Qhull": {"deprecated": false, "osi": false},
    "QPL-1.0": {"deprecated": false, "osi": true},
    "QPL-1.0-INRIA-2004": {"deprecated": false, "osi": false},
    "radvd": {"deprecated": false, "osi": false},
    "Rdisc": {"deprecated": false, "osi": false},
    "RHeCos-1.1": {"deprecated": false, "osi": false},
    "RPL-1.1": {"deprecated": false, "osi": true},
    "RPL-1.5": {"deprecated": false, "osi": true},
    "RPSL-1.0": {"deprecated": false, "osi": true},
    "RSA-MD": {"deprecated": false, "osi": false},
    "RSCPL": {"deprecated": false, "osi": true},
    "Ruby": {"deprecated": false, "osi": false},
    "Ruby-pty": {"deprecated": false, "osi": false},
    "SAX-PD": {"deprecated": false, "osi": false},
    "SAX-PD-2.0": {"deprecated": false, "osi": false},
    "Saxpath": {"deprecated": false, "osi": false},
    "SCEA": {"deprecated": false, "osi": false},
    "SchemeReport": {"deprecated": false, "osi": false},
    "Sendmail": {"deprecated": false, "osi": false},
    "Sendmail-8.23": {"deprecated": false, "osi": false},
    "Sendmail-Open-Source-1.1": {"deprecated": false, "osi": false},
    "SGI-B-1.0": {"deprecated": false, "osi": false},
    "SGI-B-1.1": {"deprecated": false, "osi": false},
    "SGI-B-2.0": {"deprecated": false, "osi": false},
    "SGI-OpenGL": {"deprecated": false, "osi": false},
    "SGMLUG-PM": {"deprecated": false, "osi": false},
    "SGP4": {"deprecated": false, "osi": false},
    "SHL-0.5": {"deprecated": false, "osi": false},
    "SHL-0.51": {"deprecated": false, "osi": false},
    "SimPL-2.0": {"deprecated": false, "osi": true},
    "SISSL": {"deprecated": false, "osi": true},
    "SISSL-1.2": {"deprecated": false, "osi": false},
    "SL": {"deprecated": false, "osi": false},
    "Sleepycat": {"deprecated": false, "osi": true},
    "SMAIL-GPL": {"deprecated": false, "osi": false},
    "SMLNJ": {"deprecated": false, "osi": false},
    "SMPPL": {"deprecated": false, "osi": false},
    "SNIA": {"deprecated": false, "osi": false},
    "snprintf": {"deprecated": false, "osi": false},
    "SOFA": {"deprecated": false, "osi": false},
    "softSurfer": {"deprecated": false, "osi": false},
    "Soundex": {"deprecated": false, "osi": false},
    "Spencer-86": {"deprecated": false, "osi": false},
    "Spencer-94": {"deprecated": false, "osi": false},
    "Spencer-99": {"deprecated": false, "osi": false},
    "SPL-1.0": {"deprecated": false, "osi": true},
    "ssh-keyscan": {"deprecated": false, "osi": false},
    "SSH-OpenSSH": {"deprecated": false, "osi": false},
    "SSH-short": {"deprecated": false, "osi": false},
    "SSLeay-standalone": {"deprecated": false, "osi": false},
    "SSPL-1.0": {"deprecated": false, "osi": false},
    "StandardML-NJ": {"deprecated": true, "osi": false},
    "SugarCRM-1.1.3": {"deprecated": false, "osi": false},
    "SUL-1.0": {"deprecated": false, "osi": false},
    "Sun-PPP": {"deprecated": false, "osi": false},
    "Sun-PPP-2000": {"deprecated": false, "osi": false},
    "SunPro": {"deprecated": false, "osi": false},
    "SWL": {"deprecated": false, "osi": false},
    "swrule": {"deprecated": false, "osi": false},
    "Symlinks": {"deprecated": false, "osi": false},
    "TAPR-OHL-1.0": {"deprecated": false, "osi": false},
    "TCL": {"deprecated": false, "osi": false},
    "TCP-wrappers": {"deprecated": false, "osi": false},
    "TekHVC": {"deprecated": false, "osi": false},
    "TermReadKey": {"deprecated": false, "osi": false},
    "TGPPL-1.0": {"deprecated": false, "osi": false},
    "ThirdEye": {"deprecated": false, "osi": false},
    "threeparttable": {"deprecated": false, "osi": false},
    "TMate": {"deprecated": false, "osi": false},
    "TORQUE-1.1": {"deprecated": false, "osi": false},
    "TOSL": {"deprecated": false, "osi": false},
    "TPDL": {"deprecated": false, "osi": false},
    "TPL-1.0": {"deprecated": false, "osi": false},
    "TrustedQSL": {"deprecated": false, "osi": false},
    "TTWL": {"deprecated": false, "osi": false},
    "TTYP0": {"deprecated": false, "osi": false},
    "TU-Berlin-1.0": {"deprecated": false, "osi": false},
    "TU-Berlin-2.0": {"deprecated": false, "osi": false},
    "Ubuntu-font-1.0": {"deprecated": false, "osi": false},
    "UCAR": {"deprecated": false, "osi": false},
    "UCL-1.0": {"deprecated": false, "osi": true},
    "ulem": {"deprecated": false, "osi": false},
    "UMich-Merit": {"deprecated": false, "osi": false},
    "Unicode-3.0": {"deprecated": false, "osi": true},
    "Unicode-DFS-2015": {"deprecated": false, "osi": false},
    "Unicode-DFS-2016": {"deprecated": false, "osi": true},
    "Unicode-TOU": {"deprecated": false, "osi": false},
    "UnixCrypt": {"deprecated": false, "osi": false},
    "Unlicense": {"deprecated": false, "osi": true},
    "Unlicense-libtelnet": {"deprecated": false, "osi": false},
    "Unlicense-libwhirlpool": {"deprecated": false, "osi": false},
    "UnRAR": {"deprecated": false, "osi": false},
    "UPL-1.0": {"deprecated": false, "osi": true},
    "URT-RLE": {"deprecated": false, "osi": false},
    "Vim": {"deprecated": false, "osi": false},
    "Vixie-Cron": {"deprecated": false, "osi": false},
    "VOSTROM": {"deprecated": false, "osi": false},
    "VSL-1.0": {"deprecated": false, "osi": true},
    "W3C": {"deprecated": false, "osi": true},
    "W3C-19980720": {"deprecated": false, "osi": false},
    "W3C-20150513": {"deprecated": false, "osi": true},
    "w3m": {"deprecated": false, "osi": false},
    "Watcom-1.0": {"deprecated": false, "osi": true},
    "Widget-Workshop": {"deprecated": false, "osi": false},
    "WordNet": {"deprecated": false, "osi": true},
    "Wsuipa": {"deprecated": false, "osi": false},
    "WTFNMFPL": {"deprecated": false, "osi": false},
    "WTFPL": {"deprecated": false, "osi": false},
    "wwl": {"deprecated": false, "osi": false},
    "wxWindows": {"deprecated": true, "osi": true},
    "X11": {"deprecated": false, "osi": false},
    "X11-distribute-modifications-variant": {"deprecated": false, "osi": false},
    "X11-no-permit-persons": {"deprecated": false, "osi": false},
    "X11-swapped": {"deprecated": false, "osi": false},
    "Xdebug-1.03": {"deprecated": false, "osi": false},
    "Xerox": {"deprecated": false, "osi": false},
    "Xfig": {"deprecated": false, "osi": false},
    "XFree86-1.1": {"deprecated": false, "osi": false},
    "xinetd": {"deprecated": false, "osi": false},
    "xkeyboard-config-Zinoviev": {"deprecated": false, "osi": false},
    "xlock": {"deprecated": false, "osi": false},
    "Xnet": {"deprecated": false, "osi": true},
    "xpp": {"deprecated": false, "osi": false},
    "XSkat": {"deprecated": false, "osi": false},
    "xzoom": {"deprecated": false, "osi": false},
    "YPL-1.0": {"deprecated": false, "osi": false},
    "YPL-1.1": {"deprecated": false, "osi": false},
    "Zed": {"deprecated": false, "osi": false},
    "Zeeff": {"deprecated": false, "osi": false},
    "Zend-2.0": {"deprecated": false, "osi": false},
    "Zimbra-1.3": {"deprecated": false, "osi": false},
    "Zimbra-1.4": {"deprecated": false, "osi": false},
    "Zlib": {"deprecated": false, "osi": true},
    "zlib-acknowledgement": {"deprecated": false, "osi": false},
    "ZPL-1.1": {"deprecated": false, "osi": false},
    "ZPL-2.0": {"deprecated": false, "osi": true},
    "ZPL-2.1": {"deprecated": false, "osi": true}
  },
  "exceptions": {
    "389-exception": {"deprecated": false},
    "Asterisk-exception": {"deprecated": false},
    "Asterisk-linking-protocols-exception": {"deprecated": false},
    "Autoconf-exception-2.0": {"deprecated": false},
    "Autoconf-exception-3.0": {"deprecated": false},
    "Autoconf-exception-generic": {"deprecated": false},
    "Autoconf-exception-generic-3.0": {"deprecated": false},
    "Autoconf-exception-macro": {"deprecated": false},
    "Bison-exception-1.24": {"deprecated": false},
    "Bison-exception-2.2": {"deprecated": false},
    "Bootloader-exception": {"deprecated": false},
    "CGAL-linking-exception": {"deprecated": false},
    "Classpath-exception-2.0": {"deprecated": false},
    "Classpath-exception-2.0-short": {"deprecated": false},
    "CLISP-exception-2.0": {"deprecated": false},
    "cryptsetup-OpenSSL-exception": {"deprecated": false},
    "Digia-Qt-LGPL-exception-1.1": {"deprecated": false},
    "DigiRule-FOSS-exception": {"deprecated": false},
    "eCos-exception-2.0": {"deprecated": false},
    "erlang-otp-linking-exception": {"deprecated": false},
    "Fawkes-Runtime-exception": {"deprecated": false},
    "FLTK-exception": {"deprecated": false},
    "fmt-exception": {"deprecated": false},
    "Font-exception-2.0": {"deprecated": false},
    "freertos-exception-2.0": {"deprecated": false},
    "GCC-exception-2.0": {"deprecated": false},
    "GCC-exception-2.0-note": {"deprecated": false},
    "GCC-exception-3.1": {"deprecated": false},
    "Gmsh-exception": {"deprecated": false},
    "GNAT-exception": {"deprecated": false},
    "GNOME-examples-exception": {"deprecated": false},
    "GNU-compiler-exception": {"deprecated": false},
    "gnu-javamail-exception": {"deprecated": false},
    "Google-Patent-WebM": {"deprecated": false},
    "GPL-3.0-389-ds-base-exception": {"deprecated": false},
    "GPL-3.0-interface-exception": {"deprecated": false},
    "GPL-3.0-linking-exception": {"deprecated": false},
    "GPL-3.0-linking-source-exception": {"deprecated": false},
    "GPL-CC-1.0": {"deprecated": false},
    "GStreamer-exception-2005": {"deprecated": false},
    "GStreamer-exception-2008": {"deprecated": false},
    "harbour-exception": {"deprecated": false},
    "i2p-gpl-java-exception": {"deprecated": false},
    "Independent-modules-exception": {"deprecated": false},
    "KiCad-libraries-exception": {"deprecated": false},
    "kvirc-openssl-exception": {"deprecated": false},
    "LGPL-3.0-linking-exception": {"deprecated": false},
    "libpri-OpenH323-exception": {"deprecated": false},
    "Libtool-exception": {"deprecated": false},
    "Linux-syscall-note": {"deprecated": false},
    "LLGPL": {"deprecated": false},
    "LLVM-exception": {"deprecated": false},
    "LZMA-exception": {"deprecated": false},
    "mif-exception": {"deprecated": false},
    "mxml-exception": {"deprecated": false},
    "Nokia-Qt-exception-1.1": {"deprecated": true},
    "OCaml-LGPL-linking-exception": {"deprecated": false},
    "OCCT-exception-1.0": {"deprecated": false},
    "OpenJDK-assembly-exception-1.0": {"deprecated": false},
    "openvpn-openssl-exception": {"deprecated": false},
    "PCRE2-exception": {"deprecated": false},
    "polyparse-exception": {"deprecated": false},
    "PS-or-PDF-font-exception-20170817": {"deprecated": false},
    "QPL-1.0-INRIA-2004-exception": {"deprecated": false},
    "Qt-GPL-exception-1.0": {"deprecated": false},
    "Qt-LGPL-exception-1.1": {"deprecated": false},
    "Qwt-exception-1.0": {"deprecated": false},
    "romic-exception": {"deprecated": false},
    "RRDtool-FLOSS-exception-2.0": {"deprecated": false},
    "rsync-linking-exception": {"deprecated": false},
    "SANE-exception": {"deprecated": false},
    "SHL-2.0": {"deprecated": false},
    "SHL-2.1": {"deprecated": false},
    "Simple-Library-Usage-exception": {"deprecated": false},
    "Spelling-Provider-LGPL-exception": {"deprecated": false},
    "sqlitestudio-OpenSSL-exception": {"deprecated": false},
    "stunnel-exception": {"deprecated": false},
    "SWI-exception": {"deprecated": false},
    "Swift-exception": {"deprecated": false},
    "Texinfo-exception": {"deprecated": false},
    "u-boot-exception-2.0": {"deprecated": false},
    "UBDL-exception": {"deprecated": false},
    "Universal-FOSS-exception-1.0": {"deprecated": false},
    "vsftpd-openssl-exception": {"deprecated": false},
    "WxWindows-exception-3.1": {"deprecated": false},
    "x11vnc-openssl-exception": {"deprecated": false}
  }
}

Where it is served

The registry serves only AXLR clients, so a browser gets 403; fetch with a User-Agent that starts with axlr:

curl -A axlr-docs/1.0 -O https://registry.underpassai.com/tools/sbom_check/1.0.0/manifest.json
curl -A axlr-docs/1.0 -O https://registry.underpassai.com/tools/sbom_check/1.0.0/sbom_check.py
curl -A axlr-docs/1.0 -O https://registry.underpassai.com/tools/sbom_check/1.0.0/spdx_licenses.json