Skip to content

Commit 9768011

Browse files
author
wuerror
committed
fix: resolve ConcurrentModificationException in SecretScanner and enable Phase 8.1 in API mode
1 parent 6711134 commit 9768011

2 files changed

Lines changed: 27 additions & 15 deletions

File tree

src/main/java/com/jbytescanner/JByteScanner.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,11 @@ public Integer call() throws Exception {
125125
} else {
126126
System.out.println("Phase 2 Skipped. Using existing api.txt for project: " + projectName);
127127
}
128-
129-
if (isApiMode) {
130-
System.out.println("Mode 'api' finished. Exiting.");
131-
return 0;
132-
}
133128

134-
// Phase 2.5: Secret Scanner
135-
// Ensure Soot is initialized if Discovery was skipped
136-
if (apiFile.exists() && !forceDiscovery) {
129+
// Phase 2.5: Secret Scanner (Execute in BOTH api and scan modes)
130+
// Ensure Soot is initialized if Discovery was skipped (e.g. in 'scan' mode with existing api.txt)
131+
// Note: In 'api' mode, DiscoveryEngine.run() already initializes Soot.
132+
if (isScanMode && apiFile.exists() && !forceDiscovery) {
137133
List<String> combinedLibs = new java.util.ArrayList<>(loadedJars.libJars);
138134
if (loadedJars.depAppJars != null) combinedLibs.addAll(loadedJars.depAppJars);
139135
com.jbytescanner.core.SootManager.initSoot(loadedJars.targetAppJars, combinedLibs, false);
@@ -146,6 +142,11 @@ public Integer call() throws Exception {
146142
secretScanner.writeReport(workspaceDir, findings);
147143
System.out.println("Secret Scan Complete. Findings: " + findings.size());
148144

145+
if (isApiMode) {
146+
System.out.println("Mode 'api' finished. Exiting.");
147+
return 0;
148+
}
149+
149150
System.out.println("------------------------------------------");
150151

151152
// 4. Phase 3: Taint Analysis

src/main/java/com/jbytescanner/secret/SecretScanner.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,16 @@ private List<SecretFinding> scanFile(File file) {
111111
private List<SecretFinding> scanConstantPool() {
112112
List<SecretFinding> findings = new ArrayList<>();
113113

114-
for (SootClass sc : Scene.v().getApplicationClasses()) {
114+
// Use a snapshot of classes to avoid ConcurrentModificationException if Soot modifies the chain
115+
List<SootClass> snapshot = new ArrayList<>(Scene.v().getApplicationClasses());
116+
117+
for (SootClass sc : snapshot) {
115118
if (sc.isPhantom()) continue;
116119

117-
for (SootMethod sm : sc.getMethods()) {
120+
// Use a snapshot of methods as well, just in case
121+
List<SootMethod> methodSnapshot = new ArrayList<>(sc.getMethods());
122+
123+
for (SootMethod sm : methodSnapshot) {
118124
if (!sm.hasActiveBody()) {
119125
try {
120126
sm.retrieveActiveBody();
@@ -123,13 +129,18 @@ private List<SecretFinding> scanConstantPool() {
123129
}
124130
}
125131

126-
for (Unit u : sm.getActiveBody().getUnits()) {
127-
for (ValueBox vb : u.getUseBoxes()) {
128-
if (vb.getValue() instanceof StringConstant) {
129-
String value = ((StringConstant) vb.getValue()).value;
130-
checkStringSecret(value, sc.getName() + "." + sm.getName(), findings, u);
132+
// Check units safely
133+
try {
134+
for (Unit u : sm.getActiveBody().getUnits()) {
135+
for (ValueBox vb : u.getUseBoxes()) {
136+
if (vb.getValue() instanceof StringConstant) {
137+
String value = ((StringConstant) vb.getValue()).value;
138+
checkStringSecret(value, sc.getName() + "." + sm.getName(), findings, u);
139+
}
131140
}
132141
}
142+
} catch (Exception e) {
143+
// Ignore errors during unit iteration (e.g. body modification)
133144
}
134145
}
135146
}

0 commit comments

Comments
 (0)