From 86f8f86e2b632895767622fca0d5f846d83e8a44 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Tue, 17 Mar 2026 10:23:32 +0530 Subject: [PATCH 1/2] Devassist asca behaviour --- .../devassist/ignore/IgnoreEntry.java | 7 +- .../devassist/ignore/IgnoreManager.java | 151 +++++++++++++++++- .../devassist/model/Vulnerability.java | 1 + .../scanners/asca/AscaScanResultAdaptor.java | 66 +++++++- .../scanners/asca/AscaScannerService.java | 32 +++- 5 files changed, 244 insertions(+), 13 deletions(-) diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreEntry.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreEntry.java index 5d27748c3..0d11c595a 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreEntry.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreEntry.java @@ -40,14 +40,19 @@ public static final class FileReference { public String path; public boolean active; public Integer line; + public String problematicLine; public FileReference() { } - public FileReference(String relativePath, boolean b, int line) { + public FileReference(String relativePath, boolean b, int line, String problematicLine) { this.path = relativePath; this.active = b; this.line = line; + if (!problematicLine.isEmpty()) { + this.problematicLine = problematicLine; + } + } } } diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java index a728920f0..4fe7d14b3 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java @@ -126,7 +126,7 @@ public void addAllIgnoredEntry(ScanIssue issueToIgnore, String clickId) { fileRefs.add(new IgnoreEntry.FileReference( ignoreFileManager.normalizePath(issue.getFilePath()), true, - issue.getLocations().get(0).getLine())); + issue.getLocations().get(0).getLine(), "")); scanFileAndUpdateResults(issue.getFilePath(), issue.getScanEngine()); return true; }); @@ -343,7 +343,7 @@ public IgnoreEntry convertToIgnoredEntryIac(ScanIssue detail, String clickId) { ignoreEntry.setSimilarityId(vulnerability.getSimilarityId()); ignoreEntry.setSeverity(vulnerability.getSeverity()); ignoreEntry.setDescription(vulnerability.getDescription()); - ignoreEntry.setFiles(List.of(new IgnoreEntry.FileReference(relativePath, true, line))); + ignoreEntry.setFiles(List.of(new IgnoreEntry.FileReference(relativePath, true, line, ""))); return ignoreEntry; }); ifExistingIssue(detail, entry); @@ -383,7 +383,7 @@ public IgnoreEntry convertToIgnoredEntryAsca(ScanIssue detail, String clickId) { ignoreEntry.setRuleId(detail.getRuleId()); ignoreEntry.setSeverity(vulnerability.getSeverity()); ignoreEntry.setDescription(vulnerability.getDescription()); - ignoreEntry.setFiles(List.of(new IgnoreEntry.FileReference(relativePath, true, line))); + ignoreEntry.setFiles(List.of(new IgnoreEntry.FileReference(relativePath, true, line, vulnerability.getProblematicLine()))); return ignoreEntry; }); ifExistingIssue(detail, entry); @@ -404,7 +404,7 @@ public IgnoreEntry convertToIgnoredEntry(ScanIssue detail, String clickId) { String vulnerabilityKey = createJsonKeyForIgnoreEntry(detail, clickId); int line = detail.getLocations().get(0).getLine(); IgnoreEntry entry = ignoreFileManager.getIgnoreData().computeIfAbsent(vulnerabilityKey, k -> { - IgnoreEntry.FileReference fileRef = new IgnoreEntry.FileReference(relativePath, true, line); + IgnoreEntry.FileReference fileRef = new IgnoreEntry.FileReference(relativePath, true, line, ""); ArrayList fileReference = new ArrayList<>(); fileReference.add(fileRef); IgnoreEntry ignoreEntry = new IgnoreEntry(); @@ -444,6 +444,15 @@ public IgnoreEntry convertToIgnoredEntry(ScanIssue detail, String clickId) { private void ifExistingIssue(ScanIssue detail, IgnoreEntry entry) { String relativePath = ignoreFileManager.normalizePath(detail.getFilePath()); int line = detail.getLocations().get(0).getLine(); + String problematicLine = null; + if (detail.getScanEngine() == ScanEngine.ASCA && detail.getVulnerabilities() != null && !detail.getVulnerabilities().isEmpty()) { + // Find the matching vulnerability for this line + for (Vulnerability v : detail.getVulnerabilities()) { + // You may want to match by line or other criteria if needed + problematicLine = v.getProblematicLine(); + break; // Use the first for now, or improve as needed + } + } // Ensure files list is mutable if (!(entry.getFiles() instanceof ArrayList)) { entry.setFiles(new ArrayList<>(entry.getFiles())); @@ -453,8 +462,13 @@ private void ifExistingIssue(ScanIssue detail, IgnoreEntry entry) { .findFirst(); if (existing.isPresent()) { existing.get().setActive(true); + // Update problematicLine if ASCA and not set or different + if (detail.getScanEngine() == ScanEngine.ASCA && problematicLine != null && + (existing.get().getProblematicLine() == null || !existing.get().getProblematicLine().equals(problematicLine))) { + existing.get().setProblematicLine(problematicLine); + } } else { - entry.getFiles().add(new IgnoreEntry.FileReference(relativePath, true, line)); + entry.getFiles().add(new IgnoreEntry.FileReference(relativePath, true, line, problematicLine)); } } @@ -721,4 +735,131 @@ private List createIgnoreKeysForScanIssue(ScanIssue scanIssue) { } return keys; } + + /** + * Updates line numbers for ignored ASCA entries based on new scan results, using problematicLine content for matching. + * For each ignored file reference, if a scan result with the same problematicLine is found, update the line number in the ignore entry. + * Removes file references and ignore entries that are no longer present in the scan result. + * + * @param fullScanResults The scan results containing updated line numbers and issues + * @param filePath The path of the file that was scanned and needs line number updates + */ + public void updateLineNumbersForIgnoredEntriesByProblematicLine(ScanResult fullScanResults, String filePath) { + List allIssuesForFile = fullScanResults.getIssues(); + if (allIssuesForFile == null || allIssuesForFile.isEmpty()) { + LOGGER.debug(String.format("ASCA-Ignore: No issues found in scan results for file: %s", filePath)); + return; + } + String relativePath = ignoreFileManager.normalizePath(filePath); + boolean hasChanges = false; + // Build a list of all vulnerabilities with their problematicLine and line number + List vulnerabilitiesWithLine = new ArrayList<>(); + Set presentProblematicLines = new HashSet<>(); + for (ScanIssue scanIssue : allIssuesForFile) { + if (scanIssue.getVulnerabilities() != null) { + for (Vulnerability v : scanIssue.getVulnerabilities()) { + int line = (scanIssue.getLocations() != null && !scanIssue.getLocations().isEmpty()) + ? scanIssue.getLocations().get(0).getLine() : 0; + vulnerabilitiesWithLine.add(new VulnerabilityWithLine(v.getProblematicLine(), line)); + if (v.getProblematicLine() != null) { + presentProblematicLines.add(v.getProblematicLine()); + } + } + } + } + // Collect keys to remove + List keysToRemove = new ArrayList<>(); + // Iterate through all ignore entries using normal for-each + for (Map.Entry mapEntry : ignoreFileManager.getIgnoreData().entrySet()) { + IgnoreEntry ignoreEntry = mapEntry.getValue(); + if (!"ASCA".equalsIgnoreCase(String.valueOf(ignoreEntry.getType()))) { + continue; // Only process ASCA entries + } + // Remove file references that are not present in the scan result + List fileRefs = ignoreEntry.getFiles(); + List fileRefsToRemove = new ArrayList<>(); + for (IgnoreEntry.FileReference fileRef : fileRefs) { + if (fileRef.getPath().equals(relativePath) && fileRef.isActive()) { + String ignoredProblematicLine = fileRef.getProblematicLine(); + // Find a matching vulnerability by problematicLine (null-safe) + VulnerabilityWithLine match = vulnerabilitiesWithLine.stream() + .filter(vwl -> Objects.equals(vwl.problematicLine, ignoredProblematicLine)) + .findFirst().orElse(null); + if (match != null && match.line > 0 && fileRef.getLine() != match.line) { + fileRef.setLine(match.line); + hasChanges = true; + } + // If problematicLine is not present in the scan result, mark this file reference for removal + if (ignoredProblematicLine == null || !presentProblematicLines.contains(ignoredProblematicLine)) { + fileRefsToRemove.add(fileRef); + hasChanges = true; + } + } + } + // Remove marked file references + if (!fileRefsToRemove.isEmpty()) { + fileRefs.removeAll(fileRefsToRemove); + } + // If no file references left, mark the key for removal + if (ignoreEntry.getFiles().isEmpty()) { + keysToRemove.add(mapEntry.getKey()); + } + } + // Remove keys from ignore data + for (String keyToRemove : keysToRemove) { + ignoreFileManager.getIgnoreData().remove(keyToRemove); + hasChanges = true; + } + if (hasChanges) { + ignoreFileManager.saveIgnoreDataToDisk(); + LOGGER.info(String.format("ASCA-Ignore: Line numbers and obsolete entries updated by problematicLine and saved for file: %s", relativePath)); + } else { + LOGGER.debug(String.format("ASCA-Ignore: No line number or entry changes detected by problematicLine for file: %s", relativePath)); + } + } + + // Helper class for matching problematicLine and line together + private static class VulnerabilityWithLine { + String problematicLine; + int line; + VulnerabilityWithLine(String problematicLine, int line) { + this.problematicLine = problematicLine; + this.line = line; + } + } + + /** + * Removes all ASCA ignore entries and file references for a file when there are no issues in the scan result. + * + * @param filePath The path of the file for which ignore entries should be removed + * @return true if any ignore entries were removed, false otherwise + */ + public void removeIgnoreEntriesForFileIfEmpty(String filePath) { + String relativePath = ignoreFileManager.normalizePath(filePath); + List keysToRemove = new ArrayList<>(); + boolean removed = false; + for (Map.Entry mapEntry : ignoreFileManager.getIgnoreData().entrySet()) { + IgnoreEntry ignoreEntry = mapEntry.getValue(); + if (!"ASCA".equalsIgnoreCase(String.valueOf(ignoreEntry.getType()))) { + continue; + } + // Remove file references for this file + List fileRefs = ignoreEntry.getFiles(); + fileRefs.removeIf(fileRef -> fileRef.getPath().equals(relativePath)); + // If no file references left, mark the key for removal + if (ignoreEntry.getFiles().isEmpty()) { + keysToRemove.add(mapEntry.getKey()); + } + } + // Remove keys from ignore data + for (String keyToRemove : keysToRemove) { + ignoreFileManager.getIgnoreData().remove(keyToRemove); + removed = true; + } + if (removed) { + ignoreFileManager.saveIgnoreDataToDisk(); + LOGGER.info(String.format("ASCA-Ignore: Removed ignore entries for file with no issues: %s", relativePath)); + } + } + } diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/model/Vulnerability.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/model/Vulnerability.java index 8999a79f0..6681e3afa 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/model/Vulnerability.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/model/Vulnerability.java @@ -33,5 +33,6 @@ public Vulnerability() { private String expectedValue; private String title; private String SimilarityId; + private String problematicLine; } diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java index 7e8cf3e99..c6623a129 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java @@ -4,6 +4,8 @@ import com.checkmarx.ast.asca.ScanResult; import com.checkmarx.intellij.common.utils.SeverityLevel; import com.checkmarx.intellij.common.utils.Utils; +import com.checkmarx.intellij.devassist.ignore.IgnoreEntry; +import com.checkmarx.intellij.devassist.ignore.IgnoreFileManager; import com.checkmarx.intellij.devassist.model.Location; import com.checkmarx.intellij.devassist.model.ScanIssue; import com.checkmarx.intellij.devassist.model.Vulnerability; @@ -12,7 +14,10 @@ import com.checkmarx.intellij.devassist.utils.ScanEngine; import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; @@ -27,6 +32,9 @@ public class AscaScanResultAdaptor implements com.checkmarx.intellij.devassist.c private final ScanResult ascaScanResult; private final String filePath; private final List scanIssues; + private String workspaceRootPath = ""; + private final Project project; + /** * Constructs an instance of {@code AscaScanResultAdaptor} with the specified ASCA scan results. @@ -35,9 +43,12 @@ public class AscaScanResultAdaptor implements com.checkmarx.intellij.devassist.c * @param ascaScanResult the ASCA scan results to be wrapped by this adapter * @param filePath the path of the file being scanned (needed for UI display) */ - public AscaScanResultAdaptor(ScanResult ascaScanResult, String filePath) { + public AscaScanResultAdaptor(ScanResult ascaScanResult, String filePath, Project project) { this.ascaScanResult = ascaScanResult; this.filePath = filePath; + this.project = project; + String basePath = project.getBasePath(); + this.workspaceRootPath = basePath; this.scanIssues = buildIssues(); } @@ -80,7 +91,8 @@ private List buildIssues() { if (scanDetails.isEmpty()) { return Collections.emptyList(); } - + IgnoreFileManager ignoreFileManager = IgnoreFileManager.getInstance(project); + List ignoreEntries = ignoreFileManager.getAllIgnoreEntries(); // Group scan details by line number, then sort by severity precedence Map> groupedIssues = scanDetails.stream() .filter(Objects::nonNull) @@ -96,6 +108,7 @@ private List buildIssues() { List issues = groupedIssues.values().stream() .map(this::createScanIssueForGroup) .filter(Objects::nonNull) + //.filter(issue -> !isIgnored(issue, ignoreEntries, filePath)) .collect(Collectors.toList()); LOGGER.debug("ASCA adaptor: Converted " + issues.size() + " grouped scan issues for file: " + filePath); @@ -192,6 +205,7 @@ private Vulnerability createVulnerability(ScanDetail scanDetail, String override vulnerability.setSeverity(mapSeverity(scanDetail.getSeverity())); vulnerability.setRemediationAdvise(scanDetail.getRemediationAdvise()); vulnerability.setTitle(scanDetail.getRuleName()); + vulnerability.setProblematicLine(scanDetail.getProblematicLine()); return vulnerability; } @@ -225,4 +239,52 @@ private String getUniqueId(ScanDetail scanIssue) { } return ScanEngine.ASCA.name(); } + + public boolean isIgnored(ScanIssue issue, List ignoreEntries, String filePath) { + String normalizedPath = normalizePath(filePath); + boolean isAsca = issue.getScanEngine() == ScanEngine.ASCA; + // For ASCA, check problematicLine for all vulnerabilities + if (isAsca && issue.getVulnerabilities() != null && !issue.getVulnerabilities().isEmpty()) { + for (Vulnerability vuln : issue.getVulnerabilities()) { + String issueProblematicLine = vuln.getProblematicLine(); + for (IgnoreEntry entry : ignoreEntries) { + for (IgnoreEntry.FileReference ref : entry.getFiles()) { + boolean pathMatch = ref.isActive() && ref.getPath().equals(normalizedPath); + boolean problematicLineMatch = (issueProblematicLine == null && ref.getProblematicLine() == null) + || (issueProblematicLine != null && issueProblematicLine.equals(ref.getProblematicLine())); + if (pathMatch && problematicLineMatch) { + return true; + } + } + } + } + return false; + } + // Default: match by path and line + int issueLine = issue.getLocations() != null && !issue.getLocations().isEmpty() + ? issue.getLocations().get(0).getLine() + : -1; + for (IgnoreEntry entry : ignoreEntries) { + for (IgnoreEntry.FileReference ref : entry.getFiles()) { + if (ref.isActive() && ref.getPath().equals(normalizedPath) && ref.getLine() == issueLine) { + return true; + } + } + } + return false; + } + + /** + * normalizes the given file path to be relative to the project's workspace root. + * + * @param filePath + * @return + */ + private String normalizePath(String filePath) { + return Path.of(workspaceRootPath) + .relativize(Paths.get(filePath)) + .toString() + .replace("\\", "/"); + } + } diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java index f0046b9f0..67f97f097 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java @@ -7,6 +7,7 @@ import com.checkmarx.intellij.common.wrapper.CxWrapperFactory; import com.checkmarx.intellij.devassist.basescanner.BaseScannerService; import com.checkmarx.intellij.devassist.configuration.ScannerConfig; +import com.checkmarx.intellij.devassist.ignore.IgnoreEntry; import com.checkmarx.intellij.devassist.ignore.IgnoreManager; import com.checkmarx.intellij.devassist.telemetry.TelemetryService; import com.checkmarx.intellij.devassist.utils.DevAssistConstants; @@ -28,6 +29,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; /** * Realtime ASCA scanner service that integrates with the realtime scanner system. @@ -144,9 +147,26 @@ public com.checkmarx.intellij.devassist.common.ScanResult scan(@NotN int issueCount = ascaResult.getScanDetails() != null ? ascaResult.getScanDetails().size() : 0; LOGGER.debug("ASCA scanner: scan completed - " + uri + " (" + issueCount + " issues found)"); - AscaScanResultAdaptor scanResultAdaptor = new AscaScanResultAdaptor(ascaResult, uri); - TelemetryService.logScanResults(scanResultAdaptor, ScanEngine.ASCA); - return scanResultAdaptor; + AscaScanResultAdaptor scanResultAdaptor = new AscaScanResultAdaptor(ascaResult, uri, psiFile.getProject()); + + // Filter out ignored issues based on problematicLine + com.checkmarx.intellij.devassist.ignore.IgnoreFileManager ignoreFileManager = com.checkmarx.intellij.devassist.ignore.IgnoreFileManager.getInstance(psiFile.getProject()); + List ignoreEntries = ignoreFileManager.getAllIgnoreEntries(); + List filteredIssues = new ArrayList<>(); + for (com.checkmarx.intellij.devassist.model.ScanIssue issue : scanResultAdaptor.getIssues()) { + if (!scanResultAdaptor.isIgnored(issue, ignoreEntries, uri)) { + filteredIssues.add(issue); + } + } + // Return a new adaptor with only non-ignored issues + AscaScanResultAdaptor filteredAdaptor = new AscaScanResultAdaptor(ascaResult, uri, psiFile.getProject()) { + @Override + public List getIssues() { + return filteredIssues; + } + }; + TelemetryService.logScanResults(filteredAdaptor, ScanEngine.ASCA); + return filteredAdaptor; } catch (Exception e) { LOGGER.warn("ASCA scanner: scan error for file: " + uri, e); @@ -440,8 +460,10 @@ private void updateIgnoredFileDataOnLatestResult(String tempFilePath, Project pr LOGGER.debug("ASCA: Performing full scan to update line numbers for ignored issues"); ScanResult fullScanResult = scanAscaFile(tempFilePath, ascLatestVersion, agent, ""); if (fullScanResult.getScanDetails() != null && !fullScanResult.getScanDetails().isEmpty()) { - AscaScanResultAdaptor fullScanResultAdaptor = new AscaScanResultAdaptor(fullScanResult, filePath); - ignoreManager.updateLineNumbersForIgnoredEntries(fullScanResultAdaptor, filePath); + AscaScanResultAdaptor fullScanResultAdaptor = new AscaScanResultAdaptor(fullScanResult, filePath, project); + ignoreManager.updateLineNumbersForIgnoredEntriesByProblematicLine(fullScanResultAdaptor, filePath); + }else{ + ignoreManager.removeIgnoreEntriesForFileIfEmpty(filePath); } } } catch (Exception e) { From e884dd10eb4690adc29bdf26bd79f7cb3edd1c96 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Wed, 25 Mar 2026 13:13:29 +0530 Subject: [PATCH 2/2] Resolved review comment --- .../devassist/ignore/IgnoreManager.java | 38 +++++++++++- .../scanners/asca/AscaScanResultAdaptor.java | 60 +------------------ .../scanners/asca/AscaScannerService.java | 16 +++-- 3 files changed, 47 insertions(+), 67 deletions(-) diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java index 4fe7d14b3..27f4ac04a 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/ignore/IgnoreManager.java @@ -772,7 +772,7 @@ public void updateLineNumbersForIgnoredEntriesByProblematicLine(ScanResult fu // Iterate through all ignore entries using normal for-each for (Map.Entry mapEntry : ignoreFileManager.getIgnoreData().entrySet()) { IgnoreEntry ignoreEntry = mapEntry.getValue(); - if (!"ASCA".equalsIgnoreCase(String.valueOf(ignoreEntry.getType()))) { + if (!ScanEngine.ASCA.toString().equalsIgnoreCase(String.valueOf(ignoreEntry.getType()))) { continue; // Only process ASCA entries } // Remove file references that are not present in the scan result @@ -840,7 +840,7 @@ public void removeIgnoreEntriesForFileIfEmpty(String filePath) { boolean removed = false; for (Map.Entry mapEntry : ignoreFileManager.getIgnoreData().entrySet()) { IgnoreEntry ignoreEntry = mapEntry.getValue(); - if (!"ASCA".equalsIgnoreCase(String.valueOf(ignoreEntry.getType()))) { + if (!ScanEngine.ASCA.toString().equalsIgnoreCase(String.valueOf(ignoreEntry.getType()))) { continue; } // Remove file references for this file @@ -862,4 +862,38 @@ public void removeIgnoreEntriesForFileIfEmpty(String filePath) { } } + public boolean isIgnored(ScanIssue issue, List ignoreEntries, String filePath) { + String normalizedPath = ignoreFileManager.normalizePath(filePath); + boolean isAsca = issue.getScanEngine() == ScanEngine.ASCA; + // For ASCA, check problematicLine for all vulnerabilities + if (isAsca && issue.getVulnerabilities() != null && !issue.getVulnerabilities().isEmpty()) { + for (Vulnerability vuln : issue.getVulnerabilities()) { + String issueProblematicLine = vuln.getProblematicLine(); + for (IgnoreEntry entry : ignoreEntries) { + for (IgnoreEntry.FileReference ref : entry.getFiles()) { + boolean pathMatch = ref.isActive() && ref.getPath().equals(normalizedPath); + boolean problematicLineMatch = (issueProblematicLine == null && ref.getProblematicLine() == null) + || (issueProblematicLine != null && issueProblematicLine.equals(ref.getProblematicLine())); + if (pathMatch && problematicLineMatch) { + return true; + } + } + } + } + return false; + } + // Default: match by path and line + int issueLine = issue.getLocations() != null && !issue.getLocations().isEmpty() + ? issue.getLocations().get(0).getLine() + : -1; + for (IgnoreEntry entry : ignoreEntries) { + for (IgnoreEntry.FileReference ref : entry.getFiles()) { + if (ref.isActive() && ref.getPath().equals(normalizedPath) && ref.getLine() == issueLine) { + return true; + } + } + } + return false; + } + } diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java index c6623a129..631cf9dd2 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScanResultAdaptor.java @@ -4,8 +4,6 @@ import com.checkmarx.ast.asca.ScanResult; import com.checkmarx.intellij.common.utils.SeverityLevel; import com.checkmarx.intellij.common.utils.Utils; -import com.checkmarx.intellij.devassist.ignore.IgnoreEntry; -import com.checkmarx.intellij.devassist.ignore.IgnoreFileManager; import com.checkmarx.intellij.devassist.model.Location; import com.checkmarx.intellij.devassist.model.ScanIssue; import com.checkmarx.intellij.devassist.model.Vulnerability; @@ -14,10 +12,7 @@ import com.checkmarx.intellij.devassist.utils.ScanEngine; import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NotNull; -import com.intellij.openapi.project.Project; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; @@ -32,8 +27,6 @@ public class AscaScanResultAdaptor implements com.checkmarx.intellij.devassist.c private final ScanResult ascaScanResult; private final String filePath; private final List scanIssues; - private String workspaceRootPath = ""; - private final Project project; /** @@ -43,12 +36,9 @@ public class AscaScanResultAdaptor implements com.checkmarx.intellij.devassist.c * @param ascaScanResult the ASCA scan results to be wrapped by this adapter * @param filePath the path of the file being scanned (needed for UI display) */ - public AscaScanResultAdaptor(ScanResult ascaScanResult, String filePath, Project project) { + public AscaScanResultAdaptor(ScanResult ascaScanResult, String filePath) { this.ascaScanResult = ascaScanResult; this.filePath = filePath; - this.project = project; - String basePath = project.getBasePath(); - this.workspaceRootPath = basePath; this.scanIssues = buildIssues(); } @@ -91,8 +81,6 @@ private List buildIssues() { if (scanDetails.isEmpty()) { return Collections.emptyList(); } - IgnoreFileManager ignoreFileManager = IgnoreFileManager.getInstance(project); - List ignoreEntries = ignoreFileManager.getAllIgnoreEntries(); // Group scan details by line number, then sort by severity precedence Map> groupedIssues = scanDetails.stream() .filter(Objects::nonNull) @@ -108,7 +96,6 @@ private List buildIssues() { List issues = groupedIssues.values().stream() .map(this::createScanIssueForGroup) .filter(Objects::nonNull) - //.filter(issue -> !isIgnored(issue, ignoreEntries, filePath)) .collect(Collectors.toList()); LOGGER.debug("ASCA adaptor: Converted " + issues.size() + " grouped scan issues for file: " + filePath); @@ -240,51 +227,6 @@ private String getUniqueId(ScanDetail scanIssue) { return ScanEngine.ASCA.name(); } - public boolean isIgnored(ScanIssue issue, List ignoreEntries, String filePath) { - String normalizedPath = normalizePath(filePath); - boolean isAsca = issue.getScanEngine() == ScanEngine.ASCA; - // For ASCA, check problematicLine for all vulnerabilities - if (isAsca && issue.getVulnerabilities() != null && !issue.getVulnerabilities().isEmpty()) { - for (Vulnerability vuln : issue.getVulnerabilities()) { - String issueProblematicLine = vuln.getProblematicLine(); - for (IgnoreEntry entry : ignoreEntries) { - for (IgnoreEntry.FileReference ref : entry.getFiles()) { - boolean pathMatch = ref.isActive() && ref.getPath().equals(normalizedPath); - boolean problematicLineMatch = (issueProblematicLine == null && ref.getProblematicLine() == null) - || (issueProblematicLine != null && issueProblematicLine.equals(ref.getProblematicLine())); - if (pathMatch && problematicLineMatch) { - return true; - } - } - } - } - return false; - } - // Default: match by path and line - int issueLine = issue.getLocations() != null && !issue.getLocations().isEmpty() - ? issue.getLocations().get(0).getLine() - : -1; - for (IgnoreEntry entry : ignoreEntries) { - for (IgnoreEntry.FileReference ref : entry.getFiles()) { - if (ref.isActive() && ref.getPath().equals(normalizedPath) && ref.getLine() == issueLine) { - return true; - } - } - } - return false; - } - /** - * normalizes the given file path to be relative to the project's workspace root. - * - * @param filePath - * @return - */ - private String normalizePath(String filePath) { - return Path.of(workspaceRootPath) - .relativize(Paths.get(filePath)) - .toString() - .replace("\\", "/"); - } } diff --git a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java index 67f97f097..f54fbfe2a 100644 --- a/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java +++ b/devassist-lib/src/main/java/com/checkmarx/intellij/devassist/scanners/asca/AscaScannerService.java @@ -8,6 +8,7 @@ import com.checkmarx.intellij.devassist.basescanner.BaseScannerService; import com.checkmarx.intellij.devassist.configuration.ScannerConfig; import com.checkmarx.intellij.devassist.ignore.IgnoreEntry; +import com.checkmarx.intellij.devassist.ignore.IgnoreFileManager; import com.checkmarx.intellij.devassist.ignore.IgnoreManager; import com.checkmarx.intellij.devassist.telemetry.TelemetryService; import com.checkmarx.intellij.devassist.utils.DevAssistConstants; @@ -39,6 +40,7 @@ public class AscaScannerService extends BaseScannerService { private static final Logger LOGGER = Utils.getLogger(AscaScannerService.class); private static final String ASCA_DIR = "CxASCA"; + private static final Object SCAN_LOCK = new Object(); /** * Creates an ASCA scanner service with the default ASCA realtime configuration. @@ -147,19 +149,20 @@ public com.checkmarx.intellij.devassist.common.ScanResult scan(@NotN int issueCount = ascaResult.getScanDetails() != null ? ascaResult.getScanDetails().size() : 0; LOGGER.debug("ASCA scanner: scan completed - " + uri + " (" + issueCount + " issues found)"); - AscaScanResultAdaptor scanResultAdaptor = new AscaScanResultAdaptor(ascaResult, uri, psiFile.getProject()); + AscaScanResultAdaptor scanResultAdaptor = new AscaScanResultAdaptor(ascaResult, uri); // Filter out ignored issues based on problematicLine - com.checkmarx.intellij.devassist.ignore.IgnoreFileManager ignoreFileManager = com.checkmarx.intellij.devassist.ignore.IgnoreFileManager.getInstance(psiFile.getProject()); + IgnoreManager ignoreManager = new IgnoreManager(psiFile.getProject()); + IgnoreFileManager ignoreFileManager = IgnoreFileManager.getInstance(psiFile.getProject()); List ignoreEntries = ignoreFileManager.getAllIgnoreEntries(); List filteredIssues = new ArrayList<>(); for (com.checkmarx.intellij.devassist.model.ScanIssue issue : scanResultAdaptor.getIssues()) { - if (!scanResultAdaptor.isIgnored(issue, ignoreEntries, uri)) { + if (!ignoreManager.isIgnored(issue, ignoreEntries, uri)) { filteredIssues.add(issue); } } // Return a new adaptor with only non-ignored issues - AscaScanResultAdaptor filteredAdaptor = new AscaScanResultAdaptor(ascaResult, uri, psiFile.getProject()) { + AscaScanResultAdaptor filteredAdaptor = new AscaScanResultAdaptor(ascaResult, uri) { @Override public List getIssues() { return filteredIssues; @@ -201,12 +204,12 @@ private ScanResult runAscaScan(PsiFile file, Project project, boolean ascLatestV return null; } + synchronized (SCAN_LOCK) { String tempFilePath = saveTempFile(file.getName(), fileContent); if (tempFilePath == null) { LOGGER.warn("Failed to create temporary file for ASCA scan."); return null; } - try { LOGGER.info(Strings.join("Starting ASCA scan on file: ", virtualFile.getPath())); ScanResult scanResult = scanAscaFile(tempFilePath, ascLatestVersion, agent, DevAssistUtils.getIgnoreFilePath(project)); @@ -220,6 +223,7 @@ private ScanResult runAscaScan(PsiFile file, Project project, boolean ascLatestV } finally { deleteFile(tempFilePath); } + } } /** @@ -460,7 +464,7 @@ private void updateIgnoredFileDataOnLatestResult(String tempFilePath, Project pr LOGGER.debug("ASCA: Performing full scan to update line numbers for ignored issues"); ScanResult fullScanResult = scanAscaFile(tempFilePath, ascLatestVersion, agent, ""); if (fullScanResult.getScanDetails() != null && !fullScanResult.getScanDetails().isEmpty()) { - AscaScanResultAdaptor fullScanResultAdaptor = new AscaScanResultAdaptor(fullScanResult, filePath, project); + AscaScanResultAdaptor fullScanResultAdaptor = new AscaScanResultAdaptor(fullScanResult, filePath); ignoreManager.updateLineNumbersForIgnoredEntriesByProblematicLine(fullScanResultAdaptor, filePath); }else{ ignoreManager.removeIgnoreEntriesForFileIfEmpty(filePath);