OSS-Fuzz Advisory Processor — Design Document
1. Overview
Purpose: Process the Google OSS-Fuzz vulnerability database OSV YAML files (OSV-*.yaml) into CVEMetadata and related tables.
Data source: Google OSS-Fuzz vulnerability database — github.com/google/oss-fuzz-vulns (git repository cloned to /data/oss-fuzz-vulns)
Schedule: Runs weekly on Thursdays at 04:00 UTC (cron(0 4 ? * THU *)).
Timeout: 45 minutes
Resources: 256 CPU units, 512 MB memory
What it reads:
- Git repository at
/data/oss-fuzz-vulns/vulns/— walks files matchingOSV-*.yaml - Read replica: existing
sourceFileHashvalues for per-file resume - Read replica:
BulkDataDumpTrackerrow forossfuzz_advisory(HEAD SHA dedup)
What it writes:
CVEMetadata(upsert, source=ossfuzz)CVEDescription,CVEMetadataReferences,CVEMetric,CVEProblemTypeCVEAffected,CVEAffectedVersionDependency,DependencyRegistry,PackageVersion,PackageVersionCVE,GitHubRepoDependency— viadb.EnrichAffectedWithDependency, called for every affected entry insidestoreAdvisoryCVEAlias— always, viadb.InsertAliases, even for advisories with no alias list, so the same-cveIdcross-source backfill runs on every store- A derived Vulnetix CVSS v4 metric (
containerType="vulnetix") when the advisory has descriptions and does not suppress derived metrics BulkDataDumpTracker- When AI enrichment is enabled (
PIX_INFERENCE_ENABLED+ gateway token, i.e. ECS only):CVEProblemType(derivedBy="vulnetix"),CVEAttackTechnique/CVEAttackMitigation/CVEAttackDetection/CVEAttackD3fend,CVETreeSitter, and onePixLogrow per pass
Environment variables:
DATABASE_URL— RDS Write Proxy connection string (required)DATABASE_URL_READ— RDS Read Replica connection string (optional)
2. Business Logic
Pipeline Reuse
OSS-Fuzz uses the identical shared pipeline as PyPI processor (internal/processor). The only differences are constants: source=ossfuzz, trackerSource=ossfuzz_advisory, referenceSource=OSS-Fuzz, file prefix OSV-, and repo path /data/oss-fuzz-vulns.
Git Pull Strategy
processor.PullOrClone attempts git pull --ff-only on the existing clone. Returns HEAD SHA. Exits on error.
SHA-based Freshness Check
Compares HEAD SHA against BulkDataDumpTracker.sha256 for ossfuzz_advisory. Skips on match unless --force.
Per-File Resume
LoadProcessedHashes(source="ossfuzz") loads existing (cveId, sourceFileHash) pairs. SHA1 computed per file; skip if unchanged. The read is given its own 5-minute context because the replica scan is slow at production scale.
Delta Window
processor.DetectChangedFiles narrows the walk to files git reports as recently changed, and processor.FilterPaths applies it. Skipped on the first run (no tracker row) and under --force, where the full tree is walked.
Soft Deadline
When EXPECTED_DURATION_MINUTES is set (ECS only), batches stop dispatching at
minutes - 10 (main.go:63-65). Local backfills unset the variable and run to
completion.
Known defect — the intended behaviour is that a soft-deadline truncation leaves the tracker un-advanced so the next run resumes. The guard in
main.go:159only testsctx.Err(), which a soft-deadline break ininternal/processor/pipeline.go:161-164never sets, so the HEAD SHA is written after a truncated run. The next scheduled run then sees an unchanged SHA and exits withNoWork, so any file the truncated run did not reach is skipped until upstream pushes a commit — and even then the 3-day delta window excludes it. Tracked in.repo/efficacy/ossfuzz-git-processor.yaml.
Malicious Package Detection
Same 6-criteria check as PyPI processor. OSS-Fuzz advisories should not contain malicious packages, but the check runs anyway for safety.
CVE ID Derivation
Scans aliases[] for CVE-YYYY-NNNN+ pattern. Otherwise uses OSV-YYYY-NNNNN as the cveId.
Ecosystem Mapping
OSS-Fuzz ecosystem maps to collection URL https://google.github.io/oss-fuzz (defined in osv/mapper.go ecosystemCollectionURLs).
Batch Processing
Batches of 100 files per transaction, with per-file SAVEPOINT for fault isolation.
Tracker Update
Only updates tracker on a clean run (filesErrored == 0). Stores HEAD SHA in sha256.
Exit Semantics
File errors do not by themselves fail the task: notify.Finalize decides, and
the process exits 0 unless the failure ratio is systemic (main.go:140-155). The
tracker is skipped in that case so the next run retries. A pipeline-level error or
a failed tracker write exits 1.
3. Architecture Diagram
4. Deployment Diagram
post-push-ecr.sh] -->|push ARM64 image| ECR[ECR: go-processors
tag: go-ossfuzz-git-processor-sha-xxx] ECR --> TASKDEF[ECS Task Definition
go-ossfuzz-git-processor] TASKDEF --> EB[EventBridge Schedule
go-ossfuzz-git-processor
cron 0 4 ? * THU *] EB -->|trigger| FARGATE[ECS Fargate Task
vdb-scheduler cluster
ARM64 ap-southeast-2] FARGATE --> CW[CloudWatch Logs
/ecs/vdb-scheduler/go-ossfuzz-git-processor] FARGATE --> WRITE[RDS Write Proxy
cf-hyperdrive.proxy-...] FARGATE --> READ[RDS Read Replica
hyperdrive-saas-read...] FARGATE -->|baked into image
ossfuzz-git-data stage| REPO[/data/oss-fuzz-vulns]
5. Processing Flow
== headSHA?} TRACKER -->|yes, no --force| EXIT0([Exit 0]) TRACKER -->|no or --force| LOAD[LoadProcessedHashes source=ossfuzz] LOAD --> WALK[WalkAdvisories vulns/ OSV-*.yaml] WALK --> BATCH[For each batch of 100 files] BATCH --> TX[Begin transaction] TX --> FILE[For each file] FILE --> SP[SAVEPOINT sp_file] SP --> READ2[ReadFile + SHA1] READ2 --> PARSE[ParseYAML] PARSE -->|error| ROLLBACK[ROLLBACK TO SAVEPOINT
count error] PARSE -->|ok| CVEID[Derive cveId from aliases] CVEID --> SKIP{skipSet match?} SKIP -->|yes, no force| RELEASE[RELEASE SAVEPOINT
count skipped] SKIP -->|no or force| MALICIOUS{IsMaliciousPackage?} MALICIOUS -->|yes| RELEASE MALICIOUS -->|no| STORE[storeAdvisory
UpsertCVEMetadata + children] STORE -->|error| ROLLBACK STORE -->|ok| RELEASE ROLLBACK --> FILE RELEASE --> FILE FILE -->|done| COMMIT[Commit transaction] COMMIT --> BATCH BATCH -->|done| ERRORS{filesErrored > 0?} ERRORS -->|yes| FAIL2([Exit 1 — skip tracker]) ERRORS -->|no| UPSERT_TRACKER[UpsertTracker ossfuzz_advisory
sha256=headSHA] UPSERT_TRACKER --> DONE([Exit 0])
6. Data Mapping
S3 Persistence
- Archive path:
ossfuzz/files/{sha256}/{filename}✓ - Quarantine path:
failed-feeds/ossfuzz-git-processor/{YYYY-MM-DD}/{reason}/{filename}✓ - Failure reasons emitted:
parse-error,store-error
Uses s3client.Uploader from internal/s3client/uploader.go. Skipped when S3_BUCKET_NAME is unset (local dev).
See the S3 Persistence Contract for the full reason taxonomy.