Integration Guide
PackageURLs.jl was created to support the Julia security ecosystem. This page documents integration patterns with related packages.
SecurityAdvisories.jl
SecurityAdvisories.jl could use PackageURLs.jl for generating OSV-compliant security advisories in JSON format.
Basic Usage
using PackageURLs
# Create PURL for a vulnerable package
vuln_purl = purl"pkg:julia/Example@1.0.0?uuid=7876af07-990d-54b4-ab0e-23690620f79a"
# Access components for advisory generation
package_name = vuln_purl.name # "Example"
package_version = vuln_purl.version # "1.0.0"
purl_string = string(vuln_purl) # Full PURL stringOSV JSON Generation
The Open Source Vulnerability (OSV) format could use PURLs to identify affected packages:
using PackageURLs
using JSON
# Create PURL for affected package
affected_purl = purl"pkg:julia/VulnerablePackage@1.2.3?uuid=12345678-1234-1234-1234-123456789012"
# Build OSV affected entry
osv_affected = Dict(
"package" => Dict(
"ecosystem" => "Julia",
"name" => affected_purl.name,
"purl" => string(affected_purl)
),
"ranges" => [
Dict(
"type" => "ECOSYSTEM",
"events" => [
Dict("introduced" => "1.0.0"),
Dict("fixed" => "1.2.4")
]
)
],
"versions" => ["1.0.0", "1.1.0", "1.2.0", "1.2.1", "1.2.2", "1.2.3"]
)
# Serialize to JSON
osv_json = JSON.json(osv_affected, 2)Multiple Affected Packages
When an advisory affects multiple packages:
using PackageURLs
# List of affected packages
affected_packages = [
purl"pkg:julia/PackageA@1.0.0?uuid=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
purl"pkg:julia/PackageB@2.0.0?uuid=bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
]
# Generate affected entries
affected_entries = [
Dict(
"package" => Dict(
"ecosystem" => "Julia",
"name" => p.name,
"purl" => string(p)
)
)
for p in affected_packages
]Parsing PURLs from OSV Data
When processing OSV advisories that contain PURL strings:
using PackageURLs
# PURL string from OSV JSON
purl_string = "pkg:julia/Example@1.0.0?uuid=7876af07-990d-54b4-ab0e-23690620f79a"
# Safe parsing with error handling
purl = tryparse(PURL, purl_string)
if purl !== nothing
println("Package: $(purl.name)")
println("Version: $(purl.version)")
uuid_val = get(purl.qualifiers, "uuid", "unknown")
println("UUID: $uuid_val")
else
@warn "Invalid PURL in advisory: $purl_string"
endBest Practices
Always Include UUID for Julia Packages
Julia PURLs require the uuid qualifier. Without it, the PURL is ambiguous since package names are not globally unique:
# Correct - includes UUID
purl"pkg:julia/HTTP@1.10.0?uuid=cd3eb016-35fb-5094-929b-558a96fad6f3"
# Incorrect - will throw PURLError
parse(PURL, "pkg:julia/HTTP@1.10.0")Use tryparse for External Data
When parsing PURLs from external sources (OSV feeds, databases), always use tryparse to handle malformed data gracefully:
function process_advisory(purl_string::String)
purl = tryparse(PURL, purl_string)
if purl === nothing
@warn "Skipping invalid PURL: $purl_string"
return nothing
end
# Process valid PURL
return purl
endValidate Package Type
When processing Julia-specific advisories, verify the package type:
purl = parse(PURL, purl_string)
if purl.type != "julia"
error("Expected Julia PURL, got type: $(purl.type)")
endRelated Projects
- SecurityAdvisories.jl - Julia security advisory database
- OSV Schema - Open Source Vulnerability format specification
- PURL Specification - Package URL specification