From 2d4e2cd4402dc3d412b142f263043181fb186e1f Mon Sep 17 00:00:00 2001 From: Saurav Bhattacharya Date: Sat, 14 Mar 2026 17:55:02 -0700 Subject: [PATCH] fix: add path validation to DotExporter/AnnotationManager + remove dead asCollection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Security (CWE-22): - DotExporter.export(): now calls ExportUtils.validateOutputPath() before writing, matching CsvReportExporter/GraphMLExporter/ InteractiveHtmlExporter which already had this guard. - GraphAnnotationManager.exportToFile(): same path validation added. - GraphAnnotationManager.importFromFile(): same validation to prevent reading files outside allowed directories. Code cleanup: - IndependentSetAnalyzer: removed dead no-op asCollection() method (identity function: takes Collection, returns same Collection). Inlined all 8 call sites — graph.getVertices() already returns Collection, wrapper served no purpose. --- Gvisual/src/gvisual/DotExporter.java | 2 ++ .../src/gvisual/GraphAnnotationManager.java | 8 ++++++-- .../src/gvisual/IndependentSetAnalyzer.java | 18 +++++++++--------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Gvisual/src/gvisual/DotExporter.java b/Gvisual/src/gvisual/DotExporter.java index 37afc25..82a5f4a 100644 --- a/Gvisual/src/gvisual/DotExporter.java +++ b/Gvisual/src/gvisual/DotExporter.java @@ -118,8 +118,10 @@ public void setTypeColor(String edgeType, String hexColor) { * * @param outputFile the file to write to * @throws IOException if writing fails + * @throws SecurityException if the path escapes allowed directories (CWE-22) */ public void export(File outputFile) throws IOException { + ExportUtils.validateOutputPath(outputFile); try (Writer writer = new OutputStreamWriter( new FileOutputStream(outputFile), StandardCharsets.UTF_8)) { writer.write(exportToString()); diff --git a/Gvisual/src/gvisual/GraphAnnotationManager.java b/Gvisual/src/gvisual/GraphAnnotationManager.java index 657e201..e9a3611 100644 --- a/Gvisual/src/gvisual/GraphAnnotationManager.java +++ b/Gvisual/src/gvisual/GraphAnnotationManager.java @@ -495,7 +495,9 @@ else if (line.startsWith("\"tags\"")) { * Export annotations to a file. */ public void exportToFile(String filePath) throws IOException { - try (Writer w = new FileWriter(filePath)) { + java.io.File file = new java.io.File(filePath); + ExportUtils.validateOutputPath(file); + try (Writer w = new FileWriter(file)) { w.write(exportToJson()); } } @@ -504,8 +506,10 @@ public void exportToFile(String filePath) throws IOException { * Import annotations from a file. */ public int importFromFile(String filePath) throws IOException { + java.io.File file = new java.io.File(filePath); + ExportUtils.validateOutputPath(file); StringBuilder sb = new StringBuilder(); - try (BufferedReader r = new BufferedReader(new FileReader(filePath))) { + try (BufferedReader r = new BufferedReader(new FileReader(file))) { String line; while ((line = r.readLine()) != null) { sb.append(line).append("\n"); diff --git a/Gvisual/src/gvisual/IndependentSetAnalyzer.java b/Gvisual/src/gvisual/IndependentSetAnalyzer.java index 92ae0d8..65b2072 100644 --- a/Gvisual/src/gvisual/IndependentSetAnalyzer.java +++ b/Gvisual/src/gvisual/IndependentSetAnalyzer.java @@ -104,7 +104,7 @@ public boolean isMaximalIndependentSet(Set vertices) { */ public Set greedyIndependentSet() { Set result = new LinkedHashSet<>(); - Set remaining = new HashSet<>(asCollection(graph.getVertices())); + Set remaining = new HashSet<>(graph.getVertices()); Map> adjMap = GraphUtils.buildAdjacencyMap(graph, remaining); while (!remaining.isEmpty()) { @@ -141,7 +141,7 @@ public Set greedyIndependentSet() { */ public Set greedyMaxDegreeIndependentSet() { Set result = new LinkedHashSet<>(); - Set remaining = new HashSet<>(asCollection(graph.getVertices())); + Set remaining = new HashSet<>(graph.getVertices()); Map> adjMap = GraphUtils.buildAdjacencyMap(graph, remaining); while (!remaining.isEmpty()) { @@ -168,7 +168,7 @@ public Set greedyMaxDegreeIndependentSet() { } // Better implementation: standard vertex removal approach - remaining = new HashSet<>(asCollection(graph.getVertices())); + remaining = new HashSet<>(graph.getVertices()); while (!remaining.isEmpty()) { // Find max-degree vertex in remaining String maxV = null; @@ -218,7 +218,7 @@ public Set exactMaximumIndependentSet(int maxVertices) { } if (n == 0) return Collections.emptySet(); - List vertices = new ArrayList<>(asCollection(graph.getVertices())); + List vertices = new ArrayList<>(graph.getVertices()); Collections.sort(vertices); Map> adjMap = GraphUtils.buildAdjacencyMap(graph, new HashSet<>(vertices)); @@ -286,7 +286,7 @@ public List> allMaximalIndependentSets() { * @return list of maximal independent sets */ public List> allMaximalIndependentSets(int maxCount) { - List vertices = new ArrayList<>(asCollection(graph.getVertices())); + List vertices = new ArrayList<>(graph.getVertices()); Collections.sort(vertices); Map> adjMap = GraphUtils.buildAdjacencyMap(graph, new HashSet<>(vertices)); @@ -387,7 +387,7 @@ public KernelResult(Set forced, Set kernel, */ public KernelResult kernelReduction() { Set forced = new LinkedHashSet<>(); - Set remaining = new LinkedHashSet<>(asCollection(graph.getVertices())); + Set remaining = new LinkedHashSet<>(graph.getVertices()); Map> adj = GraphUtils.buildAdjacencyMap(graph, remaining); List log = new ArrayList<>(); int rules = 0; @@ -570,7 +570,7 @@ public int[] independencePolynomial() { "Independence polynomial computation limited to 20 vertices, graph has " + n); } - List vertices = new ArrayList<>(asCollection(graph.getVertices())); + List vertices = new ArrayList<>(graph.getVertices()); Collections.sort(vertices); Map> adj = GraphUtils.buildAdjacencyMap(graph, new HashSet<>(vertices)); @@ -617,7 +617,7 @@ public Set maximumCliqueViaComplement() { private Graph buildComplement() { Graph comp = new UndirectedSparseGraph<>(); - List vertices = new ArrayList<>(asCollection(graph.getVertices())); + List vertices = new ArrayList<>(graph.getVertices()); for (String v : vertices) comp.addVertex(v); int edgeId = 0; for (int i = 0; i < vertices.size(); i++) { @@ -723,7 +723,7 @@ public IndependentSetReport fullReport() { @SuppressWarnings("unchecked") - private Collection asCollection(Collection c) { + private Collection Collection c { return c; } }