-
Notifications
You must be signed in to change notification settings - Fork 3
re-use vulnerability type/detector instances to avoid unnecessary mem usage #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a6219c2
283582f
10a3e96
bedc44b
8a70bb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,7 +44,7 @@ public static void report(String hostname, InetAddress[] inetAddresses) { | |
| } | ||
| logger.debug("Hostname: %s, Port: %s, IPs: %s", hostnameEntry.getHostname(), hostnameEntry.getPort(), ipAddresses); | ||
|
|
||
| Attack attack = new SSRFDetector().run( | ||
| Attack attack = SSRFDetector.run( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replacing instance call with static 'SSRFDetector.run' may introduce shared mutable state access and race conditions if run uses non-thread-safe state. Details✨ AI Reasoning 🔧 How do I fix it? More info - Comment |
||
| hostname, hostnameEntry.getPort(), ipAddresses, OPERATION_NAME | ||
| ); | ||
| if (attack == null) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,18 +31,17 @@ public static void report(Object filePath, String operation, int depth) { | |
| logger.trace("Scan on %s for file: %s", operation, filePath); | ||
| StatisticsStore.registerCall(operation, OperationKind.FS_OP); | ||
|
|
||
| Vulnerabilities.Vulnerability vulnerability = new Vulnerabilities.PathTraversalVulnerability(); | ||
| if (filePath instanceof String filePathString) { | ||
| Scanner.scanForGivenVulnerability(vulnerability, operation, new String[]{filePathString}); | ||
| Scanner.scanForGivenVulnerability(Vulnerabilities.PATH_TRAVERSAL, operation, new String[]{filePathString}); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reusing shared Vulnerabilities.PATH_TRAVERSAL may introduce data races if Vulnerability instances are mutable or used concurrently. Details✨ AI Reasoning 🔧 How do I fix it? More info - Comment |
||
| } else if (filePath instanceof URI filePathURI) { | ||
| // File(...) Constructor also accepts URI objects, but path remains the same | ||
| // So we just extract the path here : (i.e. new File("file:///../test.txt") --> "/../test.txt") | ||
| String filePathString = filePathURI.getPath(); | ||
| Scanner.scanForGivenVulnerability(vulnerability, operation, new String[]{filePathString}); | ||
| Scanner.scanForGivenVulnerability(Vulnerabilities.PATH_TRAVERSAL, operation, new String[]{filePathString}); | ||
| } else if (filePath instanceof Path filePathAsPath) { | ||
| // Some functions on Path also accept other paths | ||
| String filePathString = filePathAsPath.toString(); | ||
| Scanner.scanForGivenVulnerability(vulnerability, operation, new String[]{filePathString}); | ||
| Scanner.scanForGivenVulnerability(Vulnerabilities.PATH_TRAVERSAL, operation, new String[]{filePathString}); | ||
| } else if (filePath instanceof Object[] filePaths) { | ||
| // In Paths.get() sometimes you can have multiple paths provided, scan them individually : | ||
| if (depth >= MAX_RECURSION_DEPTH) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,6 @@ public static void report(String sql, String dialect, String operation) { | |
| StatisticsStore.registerCall(operation, OperationKind.SQL_OP); | ||
|
|
||
| // scan | ||
| Vulnerabilities.Vulnerability vulnerability = new Vulnerabilities.SQLInjectionVulnerability(); | ||
| Scanner.scanForGivenVulnerability(vulnerability, operation, new String[]{sql, dialect}); | ||
| Scanner.scanForGivenVulnerability(Vulnerabilities.SQL_INJECTION, operation, new String[]{sql, dialect}); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reusing a shared Vulnerabilities.SQL_INJECTION instance may introduce thread-safety issues if the vulnerability object is mutable or mutated during scanning. Details✨ AI Reasoning 🔧 How do I fix it? More info - Comment |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,56 +3,65 @@ | |
| import dev.aikido.agent_api.vulnerabilities.path_traversal.PathTraversalDetector; | ||
| import dev.aikido.agent_api.vulnerabilities.shell_injection.ShellInjectionDetector; | ||
| import dev.aikido.agent_api.vulnerabilities.sql_injection.SqlDetector; | ||
| import dev.aikido.agent_api.vulnerabilities.ssrf.SSRFDetector; | ||
|
|
||
| public final class Vulnerabilities { | ||
| private Vulnerabilities() {} | ||
| public interface Vulnerability { | ||
| Detector getDetector(); | ||
| String getKind(); | ||
| } | ||
| public static final class SQLInjectionVulnerability implements Vulnerability { | ||
|
|
||
| private static final class SQLInjectionVulnerability implements Vulnerability { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switched from creating new Detector instances to using shared INSTANCE singletons, which may expose non-thread-safe Detector state to concurrent threads. Details✨ AI Reasoning 🔧 How do I fix it? More info - Comment |
||
| @Override | ||
| public Detector getDetector() { | ||
| return new SqlDetector(); | ||
| return SqlDetector.INSTANCE; | ||
| } | ||
| @Override | ||
| public String getKind() { | ||
| return "sql_injection"; | ||
| } | ||
| } | ||
| public static final class PathTraversalVulnerability implements Vulnerability { | ||
| public static final Vulnerability SQL_INJECTION = new SQLInjectionVulnerability(); | ||
|
|
||
| private static final class PathTraversalVulnerability implements Vulnerability { | ||
| @Override | ||
| public Detector getDetector() { | ||
| return new PathTraversalDetector(); | ||
| return PathTraversalDetector.INSTANCE; | ||
| } | ||
| @Override | ||
| public String getKind() { | ||
| return "path_traversal"; | ||
| } | ||
| } | ||
| public static final class SSRFVulnerability implements Vulnerability { | ||
| public static final Vulnerability PATH_TRAVERSAL = new PathTraversalVulnerability(); | ||
|
|
||
| private static final class SSRFVulnerability implements Vulnerability { | ||
| @Override | ||
| public Detector getDetector() { return null; } | ||
| @Override | ||
| public String getKind() { | ||
| return "ssrf"; | ||
| } | ||
| } | ||
| public static final class StoredSSRFVulnerability implements Vulnerability { | ||
| public static final Vulnerability SSRF = new SSRFVulnerability(); | ||
|
|
||
| private static final class StoredSSRFVulnerability implements Vulnerability { | ||
| @Override | ||
| public Detector getDetector() { return null; } | ||
| @Override | ||
| public String getKind() { | ||
| return "stored_ssrf"; | ||
| } | ||
| } | ||
| public static final class ShellInjectionVulnerability implements Vulnerability { | ||
| public static final Vulnerability STORED_SSRF = new StoredSSRFVulnerability(); | ||
|
|
||
| private static final class ShellInjectionVulnerability implements Vulnerability { | ||
| @Override | ||
| public Detector getDetector() { return new ShellInjectionDetector(); } | ||
| public Detector getDetector() { return ShellInjectionDetector.INSTANCE; } | ||
| @Override | ||
| public String getKind() { | ||
| return "shell_injection"; | ||
| } | ||
| } | ||
| public static final Vulnerability SHELL_INJECTION = new ShellInjectionVulnerability(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,9 @@ | |
| import java.util.regex.Pattern; | ||
|
|
||
| public class SqlDetector implements Detector { | ||
| public static final SqlDetector INSTANCE = new SqlDetector(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Declaring INSTANCE before the static logger risks static initialization-order problems if the instance uses the logger during construction. Details✨ AI Reasoning 🔧 How do I fix it? More info - Comment |
||
| private static final Logger logger = LogManager.getLogger(SqlDetector.class); | ||
|
|
||
| /** | ||
| * @param userInput contains the user input which we want to scan | ||
| * @param arguments contains: [query, dialect] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,22 +3,18 @@ | |
| import dev.aikido.agent_api.context.Context; | ||
| import dev.aikido.agent_api.context.ContextObject; | ||
| import dev.aikido.agent_api.vulnerabilities.Attack; | ||
| import dev.aikido.agent_api.vulnerabilities.Detector; | ||
| import dev.aikido.agent_api.vulnerabilities.Vulnerabilities; | ||
|
|
||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| import static dev.aikido.agent_api.helpers.ShouldBlockHelper.shouldBlock; | ||
| import static dev.aikido.agent_api.helpers.StackTrace.getCurrentStackTrace; | ||
| import static dev.aikido.agent_api.vulnerabilities.ssrf.FindHostnameInContext.findHostnameInContext; | ||
| import static dev.aikido.agent_api.vulnerabilities.ssrf.IsPrivateIP.containsPrivateIP; | ||
| import static dev.aikido.agent_api.vulnerabilities.ssrf.PrivateIPRedirectFinder.isRedirectToPrivateIP; | ||
| import static dev.aikido.agent_api.vulnerabilities.ssrf.imds.Resolver.resolvesToImdsIp; | ||
|
|
||
| public class SSRFDetector { | ||
| public Attack run(String hostname, int port, List<String> ipAddresses, String operation) { | ||
| public final class SSRFDetector { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changing SSRFDetector to final and making run(...) static breaks the previous public API (instance method -> static). Details🔧 How do I fix it? More info - Comment |
||
| public static Attack run(String hostname, int port, List<String> ipAddresses, String operation) { | ||
| if(hostname == null || hostname.isEmpty()) { | ||
| return null; | ||
| } | ||
|
|
@@ -39,7 +35,7 @@ public Attack run(String hostname, int port, List<String> ipAddresses, String op | |
| if(attackFindings != null) { | ||
| return new Attack( | ||
| operation, | ||
| new Vulnerabilities.SSRFVulnerability(), | ||
| Vulnerabilities.SSRF, | ||
| attackFindings.source(), | ||
| attackFindings.pathToPayload(), | ||
| /*metadata*/ Map.of( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,7 @@ public Attack run(String hostname, List<String> ipAddresses, String operation) { | |
|
|
||
| return new Attack( | ||
| operation, | ||
| new Vulnerabilities.StoredSSRFVulnerability(), | ||
| Vulnerabilities.STORED_SSRF, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replacing a per-call Vulnerability object with a shared Vulnerabilities.STORED_SSRF instance may introduce unsafe shared mutable state access across threads. Details✨ AI Reasoning 🔧 How do I fix it? More info - Comment |
||
| null, // source is null for stored attacks | ||
| "", // path is empty | ||
| Map.of( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.