Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9b95355
feat: 'fcli aviator entitlement': Add 'list-sast'/'list-dast' command…
AnkitRathod29 Feb 12, 2026
fc10bf0
Merge pull request #918 from ankit2995/ankit/dast-entitlements
rsenden Feb 25, 2026
e5e65b8
Implement streaming FVDL processing with memory tracking to optimize …
Feb 16, 2026
47519cd
refactor(aviator-common): Clean up redundant XML parsing dependencies
Feb 20, 2026
c2b289b
Merge pull request #920 from mneeta/feature/aviator-Stax-fvdl-processor
rsenden Feb 26, 2026
e738972
feat: Implement `--skip-if-exceeding-quota` and `--test-exceeding-quo…
AnkitRathod29 Feb 26, 2026
361a7b4
Add issue prioritization by folder for audit commands
Feb 25, 2026
3de405b
Resolve conflicts after base branch change to feat/v3.x/aviator/26.2
Feb 26, 2026
9230dd4
Merge pull request #927 from mneeta/feature/issue-prioritization-by-f…
rsenden Feb 26, 2026
dde89a9
Merge branch 'feat/v3.x/aviator/26.2' into ankit/aviator_quota_overflow
AnkitRathod29 Feb 27, 2026
fc35240
feat: Update GetDefaultQuotaRequest to use optional fields for token,…
AnkitRathod29 Feb 27, 2026
83d3c02
Merge branch 'dev/v3.x' into feat/v3.x/aviator/26.2
rsenden Mar 3, 2026
f2cc269
feat: Add --aviator-app-mapping option to ssc bulkaudit action
Mar 4, 2026
bdc9e0c
Merge pull request #939 from kireetivar/p/cdatla/bulk_audit_mapping
rsenden Mar 5, 2026
07d70eb
chore: Add validation for --aviator-app-mapping option
Mar 5, 2026
dcea406
Addressed Review comments
AnkitRathod29 Mar 6, 2026
cf8ea17
chore: Simplify validation logic for --aviator-app-mapping and --tag-…
Mar 6, 2026
0e31906
Merge branch 'fortify:dev/v3.x' into ankit/aviator_quota_overflow
ankit2995 Mar 6, 2026
a5c537f
Merge pull request #940 from kireetivar/p/kireetivar/add_validation_l…
rsenden Mar 6, 2026
50cc5b7
Resolved Conflicts.
AnkitRathod29 Mar 6, 2026
5a7e26c
Merge branch 'ankit/aviator_quota_overflow' of https://github.com/ank…
AnkitRathod29 Mar 6, 2026
62870dc
Revert "chore: DAST Automated fixes and missing option. (#937)"
AnkitRathod29 Mar 6, 2026
9dfc51f
Merge pull request #929 from ankit2995/ankit/aviator_quota_overflow
rsenden Mar 6, 2026
586ff8c
fix: Prevent Failed(No response from server) output when quota filter…
Mar 9, 2026
789bdec
Merge pull request #945 from mneeta/feature/issue-prioritization-by-f…
rsenden Mar 9, 2026
e8d2bd9
feat: add default empty string for missing buildId in FPRInfo and upd…
AnkitRathod29 Mar 9, 2026
d6ccd95
Merge branch 'dev/v3.x' into feat/v3.x/aviator/26.2
rsenden Mar 9, 2026
cfe9b29
Merge pull request #946 from ankit2995/ankit/D1999224
rsenden Mar 10, 2026
14e178e
feat(aviator): Improve apply-remediations UX with --latest, --all-ope…
Mar 17, 2026
68a4560
Exception message for 'm' option modified
Mar 20, 2026
446ca15
Address PR review comments for apply-remediations command
Mar 24, 2026
b6b051a
Address PR review comments: move FoD apply-remediations to fcli-fod a…
Mar 25, 2026
f8d7332
renamed --all-open-issues to --all
Mar 26, 2026
e29132f
Merge pull request #948 from mneeta/feature/improved-auto-remediation-ux
rsenden Mar 26, 2026
80aa31c
refactor: move FoDAviatorApplyRemediationsCommand test to fcli-fod mo…
Mar 27, 2026
1cc1918
Merge pull request #954 from mneeta/feature/fod-aviator-test-relocation
rsenden Mar 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
992 changes: 0 additions & 992 deletions CHANGELOG.md

This file was deleted.

11 changes: 8 additions & 3 deletions fcli-core/fcli-aviator-common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ tasks.withType<JavaCompile>().configureEach { dependsOn("generateProto") }
dependencies {
implementation(project(":fcli-core:fcli-common"))
implementation("org.yaml:snakeyaml:2.3")
implementation("jakarta.xml.bind:jakarta.xml.bind-api:2.3.3")
implementation("org.glassfish.jaxb:jaxb-runtime:2.3.3")

// JAXB for XML object marshalling (used in FVDLProcessor legacy parser)
implementation("jakarta.xml.bind:jakarta.xml.bind-api:3.0.1")
implementation("org.glassfish.jaxb:jaxb-runtime:3.0.2")
implementation("com.sun.activation:jakarta.activation:2.0.1")
implementation("jakarta.xml.ws:jakarta.xml.ws-api:3.0.1")

// Note: StAX (javax.xml.stream) uses Woodstox 7.1.1 via jackson-dataformat-xml
// from fcli-common (needed for XML output). No explicit dependency required.

implementation("com.auth0:java-jwt:4.5.0")
implementation("io.grpc:grpc-netty-shaded:1.76.0")
implementation("io.grpc:grpc-protobuf:1.76.0")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2021-2026 Open Text.
*
* The only warranties for products and services of Open Text
* and its affiliates and licensors ("Open Text") are as may
* be set forth in the express warranty statements accompanying
* such products and services. Nothing herein should be construed
* as constituting an additional warranty. Open Text shall not be
* liable for technical or editorial errors or omissions contained
* herein. The information contained herein is subject to change
* without notice.
*/
package com.fortify.cli.aviator._common.exception;

/**
* Exception thrown when quota-based filtering results in zero issues to audit.
* This is not a technical error but a business logic outcome indicating that
* all issues were filtered out based on quota and priority constraints.
*/
public class AviatorQuotaFilterException extends AviatorSimpleException {
public AviatorQuotaFilterException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static RemediationMetric applyRemediations(FprHandle fprHandle, String so
LOG.info("Starting apply auto-remediation process for file: {}", fprHandle.getFprPath());

if (!fprHandle.hasRemediations()) {
LOG.error("FPR file does not contain remediations.xml file: {}", fprHandle.getFprPath());
//LOG.error("FPR file does not contain remediations.xml file: {}", fprHandle.getFprPath());
throw new AviatorSimpleException("FPR file does not contain remediations.xml file.");
}
LOG.info("FPR validation successful");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import com.fortify.cli.aviator.fpr.model.AuditIssue;
import com.fortify.cli.aviator.fpr.model.FPRInfo;
import com.fortify.cli.aviator.fpr.processor.AuditProcessor;
import com.fortify.cli.aviator.fpr.processor.FVDLProcessor;
import com.fortify.cli.aviator.fpr.processor.StreamingFVDLProcessor;
import com.fortify.cli.aviator.util.FprHandle;
import com.fortify.cli.aviator.util.ResourceUtil;

Expand Down Expand Up @@ -65,28 +65,29 @@ public static FPRAuditResult auditFPR(AuditFprOptions options)
Map<String, AuditResponse> auditResponses = new ConcurrentHashMap<>();
AuditOutcome auditOutcome = performAviatorAudit(
parsedData, options.getLogger(), options.getToken(), options.getAppVersion(), options.getUrl(), options.getSscAppName(), options.getSscAppVersion(),
auditResponses, filterSelection
auditResponses, filterSelection, options.getFprHandle(), options.getFolderPriorityOrder()
);

// --- STAGE 4: FINALIZATION ---
return finalizeFprAudit(
auditOutcome, auditResponses, parsedData.auditProcessor,
tagMappingConfig, parsedData.fprInfo, parsedData.fvdlProcessor
tagMappingConfig, parsedData.fprInfo
);
}

private static ParsedFprData prepareAndParseFpr(FprHandle fprHandle) {
try {
// Processors now take the FprHandle directly, no more extracted path
AuditProcessor auditProcessor = new AuditProcessor(fprHandle);
FVDLProcessor fvdlProcessor = new FVDLProcessor(fprHandle);
//FVDLProcessor fvdlProcessor = new FVDLProcessor(fprHandle);
StreamingFVDLProcessor streamingFVDLProcessor = new StreamingFVDLProcessor(fprHandle);

Map<String, AuditIssue> auditIssueMap = auditProcessor.processAuditXML();
FPRProcessor fprProcessor = new FPRProcessor(fprHandle, auditIssueMap, auditProcessor);
List<Vulnerability> vulnerabilities = fprProcessor.process(fvdlProcessor);
List<Vulnerability> vulnerabilities = fprProcessor.process(streamingFVDLProcessor);
FPRInfo fprInfo = fprProcessor.getFprInfo();

return new ParsedFprData(auditIssueMap, vulnerabilities, fprInfo, auditProcessor, fvdlProcessor);
return new ParsedFprData(auditIssueMap, vulnerabilities, fprInfo, auditProcessor, streamingFVDLProcessor);
} catch (Exception e) {
LOG.error("A critical error occurred during FPR processing.", e);
throw new AviatorTechnicalException("Failed to process FPR contents.", e);
Expand All @@ -106,21 +107,28 @@ private static TagMappingConfig loadTagMappingConfig(String tagMappingFilePath)
private static AuditOutcome performAviatorAudit(
ParsedFprData parsedData, IAviatorLogger logger,
String token, String appVersion, String url, String sscAppName, String sscAppVersion,
Map<String, AuditResponse> auditResponsesToFill, FilterSelection filterSelection) {
Map<String, AuditResponse> auditResponsesToFill, FilterSelection filterSelection, FprHandle fprHandle, List<String> folderPriorityOrder) {

IssueAuditor issueAuditor = new IssueAuditor(
parsedData.vulnerabilities, parsedData.auditProcessor, parsedData.auditIssueMap,
parsedData.fprInfo, sscAppName, sscAppVersion, filterSelection, logger
parsedData.vulnerabilities,
parsedData.auditProcessor,
parsedData.auditIssueMap,
parsedData.fprInfo,
sscAppName,
sscAppVersion,
filterSelection,
logger,
folderPriorityOrder
);
return issueAuditor.performAudit(
auditResponsesToFill, token, appVersion, parsedData.fprInfo.getBuildId(), url
auditResponsesToFill, token, appVersion, parsedData.fprInfo.getBuildId(), url, fprHandle
);
}

private static FPRAuditResult finalizeFprAudit(
AuditOutcome auditOutcome, Map<String, AuditResponse> auditResponses,
AuditProcessor auditProcessor, TagMappingConfig tagMappingConfig,
FPRInfo fprInfo, FVDLProcessor fvdlProcessor) {
FPRInfo fprInfo) {

int totalIssuesToAudit = auditOutcome.getTotalIssuesToAudit();
if (auditResponses.isEmpty()) {
Expand Down Expand Up @@ -160,10 +168,10 @@ private static FPRAuditResult finalizeFprAudit(

File updatedFile = null;
if (issuesSuccessfullyAudited > 0) {
updatedFile = auditProcessor.updateAndSaveAuditAndRemediationsXml(auditResponses, tagMappingConfig, fprInfo, fvdlProcessor);
updatedFile = auditProcessor.updateAndSaveAuditAndRemediationsXml(auditResponses, tagMappingConfig, fprInfo);
}

LOG.info("FPR audit process completed with status: {}", status);
return new FPRAuditResult(updatedFile, status, message, (int) issuesSuccessfullyAudited, totalIssuesToAudit);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fortify.cli.aviator._common.exception.AviatorQuotaFilterException;
import com.fortify.cli.aviator._common.exception.AviatorSimpleException;
import com.fortify.cli.aviator._common.exception.AviatorTechnicalException;
import com.fortify.cli.aviator.audit.model.AuditOutcome;
Expand All @@ -51,6 +52,7 @@
import com.fortify.cli.aviator.grpc.AviatorGrpcClient;
import com.fortify.cli.aviator.grpc.AviatorGrpcClientHelper;
import com.fortify.cli.aviator.util.Constants;
import com.fortify.cli.aviator.util.FprHandle;
import com.fortify.cli.aviator.util.StringUtil;


Expand All @@ -74,15 +76,16 @@ public class IssueAuditor {
private final FPRInfo fprInfo;
private final FilterSelection filterSelection;


private final TagDefinition analysisTag;
private TagDefinition humanAuditTag;
private TagDefinition aviatorStatusTag;

private final IAviatorLogger logger;
private final List<String> customPriorityOrder;

public IssueAuditor(List<Vulnerability> vulnerabilities, AuditProcessor auditProcessor, Map<String, AuditIssue> auditIssueMap, FPRInfo fprInfo, String SSCApplicationName, String SSCApplicationVersion, FilterSelection filterSelection , IAviatorLogger logger) {
public IssueAuditor(List<Vulnerability> vulnerabilities, AuditProcessor auditProcessor, Map<String, AuditIssue> auditIssueMap, FPRInfo fprInfo, String SSCApplicationName, String SSCApplicationVersion, FilterSelection filterSelection , IAviatorLogger logger, List<String> customPriorityOrder) {
this.logger = logger;
this.customPriorityOrder = customPriorityOrder;
this.MAX_PER_CATEGORY = Constants.MAX_PER_CATEGORY;
this.MAX_TOTAL = Constants.MAX_TOTAL;
this.MAX_PER_CATEGORY_EXCEEDED = Constants.MAX_PER_CATEGORY_EXCEEDED;
Expand Down Expand Up @@ -141,7 +144,7 @@ private TagDefinition resolveHumanAuditStatus() {
}

public AuditOutcome performAudit(Map<String, AuditResponse> auditResponses, String token,
String projectName, String projectBuildId, String url) {
String projectName, String projectBuildId, String url, FprHandle fprHandle) {
projectName = StringUtil.isEmpty(projectName) ? projectBuildId : projectName;
logger.progress("Starting audit for project: %s", projectName);

Expand All @@ -154,13 +157,18 @@ public AuditOutcome performAudit(Map<String, AuditResponse> auditResponses, Stri
} else {
try (AviatorGrpcClient client = AviatorGrpcClientHelper.createClient(url, logger, DEFAULT_PING_INTERVAL_SECONDS)) {
CompletableFuture<Map<String, AuditResponse>> future =
client.processBatchRequests(promptsToAudit, projectName, fprInfo.getBuildId(), SSCApplicationName, SSCApplicationVersion, token);
client.processBatchRequests(promptsToAudit, projectName, fprInfo.getBuildId(), SSCApplicationName, SSCApplicationVersion, token, fprHandle, customPriorityOrder);
Map<String, AuditResponse> responses = future.get(500, TimeUnit.MINUTES);
responses.forEach((requestId, response) -> auditResponses.put(response.getIssueId(), response));
logger.progress("Audit completed");
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof AviatorSimpleException) {
// Handle quota filtering exception (all issues filtered out)
if (cause instanceof AviatorQuotaFilterException) {
logger.progress("All issues filtered out due to quota constraints: %s", cause.getMessage());
// Update totalIssuesToAudit to reflect actual auditable count (0)
totalIssuesToAudit = 0;
} else if (cause instanceof AviatorSimpleException) {
throw (AviatorSimpleException) cause;
} else if (cause instanceof AviatorTechnicalException) {
throw (AviatorTechnicalException) cause;
Expand Down Expand Up @@ -203,10 +211,11 @@ private ConcurrentLinkedDeque<UserPrompt> prepareAndFilterPrompts() {
.collect(Collectors.toList());

// Apply secondary checks (like 'isAudited')
prompts = prompts.stream()
.filter(this::shouldInclude)
.collect(Collectors.toList());

return prompts.stream()
.filter(this::shouldInclude).collect(Collectors.toCollection(ConcurrentLinkedDeque::new));

return prompts.stream().collect(Collectors.toCollection(ConcurrentLinkedDeque::new));
}


Expand Down
Loading
Loading