feat: add rating source tracking for context-aware OWASP scores#6210
feat: add rating source tracking for context-aware OWASP scores#6210fahedouch wants to merge 1 commit into
Conversation
Signed-off-by: Fahed Dorgaa <fahed.dorgaa@gmail.com>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a source column to analyses that tracks the origin of an analysis (POLICY, VEX, MANUAL, NVD) and enforces precedence rules so lower-precedence sources cannot overwrite higher-precedence ones. Also extends the analysis request/command surface with OWASP RR vector/score and updates the CycloneDX VEX importer to ingest OWASP ratings.
Changes:
- Introduces
RatingSourceenum +SOURCEcolumn onANALYSIS, with migration and DAO/mapper wiring to persist it. - Threads
source,owaspVector,owaspScorethroughMakeAnalysisCommand, REST request, and apply overwrite precedence inAnalysisQueryManager#makeAnalysis. - Updates
CycloneDXVexImporterto support OWASP ratings and proceed when a vulnerability has ratings but no analysis block.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| migration/.../V202605291854__add_source_column_to_analysis.sql | Adds SOURCE column, index, and backfills POLICY/MANUAL values. |
| apiserver/.../model/RatingSource.java | New enum encoding source precedence and canOverwrite logic. |
| apiserver/.../model/Analysis.java | Adds persistent source field with getters/setters. |
| apiserver/.../persistence/command/MakeAnalysisCommand.java | Adds source, owaspVector, owaspScore fields/builders. |
| apiserver/.../persistence/AnalysisQueryManager.java | Guards updates by precedence and audits OWASP/source changes. |
| apiserver/.../persistence/jdbi/AnalysisDao.java | Includes SOURCE in policy-driven analysis upserts. |
| apiserver/.../persistence/jdbi/VulnerabilityPolicyDao.java | Resets SOURCE when unassigning policy. |
| apiserver/.../persistence/jdbi/mapping/AnalysisRowMapper.java | Reads SOURCE column into Analysis. |
| apiserver/.../resources/v1/vo/AnalysisRequest.java | Adds OWASP vector/score request fields. |
| apiserver/.../resources/v1/AnalysisResource.java | Passes OWASP fields and MANUAL source to the command. |
| apiserver/.../parser/cyclonedx/CycloneDXVexImporter.java | Imports OWASP ratings as VEX-sourced analyses. |
| apiserver/.../test/.../RatingSourceTest.java | Tests for precedence/overwrite behavior. |
| apiserver/.../test/.../AnalysisResourceTest.java | Updates constructor calls for new request params. |
| apiserver/.../test/.../ProcessScheduledNotificationRuleActivityTest.java | Adopts builder-style MakeAnalysisCommand. |
| final boolean canUpdate = canUpdateAnalysis(analysis.getSource(), command.source()); | ||
|
|
||
| if (canUpdate) { |
| private boolean canUpdateAnalysis(final RatingSource existingSource, final RatingSource newSource) { | ||
| if (newSource == null || existingSource == null) { | ||
| return true; | ||
| } | ||
| return newSource.canOverwrite(existingSource); | ||
| } |
| final java.math.BigDecimal score = rating.getScore() != null | ||
| ? java.math.BigDecimal.valueOf(rating.getScore()) | ||
| : null; |
| maybeSet(rs, "CVSSV4SCORE", ResultSet::getBigDecimal, analysis::setCvssV4Score); | ||
| maybeSet(rs, "OWASPVECTOR", ResultSet::getString, analysis::setOwaspVector); | ||
| maybeSet(rs, "OWASPSCORE", ResultSet::getBigDecimal, analysis::setOwaspScore); | ||
| maybeSet(rs, "SOURCE", ResultSet::getString, value -> analysis.setSource(RatingSource.valueOf(value))); |
| -- Backfill: other analyses with meaningful data get MANUAL source | ||
| UPDATE "ANALYSIS" | ||
| SET "SOURCE" = 'MANUAL' | ||
| WHERE "SOURCE" IS NULL | ||
| AND ( | ||
| ("STATE" IS NOT NULL AND "STATE" != 'NOT_SET') | ||
| OR ("JUSTIFICATION" IS NOT NULL AND "JUSTIFICATION" != 'NOT_SET') | ||
| OR ("RESPONSE" IS NOT NULL AND "RESPONSE" != 'NOT_SET') | ||
| OR "SEVERITY" IS NOT NULL | ||
| OR "CVSSV2VECTOR" IS NOT NULL | ||
| OR "CVSSV3VECTOR" IS NOT NULL | ||
| OR "CVSSV4VECTOR" IS NOT NULL | ||
| OR "OWASPVECTOR" IS NOT NULL | ||
| ); |
| if (command.source() != null && analysis.getSource() != command.source()) { | ||
| if (analysis.getSource() != null) { | ||
| auditTrailComments.add("Source: %s → %s".formatted(analysis.getSource(), command.source())); | ||
| } | ||
| analysis.setSource(command.source()); | ||
| } |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 26 |
| Duplication | 0 |
🟢 Coverage 80.36% diff coverage · -0.03% coverage variation
Metric Results Coverage variation ✅ -0.03% coverage variation (-1.00%) Diff coverage ✅ 80.36% diff coverage (70.00%) Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (659d391) 41636 35834 86.06% Head commit (2a2c8a8) 41693 (+57) 35869 (+35) 86.03% (-0.03%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#6210) 112 90 80.36% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Description
Re-targeting DependencyTrack/hyades-apiserver#1928 here, since v5 dev moved to this repo (asked by @nscuro: DependencyTrack/hyades-apiserver#1928 (comment)).
Same change as the original PR, just rebased on main. Only thing that changed: renamed the migration so it runs after the latest one on main instead of in the middle.
Addressed Issue
No separate issue — this is the re-target of DependencyTrack/hyades-apiserver#1928 onto this repo, as requested by @nscuro for the v5 GA move.
Additional Details
Checklist
docs/adr/