Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docker/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changelog
All notable changes to the docker containers will be documented in this file.

### 2025-10-31
- Added config options for recording which packaged scan is being run.

### 2025-03-25
- Update ZAP API scan to support host override for local OpenAPI spec.

Expand Down
4 changes: 2 additions & 2 deletions docker/zap-api-scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def main(argv):

if running_in_docker():
try:
params = []
params = ['-config', 'stats.pkg.apiscan-api=1']

if "-silent" not in zap_options:
params.append('-addonupdate')
Expand All @@ -368,7 +368,7 @@ def main(argv):
if context_file:
mount_dir = os.path.dirname(os.path.abspath(context_file))

params = []
params = ['-config', 'stats.pkg.apiscan-api=1']

if "-silent" not in zap_options:
params.append('-addonupdate')
Expand Down
19 changes: 16 additions & 3 deletions docker/zap-baseline.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ def main(argv):
use_af = True
af_supported = True
af_override = False
no_af_reason = ''

pass_count = 0
warn_count = 0
Expand Down Expand Up @@ -211,6 +212,7 @@ def main(argv):
elif opt == '-g':
generate = arg
af_supported = False
no_af_reason = 'gen'
elif opt == '-d':
logging.getLogger().setLevel(logging.DEBUG)
debug = True
Expand All @@ -221,12 +223,15 @@ def main(argv):
elif opt == '-D':
delay = int(arg)
af_supported = False
no_af_reason = 'delay'
elif opt == '-n':
context_file = arg
af_supported = False
no_af_reason = 'context'
elif opt == '-p':
progress_file = arg
af_supported = False
no_af_reason = 'progress'
elif opt == '-r':
report_html = arg
elif opt == '-J':
Expand All @@ -240,6 +245,7 @@ def main(argv):
elif opt == '-i':
info_unspecified = True
af_supported = False
no_af_reason = 'info'
elif opt == '-I':
ignore_warn = True
elif opt == '-j':
Expand All @@ -252,6 +258,7 @@ def main(argv):
usage()
sys.exit(3)
af_supported = False
no_af_reason = 'level'
elif opt == '-z':
zap_options = arg
elif opt == '-s':
Expand All @@ -261,14 +268,17 @@ def main(argv):
elif opt == '-U':
user = arg
af_supported = False
no_af_reason = 'user'
elif opt == '--hook':
hook_file = arg
af_supported = False
no_af_reason = 'hook'
elif opt == '--auto':
use_af = True
af_override = True
elif opt == '--autooff':
use_af = False
no_af_reason = 'optout'

check_zap_client_version()

Expand Down Expand Up @@ -415,7 +425,7 @@ def main(argv):
run_zap_inline(port, install_opts)

# Run ZAP inline with the yaml file
params = ['-autorun', yaml_file]
params = ['-autorun', yaml_file, '-config', 'stats.pkg.baseline-af=1']

add_zap_options(params, zap_options)

Expand Down Expand Up @@ -457,7 +467,10 @@ def main(argv):

else:
try:
params = ['-config', 'spider.maxDuration=' + str(mins)]
params = ['-config', 'spider.maxDuration=' + str(mins), '-config', 'stats.pkg.baseline-api=1']

if len(no_af_reason) > 0:
params.extend(['-config', 'stats.pkg.xbaseline-' + no_af_reason + '=1'])

if "-silent" not in zap_options:
params.append('-addonupdate')
Expand All @@ -482,7 +495,7 @@ def main(argv):
mount_dir = os.path.dirname(os.path.abspath(context_file))


params = ['-config', 'spider.maxDuration=' + str(mins)]
params = ['-config', 'spider.maxDuration=' + str(mins), '-config', 'stats.pkg.baseline-api=1']

if "-silent" not in zap_options:
params.append('-addonupdate')
Expand Down
4 changes: 2 additions & 2 deletions docker/zap-full-scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def main(argv):

if running_in_docker():
try:
params = ['-config', 'spider.maxDuration=' + str(mins)]
params = ['-config', 'spider.maxDuration=' + str(mins), '-config', 'stats.pkg.fullscan-api=1']

if "-silent" not in zap_options:
params.append('-addonupdate')
Expand All @@ -307,7 +307,7 @@ def main(argv):
if context_file:
mount_dir = os.path.dirname(os.path.abspath(context_file))

params = ['-config', 'spider.maxDuration=' + str(mins)]
params = ['-config', 'spider.maxDuration=' + str(mins), '-config', 'stats.pkg.fullscan-api=1']

if "-silent" not in zap_options:
params.append('-addonupdate')
Expand Down
2 changes: 1 addition & 1 deletion docker/zap-webswing.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ case "$1" in
cd $HOME

# Set up the ZAP runtime options
ZAP_OPTS="-host 0.0.0.0 -port 8090"
ZAP_OPTS="-host 0.0.0.0 -port 8090 -config stats.pkg.webswing=1"
ZAP_PUBLIC="/zap/wrk/zap_root_ca.cer"
ZAP_PRIVATE="/zap/wrk/zap_root_ca.key"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
// ZAP: 2023/11/14 When setting CWE also add a CWE alert tag with an appropriate URL.
// ZAP: 2025/10/01 Added support for nodeName.
// ZAP: 2025/10/16 Added support for systemic alerts.
// ZAP: 2025/10/30 Adjust compateTo and equals handling of nodeName and uri (now case sensitive)
package org.parosproxy.paros.core.scanner;

import java.net.URL;
Expand Down Expand Up @@ -488,9 +489,9 @@ public int compareTo(Alert alert2) {
}

if (StringUtils.isNotBlank(nodeName) && StringUtils.isNotBlank(alert2.nodeName)) {
result = nodeName.compareToIgnoreCase(alert2.nodeName);
result = nodeName.compareTo(alert2.nodeName);
} else {
result = uri.compareToIgnoreCase(alert2.uri);
result = uri.compareTo(alert2.uri);
}
if (result != 0) {
return result;
Expand Down Expand Up @@ -570,7 +571,7 @@ public boolean equals(Object obj) {
if (!nodeName.equals(item.nodeName)) {
return false;
}
} else if (!uri.equalsIgnoreCase(item.uri)) {
} else if (!uri.equals(item.uri)) {
return false;
}
if (!param.equalsIgnoreCase(item.param)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
public class Scanner implements Runnable {

public static final String ASCAN_SCAN_STARTED_STATS = "stats.ascan.started";
public static final String ASCAN_SCAN_STARTED_USER_STATS = "stats.ascan.started.user";
public static final String ASCAN_SCAN_STOPPED_STATS = "stats.ascan.stopped";
public static final String ASCAN_SCAN_TIME_STATS = "stats.ascan.time";
public static final String ASCAN_URLS_STATS = "stats.ascan.urls";
Expand Down Expand Up @@ -209,6 +210,9 @@ public void start(Target target) {
ActiveScanEventPublisher.publishScanEvent(
ScanEventPublisher.SCAN_STARTED_EVENT, this.getId(), target, this.user);
Stats.incCounter(ASCAN_SCAN_STARTED_STATS);
if (this.user != null) {
Stats.incCounter(ASCAN_SCAN_STARTED_USER_STATS);
}
}

public void stop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -150,6 +151,36 @@ void shouldNotEqualIfAlertRefDifferent() {
assertThat(equals, is(equalTo(false)));
}

@Test
void shouldNotEqualIfAlertUriDifferentCapitalization() {
// Given
Alert alertA = new Alert(1);
Alert alertB = new Alert(1);
// When
alertA.setAlertId(0);
alertB.setAlertId(1);
alertA.setUri("https://example.com/SCRIPT?q=a");
alertB.setUri("https://example.com/script?q=a");
boolean equals = alertA.equals(alertB);
// Then
assertThat(equals, is(equalTo(false)));
}

@Test
void shouldNotEqualIfAlertNodeNameDifferentCapitalization() {
// Given
Alert alertA = new Alert(1);
Alert alertB = new Alert(1);
// When
alertA.setAlertId(0);
alertB.setAlertId(1);
alertA.setNodeName("https://example.com/SCRIPT (q)");
alertB.setNodeName("https://example.com/script (q)");
boolean equals = alertA.equals(alertB);
// Then
assertThat(equals, is(equalTo(false)));
}

@Test
void shouldNotCompareIfAlertRefDifferent() {
// Given
Expand All @@ -165,6 +196,36 @@ void shouldNotCompareIfAlertRefDifferent() {
assertThat(cmp, is(equalTo(-1)));
}

@Test
void shouldCompareDissimilarIfAlertNodeNameDifferentByCapitalization() {
// Given
Alert alertA = new Alert(1);
Alert alertB = new Alert(1);
// When
alertA.setAlertId(0);
alertB.setAlertId(1);
alertA.setNodeName("https://example.com/SCRIPT (q)");
alertB.setNodeName("https://example.com/script (q)");
int cmp = alertA.compareTo(alertB);
// Then
assertThat(cmp, is(lessThan(0)));
}

@Test
void shouldCompareDissimilarIfAlertUriDifferentByCapitalization() {
// Given
Alert alertA = new Alert(1);
Alert alertB = new Alert(1);
// When
alertA.setAlertId(0);
alertB.setAlertId(1);
alertA.setUri("https://example.com/SCRIPT?q=a");
alertB.setUri("https://example.com/script?q=a");
int cmp = alertA.compareTo(alertB);
// Then
assertThat(cmp, is(lessThan(0)));
}

@Test
void shouldBuildAlertWithOneTag() {
// Given
Expand Down Expand Up @@ -289,7 +350,6 @@ void shouldAddLastCweTagEvenIfCweIdSetTwiceAndBuildTwice() {
// Then
Map<String, String> tags = alert.getTags();
assertThat(tagCount, is(equalTo(1)));
System.out.println(tags);
assertThat(tags.containsKey(cwe2Key), is(equalTo(true)));
assertThat(tags.get(cwe2Key), is(equalTo(cwe2Url)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,20 @@ void shouldFindSimilarAlert() {
getAlert(
0,
"Test Alert",
"https://www.example.com/(test)",
"https://www.example.com/ (test)",
"https://www.example.com/?test=1");
Alert a2 =
getAlert(
1,
"Test Alert",
"https://www.example.com/(test)",
"https://www.example.com/ (test)",
"https://www.example.com/?test=2");
Alert a3 =
getAlert(
2,
"Test Alert",
"https://www.example.com/(x)",
"https://www.example.com/?test=2");
"https://www.example.com/ (x)",
"https://www.example.com/?x=2");

// When
alertSet.add(a1);
Expand Down
Loading