Skip to content

Commit 68b9ceb

Browse files
authored
Merge pull request #17 from hangga/custom-scanner
Custom scanner
2 parents c90c413 + 9d065fb commit 68b9ceb

File tree

7 files changed

+140
-17
lines changed

7 files changed

+140
-17
lines changed

README.md

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ alt="Delvelin Scan Demo" width="260">
2525
+ [Usage on Android](#usage-on-android)
2626
+ [Alternative Examples](#alternative-examples)
2727
+ [Configuration Options](#configuration-options)
28+
+ [Usage with Custom Detector](#usage-with-custom-detector)
2829
- 4.[License](#4-license)
2930
- 5.[Contributing](#5-contributing)
3031
---
@@ -80,14 +81,14 @@ Add the plugin to your Gradle project.
8081
### KTS
8182
```kotlin
8283
plugins {
83-
id("io.github.hangga.delvelin") version "0.1.2-beta"
84+
id("io.github.hangga.delvelin") version "0.2.0-beta"
8485
}
8586
```
8687

8788
### Groovy
8889
```groovy
8990
plugins {
90-
id 'io.github.hangga.delvelin' version '0.1.2-beta'
91+
id 'io.github.hangga.delvelin' version '0.2.0-beta'
9192
}
9293
```
9394

@@ -153,7 +154,7 @@ repositories {
153154
}
154155

155156
dependencies {
156-
testImplementation('io.github.hangga:delvelin-plugin:0.1.2-beta')
157+
testImplementation('io.github.hangga:delvelin-plugin:0.2.0-beta')
157158
}
158159
```
159160

@@ -169,7 +170,7 @@ dependencies {
169170
<dependency>
170171
<groupId>io.github.hangga</groupId>
171172
<artifactId>delvelin-plugin</artifactId>
172-
<version>0.1.2-beta</version>
173+
<version>0.2.0-beta</version>
173174
<scope>test</scope>
174175
</dependency>
175176
```
@@ -236,21 +237,83 @@ fun `vulnerability test with save dialog`() {
236237

237238
### Configuration Options
238239

239-
| Configuration Option | Description | Default Value |
240-
|------------------------------------------|----------------------------------------------------------------------------------------------|---------------|
241-
| `setOutputFormat(OutputFileFormat format)` | Set the output format of the analysis (e.g., `HTML`, `JSON`, or `LOG`). | `LOG` |
242-
| `setAllowedExtensions(String... values)` | Specify file extensions to include in the analysis. By default, allows `.java`, `.kt`, `.gradle`, `.kts`, and `.xml`. | `[".java", ".kt", ".gradle", ".kts", ".xml"]` |
243-
| `setAutoLaunchBrowser(boolean value)` | Automatically open the generated HTML report in the browser. Set to `false` to disable. | `false` |
244-
| `setShowSaveDialog(boolean value)` | Display a save dialog for HTML and JSON reports. Set to `false` to disable. | `false` |
245-
| `setLogListener(LogListener listener)` | Set a custom listener for capturing logs during analysis (useful for Android integration). | `null` |
246-
240+
| Configuration Option | Description | Default Value |
241+
|----------------------------------------------|----------------------------------------------------------------------------------------------|---------------|
242+
| `setOutputFormat(OutputFileFormat format)` | Set the output format of the analysis (e.g., `HTML`, `JSON`, or `LOG`). | `LOG` |
243+
| `setAllowedExtensions(String... values)` | Specify file extensions to include in the analysis. By default, allows `.java`, `.kt`, `.gradle`, `.kts`, and `.xml`. | `[".java", ".kt", ".gradle", ".kts", ".xml"]` |
244+
| `setAutoLaunchBrowser(boolean value)` | Automatically open the generated HTML report in the browser. Set to `false` to disable. | `false` |
245+
| `setShowSaveDialog(boolean value)` | Display a save dialog for HTML and JSON reports. Set to `false` to disable. | `false` |
246+
| `setLogListener(LogListener listener)` | Set a custom listener for capturing logs during analysis (useful for Android integration). | `null` |
247+
| `addCustomDetector(BaseDetector detector)` | Add your own custom detector to identify specific patterns or vulnerabilities in the code. | `null` |
247248

248249
> **Important Notes**
249250
> If you choose the JSON or HTML output format, you **must** use either `setAutoLaunchBrowser` or
250251
> `setShowSaveDialog`. These methods ensure that the output is handled properly.
251252
252253
### <a href="https://github.com/delvelin/example-kotlin">See Example Project >></a>
253254

255+
Sure! Here is the additional README documentation for using `Delvelin` with a custom detector `ExampleCustomDetector`:
256+
257+
### Usage with Custom Detector
258+
259+
Below is an example of how to use Delvelin with a custom detector `ExampleCustomDetector`.
260+
261+
#### Step-by-step
262+
263+
1. Create a custom detector class like `ExampleCustomDetector`.
264+
2. Add detection implementation in the `detect(line: String, lineNumber: Int)` and `detect(content: String)` methods.
265+
3. Create a test function that sets the output format, adds the custom detector, and runs the scan.
266+
267+
#### Example Custom Detector
268+
269+
The following custom detector detects a specific pattern in the code. It checks each line of code and the entire content to find the pattern called `examplePattern`.
270+
271+
```kotlin
272+
class ExampleCustomDetector : BaseDetector() {
273+
274+
init {
275+
this.vulnerabilities = Vulnerabilities.UNSAFE_REFLECTION
276+
}
277+
278+
override fun detect(line: String, lineNumber: Int) {
279+
// Implementation of line-based detection
280+
if (line.contains("examplePattern")) {
281+
val specificLocation = specificLocation(lineNumber)
282+
setValidVulnerability(
283+
specificLocation,
284+
"Example finding",
285+
"Detected example pattern in the code"
286+
)
287+
}
288+
}
289+
290+
override fun detect(content: String) {
291+
// Implementation of full content-based detection
292+
if (content.contains("examplePattern")) {
293+
val specificLocation = specificLocation(-1) // -1 to denote whole content
294+
setValidVulnerability(
295+
specificLocation,
296+
"Example finding",
297+
"Detected example pattern in the full content"
298+
)
299+
}
300+
}
301+
}
302+
```
303+
304+
#### Using Custom Detector in Tests
305+
306+
Here is an example test that uses `ExampleCustomDetector` with Delvelin. This test sets the output format to HTML and adds the custom detector before running the scan.
307+
308+
```kotlin
309+
@Test
310+
fun `test using your own custom detector`() {
311+
Delvelin().setOutputFormat(OutputFileFormat.HTML)
312+
.addCustomDetector(ExampleCustomDetector())
313+
.scan()
314+
}
315+
```
316+
254317
# 4. License
255318
This project is licensed under [MIT License](LICENSE).
256319

src/main/java/io/github/hangga/delvelin/Delvelin.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.Objects;
99
import java.util.stream.Stream;
1010

11+
import io.github.hangga.delvelin.cwedetectors.BaseDetector;
1112
import io.github.hangga.delvelin.cwedetectors.GeneralScanner;
1213
import io.github.hangga.delvelin.properties.Config;
1314
import io.github.hangga.delvelin.properties.OutputFileFormat;
@@ -32,6 +33,11 @@ public Delvelin setOutputFormat(OutputFileFormat format) {
3233
return this;
3334
}
3435

36+
public Delvelin addCustomDetector(BaseDetector detector){
37+
generalScanner.addDetector(detector);
38+
return this;
39+
}
40+
3541
public Delvelin() {
3642
}
3743

src/main/java/io/github/hangga/delvelin/cwedetectors/BaseDetector.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,4 @@ public void setValidVulnerability(String specificLocation, String finding, Strin
4949
Reports.addToReport(vulnerabilities.getCweCode(), finding, vulnerabilities.getDescription(), specificLocation,
5050
message, vulnerabilities.getPriority(), className, extName);
5151
}
52-
5352
}

src/main/java/io/github/hangga/delvelin/cwedetectors/GeneralScanner.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public void scan(Path path) {
6262
}
6363
}
6464

65+
public void addDetector(BaseDetector detector) {
66+
detectors.add(detector);
67+
}
68+
6569
private void detectByLine(String line, int lineNumber) {
6670
detectors.forEach(detector -> detector.detect(line, lineNumber));
6771
}

src/main/java/io/github/hangga/delvelin/properties/Config.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ public class Config {
99

1010
public static OutputFileFormat outputFileFormat = OutputFileFormat.LOG;
1111

12-
public static String VERSION = "0.1.2-beta";
12+
public static String VERSION = "0.2.0-beta";
1313
}

src/main/java/io/github/hangga/delvelin/properties/Vulnerabilities.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package io.github.hangga.delvelin.properties;
22

33
public enum Vulnerabilities {
4-
SQL_INJECTION("SQL Injection", "CWE-89", "Critical".toUpperCase().toUpperCase()),
4+
SQL_INJECTION("SQL Injection", "CWE-89", "Critical".toUpperCase()),
55
COMMAND_INJECTION("Command Injection", "CWE-77", "Critical".toUpperCase()),
66
XSS("Cross-Site Scripting (XSS)", "CWE-79", "MODERATE"),
77
INSECURE_DESERIALIZATION("Insecure Deserialization", "CWE-502", "High".toUpperCase()),
88
UNSAFE_STRINGBUILDER("Unsafe StringBuilder Usage in Multithread", "CWE-362", "MODERATE"),
99
HARDCODED_SECRETS("Hardcoded Secrets and Credentials", "CWE-798", "High".toUpperCase()),
10-
HTTP_NO_SSL("HTTP Connection without SSL/TLS", "CWE-319", "High".toUpperCase()),
10+
HTTP_NO_SSL("HTTP Connection without SSL/TTLS", "CWE-319", "High".toUpperCase()),
1111
WEAK_CRYPTO("Weak Cryptographic Algorithms", "CWE-327", "MODERATE"),
1212
UNSAFE_OBJECT_CLONE("Unsafe Object.clone() Usage", "CWE-374", "MODERATE"),
1313
WEAK_SESSION_MANAGEMENT("Weak Session Management", "CWE-384", "MODERATE"),
@@ -18,7 +18,18 @@ public enum Vulnerabilities {
1818
UNSAFE_REFLECTION("Unsafe Use of Reflection", "CWE-470", "MODERATE"),
1919
NON_ATOMIC("Assignment to Variable without Proper Synchronization", "CWE-563", "MODERATE"),
2020
CONSIDER_COROUTINES("Non-Adherence to Coding Standards (Consider using coroutines instead of threads in Kotlin)", "CWE-710", "Low".toUpperCase()),
21-
NON_THREAD_SAFE_DATA_STRUCTURE("Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition)", "CWE-362", "MODERATE");
21+
NON_THREAD_SAFE_DATA_STRUCTURE("Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition)", "CWE-362", "MODERATE"),
22+
BUFFER_OVERFLOW("Buffer Overflow", "CWE-120", "Critical".toUpperCase()),
23+
INTEGER_OVERFLOW("Integer Overflow", "CWE-190", "High".toUpperCase()),
24+
UNRESTRICTED_UPLOAD("Unrestricted File Upload", "CWE-434", "High".toUpperCase()),
25+
UNVALIDATED_REDIRECT("Unvalidated Redirects and Forwards", "CWE-601", "Moderate".toUpperCase()),
26+
INSUFFICIENT_LOGGING("Insufficient Logging and Monitoring", "CWE-778", "Low".toUpperCase()),
27+
OPEN_REDIRECT("Open Redirect", "CWE-601", "High".toUpperCase()),
28+
INSECURE_COOKIE("Insecure Cookie Storage", "CWE-614", "High".toUpperCase()),
29+
MISSING_FUNCTION_LEVEL_ACCESS_CONTROL("Missing Function Level Access Control", "CWE-862", "Moderate".toUpperCase()),
30+
INSUFFICIENT_TRANSPORT_LAYER_PROTECTION("Insufficient Transport Layer Protection", "CWE-311", "High".toUpperCase()),
31+
SECURE_RANDOM("Use of a Broken or Risky Cryptographic Algorithm", "CWE-327", "High".toUpperCase()),
32+
UNSAFE_API_USAGE("Unsafe API Usage", "CWE-1234", "High".toUpperCase()); // Custom CWE example
2233

2334
private final String description;
2435
private final String cweCode;

src/test/kotlin/DelvelinUnitTest.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import io.github.hangga.delvelin.Delvelin
2+
import io.github.hangga.delvelin.cwedetectors.BaseDetector
23
import io.github.hangga.delvelin.properties.OutputFileFormat
4+
import io.github.hangga.delvelin.properties.Vulnerabilities
35
import org.junit.jupiter.api.Test
46
import java.io.BufferedReader
57
import java.io.InputStreamReader
@@ -12,6 +14,44 @@ import javax.net.ssl.TrustManagerFactory
1214

1315
class DelvelinUnitTest {
1416

17+
class ExampleCustomDetector : BaseDetector() {
18+
19+
init {
20+
this.vulnerabilities = Vulnerabilities.UNSAFE_REFLECTION
21+
}
22+
23+
override fun detect(line: String, lineNumber: Int) {
24+
// Implementation of line based detection
25+
if (line.contains("examplePattern")) {
26+
val specificLocation = specificLocation(lineNumber)
27+
setValidVulnerability(
28+
specificLocation,
29+
"Example finding",
30+
"Detected example pattern in the code"
31+
)
32+
}
33+
}
34+
35+
override fun detect(content: String) {
36+
// Implementation of full content based detection
37+
if (content.contains("examplePattern")) {
38+
val specificLocation = specificLocation(-1) // -1 to denote whole content
39+
setValidVulnerability(
40+
specificLocation,
41+
"Example finding",
42+
"Detected example pattern in the full content"
43+
)
44+
}
45+
}
46+
}
47+
48+
@Test
49+
fun `test using your own custom detector`() {
50+
Delvelin().setOutputFormat(OutputFileFormat.HTML)
51+
.addCustomDetector(ExampleCustomDetector())
52+
.scan()
53+
}
54+
1555
@Test
1656
fun `vulnerability test`() {
1757
Delvelin().setOutputFormat(OutputFileFormat.HTML)

0 commit comments

Comments
 (0)