r/semanticweb • u/pkjpathania • 2h ago
Feedback wanted: modelling CycloneDX dependency occurrences and OSV vulnerabilities in RDF
I’m building an open-source project called Dependency Risk Graph and would appreciate feedback on the RDF model from people with more semantic-web experience.
The project imports CycloneDX SBOMs, models application dependency trees in Apache Jena/TDB2, enriches package versions with OSV vulnerability data, and uses SPARQL to answer questions such as:
- Is an application affected by a particular CVE?
- Is the vulnerable dependency direct or transitive?
- What dependency path introduces it?
- Which applications share the affected package?
- Which fixed versions are reported?
A simplified view of the model is:
Application
→ activeImport
Import
Import
→ rootOccurrence
DependencyOccurrence
DependencyOccurrence
→ belongsToImport
Import
DependencyOccurrence
→ instanceOf
PackageVersion
DependencyOccurrence
→ dependsOn
DependencyOccurrence
PackageVersion
→ affectedBy
Vulnerability
Vulnerability
→ affectedPackage
AffectedPackage
→ versionRange
VersionRange
→ event
introduced / fixed / lastAffected
I deliberately distinguish a package-version identity from its occurrence inside a particular imported SBOM. This allows the same Maven package version to be shared as an identity while preserving different dependency paths across applications and imports.
I also currently use a single/default Jena graph. Application and import boundaries are represented explicitly through resources and properties rather than RDF named graphs.
Some areas where I would value criticism:
- Package identity versus occurrence Is separating
PackageVersionfromDependencyOccurrencea reasonable way to preserve both global package identity and application-specific dependency paths? - Import provenance Would modelling imports with a lightweight custom vocabulary be sufficient, or would aligning parts of this with PROV-O provide meaningful benefits?
- OSV version ranges I currently represent affected packages, ranges and range events as first-class resources. Is there an established RDF vocabulary that would be better to reuse for introduced, fixed and last-affected version events?
- SHACL boundaries Which invariants would you validate first? Current candidates include:
- every occurrence belongs to exactly one import;
- every occurrence resolves to exactly one package version;
- dependency edges remain within the same import;
- every active import has one root occurrence;
- vulnerability range events contain a recognised event type and version.
- Natural-language access The next step is intentionally limited: route a few predefined security questions to deterministic SPARQL/path operations, rather than allowing an LLM to generate arbitrary SPARQL.
I’m not trying to create a complete software-supply-chain ontology yet. The immediate goal is a small, explainable model that preserves dependency paths and produces evidence-backed security answers.
Repository: Github
Any feedback/suggestion on the modelling choices, existing vocabularies I may have missed, or problematic assumptions would be genuinely useful.
Current result: the RDF graph preserves application-specific transitive dependency paths while allowing vulnerable packages and vulnerability resources to be shared across imported SBOMs. This view shows three applications reaching CVE-2024-6763 through different Jetty dependency paths, together with the affected package versions, advisory details, and a reported fixed version.

So far, separating dependency occurrences from package-version identity has been useful. The same package can appear in different application paths without merging those paths, while vulnerability and remediation information remains attached to the shared package identity.