Feat/sast dast correlation#992
Feat/sast dast correlation#992mneeta wants to merge 6 commits intofortify:feat/v3.x/aviator/26.3from
Conversation
…on and SSC upload - Add correlate-sast-dast command for SSC Aviator - Parse SAST (FVDL) and DAST (WebInspect) FPRs from SSC - Group findings by category, identify mixed SAST+DAST buckets - gRPC-based correlation stream with Aviator server - Inject ExternalFindings into DAST FPR for SSC correlation visibility - Upload enriched DAST FPR back to SSC - Add streaming WebInspect parser for large DAST FPRs - Add getLatestSASTArtifact/getLatestDASTArtifact helpers - Add unit and integration tests for ExternalFindings injection flow - Add correlation.proto for gRPC service definition
… upsert AI_CORRELATION_METADATA session - Extract AviatorSSCCorrelateHelper, AviatorSSCCorrelateFprParser, AviatorSSCCorrelateDownloadHelper from command class to reduce GOD class - Add proper try/catch(IOException) around FPR download calls - Add progress logging at each major step (download, parse, group, correlate, inject, upload) - Add per-response progress in CorrelationStreamProcessor (Correlating X of Y / Validating X of Y) - Rename ExternalFindingsInjector to DastFprCorrelationEnricher to reflect full scope - Upsert synthetic <Session requestId=AI_CORRELATION_METADATA> in webinspect.xml with HTTP Date header to avoid needing to delete prior DAST scan before re-upload - Update references in test classes
…ied pairs, write last_correlation attribute - Add CorrelationResult record to return both confirmed and rejected pairs from gRPC stream - Track rejected pairs in CorrelationStreamState + CorrelationStreamProcessor - Parse ExternalFindings from DAST FPR via StreamingWebInspectParser to build confirmed pair keys - Add SastFprCorrelationRecorder: read/write DAST_CORRELATION_STATUS tag in SAST FPR audit.xml - Namespace-aware XML parsing (setNamespaceAware + getElementsByTagNameNS) - Creates new Issue elements for SAST findings with no prior audit record - Merge logic: CORRELATED is sticky, cannot be downgraded to REJECTED on re-run - Skip both confirmed and rejected pairs on subsequent runs (alreadyTriedKeys union) - Fix SAST FPR upload: use PROJECT_VERSION_ARTIFACTS restUpload (not UPLOAD_RESULT_FILE htmlUpload) to avoid duplicate scan GUID error in SSC - Add AviatorSSCAttributeDefs + AviatorSSCAttributeHelper: create-if-not-exists last_correlation TEXT attribute definition on SSC instance, write ISO-8601 UTC timestamp after FPR uploads - Add last_correlation attribute synchronization to prepare command (AviatorSSCPrepareHelper) - Add Step 6c to correlate-sast-dast: write last_correlation timestamp after all FPR uploads - Fix AviatorSSCCustomTagHelper: null-safe cast for valueList on TEXT-type tags (NullNode guard)
…sueList namespace lookup, add audit.xml validation - Add receivedCorrelationResponses to CorrelationResult record for Phase 1 response count - Output now includes succeeded (responses received) and skipped (submitted - succeeded) - Fix SastFprCorrelationRecorder: fallback to no-namespace getElementsByTagName for IssueList in un-audited FPRs where audit.xml uses default (null) namespace - Match parent IssueList namespace when creating new Issue elements - Add audit.xml existence validation in parseSastFpr() and parseDastFpr() - Prevent double-wrapping of FcliSimpleException in FPR parser catch blocks
rsenden
left a comment
There was a problem hiding this comment.
I've done a quick review for now; please address review points and I'll re-review once done and when I have more time.
| private String actionResult = "CORRELATED"; | ||
|
|
||
| @Override | ||
| public JsonNode getJsonNode(UnirestInstance unirest) { |
There was a problem hiding this comment.
This method is way too long; please improve
| @Mixin private ProgressWriterFactoryMixin progressWriterFactoryMixin; | ||
| @Mixin private SSCAppVersionResolverMixin.RequiredOption appVersionResolver; | ||
| @Mixin private AviatorUserSessionDescriptorSupplier sessionDescriptorSupplier; | ||
| @Option(names = {"--app"}) private String appName; |
There was a problem hiding this comment.
I assume this is Aviator app name? Is this option name consistent with other places? Any chance for confusion between SSC app and Aviator app?
| result.addEntry("Attribute Definition", "VERIFIED", | ||
| "'" + attrDef.name() + "' is already present on this SSC instance."); | ||
| } else { | ||
| createDefinition(); |
There was a problem hiding this comment.
I assume this will fail for non-admin users. Not wure what attributes are handled here exactly, but shouldn't creating the definitions be part of the ssc prepare command?
| * custom tags. | ||
| */ | ||
| @RequiredArgsConstructor | ||
| public class AviatorSSCAttributeHelper { |
There was a problem hiding this comment.
We already have SSC attribute helper classes I think in SSC module; how is this different? Seems like this class and for example AviatorSSCAttributeDefs contain functionality related to correlation, so should probably be named as such.
| */ | ||
| package com.fortify.cli.aviator.ssc.helper; | ||
|
|
||
| public final class AviatorSSCAttributeDefs { |
There was a problem hiding this comment.
We already have SSC attribute definition helper classes I think in SSC module; how is this different? Seems like this class contains functionality related to correlation, so should probably be named as such.
| /** | ||
| * Prints the mixed categories as a formatted table to the log. | ||
| */ | ||
| private void printMixedCategoriesTable(List<CategoryBucket> mixed) { |
| * @param rejectedPairs pairs rejected by this run's gRPC validation | ||
| */ | ||
| @SneakyThrows | ||
| public static void writeCorrelationTags(Path sastFprPath, |
Summary
Adds the fcli aviator ssc correlate-sast-dast command that identifies related SAST and DAST findings in an SSC application version using the Aviator gRPC service, injects correlation data into the DAST FPR for SSC visibility, and persists all tried pairs to avoid redundant work on re-runs.
Key Capabilities
Correlation: Downloads SAST and DAST FPRs from SSC, groups findings by vulnerability category, sends mixed-category pairs to the Aviator gRPC server for correlation and validation
SSC Integration: Injects confirmed pairs as into the DAST FPR and uploads back to SSC, making correlations visible in the SSC UI
Idempotent Re-runs: Persists both confirmed and rejected pair outcomes in the SAST FPR's audit.xml via a DAST_CORRELATION_STATUS custom tag — previously tried pairs are skipped on subsequent runs
last_correlation Attribute: Writes an ISO-8601 UTC timestamp to the SSC app version after each successful run, enabling the bulk-correlation action to detect stale versions
prepare Command Integration: Proactively creates the DAST_CORRELATION_STATUS custom tag and last_correlation attribute definition on the SSC instance
Command Output
{
"applicationName": "MyApp",
"versionName": "1.0",
"operation": {
"correlate": {
"submitted": 5,
"succeeded": 5,
"skipped": 0,
"correlated": 2
}
}
}
Field Description
submitted SAST findings with at least one untried DAST pairing
succeeded Correlation requests that received a server response
skipped Requests with no response (submitted - succeeded)
correlated Confirmed SAST-DAST pairs