Skip to content

Commit 36d86ea

Browse files
quickstart: Add Scan Policy option to Automated Scan panel (#7300)
1 parent a3f4cd4 commit 36d86ea

8 files changed

Lines changed: 161 additions & 3 deletions

File tree

addOns/quickstart/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ All notable changes to this add-on will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
55

66
## Unreleased
7+
### Added
8+
- Add Scan Policy option to the Automated Scan panel.
79

810

911
## [55] - 2026-03-09

addOns/quickstart/src/main/java/org/zaproxy/zap/extension/quickstart/AttackPanel.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import org.parosproxy.paros.model.SiteNode;
3939
import org.parosproxy.paros.view.View;
4040
import org.zaproxy.zap.extension.alert.ExtensionAlert;
41+
import org.zaproxy.zap.extension.ascan.ExtensionActiveScan;
42+
import org.zaproxy.zap.extension.ascan.PolicyManager;
4143
import org.zaproxy.zap.extension.search.SearchPanel;
4244
import org.zaproxy.zap.utils.DisplayUtils;
4345
import org.zaproxy.zap.view.LayoutHelper;
@@ -48,10 +50,12 @@ public class AttackPanel extends QuickStartSubPanel {
4850
private static final long serialVersionUID = 1L;
4951

5052
private static final String DEFAULT_VALUE_URL_FIELD = "http://";
53+
private static final String DEFAULT_SCAN_POLICY = "Dev Standard";
5154

5255
private ImageIcon icon;
5356
private JButton attackButton;
5457
private JButton stopButton;
58+
private JComboBox<String> policyField;
5559
private JComboBox<String> urlField;
5660
private DefaultComboBoxModel<String> urlModel;
5761
private JButton selectButton;
@@ -149,6 +153,11 @@ public JPanel getContentPanel() {
149153
urlSelectPanel.add(this.getUrlField(), LayoutHelper.getGBC(0, 0, 1, 0.5D));
150154
urlSelectPanel.add(selectButton, LayoutHelper.getGBC(1, 0, 1, 0.0D));
151155
contentPanel.add(urlSelectPanel, LayoutHelper.getGBC(2, formPanelY, 3, 0.25D));
156+
contentPanel.add(
157+
new JLabel(Constant.messages.getString("quickstart.label.policy")),
158+
LayoutHelper.getGBC(
159+
1, ++formPanelY, 1, 0.0D, DisplayUtils.getScaledInsets(5, 5, 5, 5)));
160+
contentPanel.add(getPolicyField(), LayoutHelper.getGBC(2, formPanelY, 1, 0.25D));
152161

153162
traditionalSpiderY = ++formPanelY;
154163
plugableSpiderY = ++formPanelY;
@@ -173,6 +182,35 @@ public JPanel getContentPanel() {
173182
return contentPanel;
174183
}
175184

185+
private JComboBox<String> getPolicyField() {
186+
if (policyField == null) {
187+
policyField = new JComboBox<>();
188+
ExtensionActiveScan extAscan =
189+
Control.getSingleton()
190+
.getExtensionLoader()
191+
.getExtension(ExtensionActiveScan.class);
192+
if (extAscan != null) {
193+
extAscan.getPolicyManager().getAllPolicyNames().forEach(policyField::addItem);
194+
}
195+
}
196+
return policyField;
197+
}
198+
199+
private void selectScanPolicy() {
200+
String savedPolicy = getExtensionQuickStart().getQuickStartParam().getScanPolicyName();
201+
if (!setPolicy(savedPolicy)) {
202+
setPolicy(DEFAULT_SCAN_POLICY);
203+
}
204+
}
205+
206+
private boolean setPolicy(String policyName) {
207+
if (policyName != null && PolicyManager.policyExists(policyName)) {
208+
policyField.setSelectedItem(policyName);
209+
return true;
210+
}
211+
return false;
212+
}
213+
176214
private JLabel getProgressLabel() {
177215
if (progressLabel == null) {
178216
progressLabel =
@@ -401,12 +439,17 @@ boolean attackUrl() {
401439
this.getUrlField().requestFocusInWindow();
402440
return false;
403441
}
442+
String selectedPolicy = (String) policyField.getSelectedItem();
443+
getExtensionQuickStart().getQuickStartParam().setScanPolicyName(selectedPolicy);
404444
this.getExtensionQuickStart().getQuickStartParam().addRecentUrl(urlStr);
405445
getAttackButton().setEnabled(false);
406446
getStopButton().setEnabled(true);
407447

408448
getExtensionQuickStart()
409-
.attack(url, traditionalSpider != null && traditionalSpider.isSelected());
449+
.attack(
450+
url,
451+
traditionalSpider != null && traditionalSpider.isSelected(),
452+
selectedPolicy);
410453
setSpiderButtonsEnabled(false);
411454
return true;
412455
}
@@ -465,10 +508,11 @@ protected void notifyProgress(AttackThread.Progress progress, String msg) {
465508

466509
public void optionsLoaded(QuickStartParam quickStartParam) {
467510
setRecentUrls();
511+
selectScanPolicy();
468512
}
469513

470514
public void optionsChanged(OptionsParam optionsParam) {
471-
setRecentUrls();
515+
optionsLoaded(optionsParam.getParamSet(QuickStartParam.class));
472516
}
473517

474518
@Override

addOns/quickstart/src/main/java/org/zaproxy/zap/extension/quickstart/AttackThread.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.parosproxy.paros.model.SiteNode;
3030
import org.zaproxy.zap.extension.ascan.ActiveScan;
3131
import org.zaproxy.zap.extension.ascan.ExtensionActiveScan;
32+
import org.zaproxy.zap.extension.ascan.ScanPolicy;
3233
import org.zaproxy.zap.model.Target;
3334
import org.zaproxy.zap.network.HttpRequestConfig;
3435
import org.zaproxy.zap.utils.Stats;
@@ -52,6 +53,7 @@ public enum Progress {
5253
private PlugableSpider plugableSpider;
5354
private boolean stopAttack = false;
5455
private boolean useStdSpider;
56+
private String scanPolicyName;
5557

5658
private static final Logger LOGGER = LogManager.getLogger(AttackThread.class);
5759

@@ -72,6 +74,10 @@ public void setTraditionalSpider(TraditionalSpider traditionalSpider) {
7274
this.traditionalSpider = traditionalSpider;
7375
}
7476

77+
public void setScanPolicyName(String scanPolicyName) {
78+
this.scanPolicyName = scanPolicyName;
79+
}
80+
7581
public void setPlugableSpider(PlugableSpider plugableSpider) {
7682
this.plugableSpider = plugableSpider;
7783
}
@@ -191,7 +197,18 @@ public void run() {
191197
return;
192198
} else {
193199
extension.notifyProgress(Progress.ascan);
194-
scanId = extAscan.startScan(target);
200+
ScanPolicy scanPolicy = null;
201+
if (scanPolicyName != null && !scanPolicyName.isEmpty()) {
202+
try {
203+
scanPolicy = extAscan.getPolicyManager().getPolicy(scanPolicyName);
204+
} catch (Exception ex) {
205+
LOGGER.warn("Failed to load policy {}, using default", scanPolicyName);
206+
}
207+
}
208+
if (scanPolicy == null) {
209+
scanPolicy = extAscan.getPolicyManager().getDefaultScanPolicy();
210+
}
211+
scanId = extAscan.startScan(target, null, new Object[] {scanPolicy});
195212
}
196213

197214
try {

addOns/quickstart/src/main/java/org/zaproxy/zap/extension/quickstart/ExtensionQuickStart.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,18 @@ public String getUIName() {
312312
}
313313

314314
public void attack(URL url, boolean useStdSpider) {
315+
attack(url, useStdSpider, null);
316+
}
317+
318+
public void attack(URL url, boolean useStdSpider, String policyName) {
315319
if (attackThread != null && attackThread.isAlive()) {
316320
return;
317321
}
318322
attackThread = new AttackThread(this, useStdSpider);
319323
attackThread.setURL(url);
320324
attackThread.setTraditionalSpider(traditionalSpider);
321325
attackThread.setPlugableSpider(plugableSpider);
326+
attackThread.setScanPolicyName(policyName);
322327
attackThread.start();
323328
}
324329

addOns/quickstart/src/main/java/org/zaproxy/zap/extension/quickstart/QuickStartParam.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public class QuickStartParam extends VersionedAbstractParam {
6363

6464
private static final String PARAM_CLEARED_NEWS_ITEM = PARAM_BASE_KEY + ".clearedNews";
6565

66+
private static final String PARAM_SCAN_POLICY_NAME = PARAM_BASE_KEY + ".scanPolicyName";
67+
6668
/**
6769
* The current version of the configurations. Used to keep track of configuration changes
6870
* between releases, in case changes/updates are needed.
@@ -90,6 +92,7 @@ public class QuickStartParam extends VersionedAbstractParam {
9092
private String ajaxSpiderSelection;
9193
private String ajaxSpiderDefaultBrowser;
9294
private String clearedNewsItem;
95+
private String scanPolicyName;
9396

9497
@Override
9598
protected void parseImpl() {
@@ -138,6 +141,11 @@ protected void parseImpl() {
138141
} catch (Exception e) {
139142
LOGGER.error("Failed to load the cleared news item configuration", e);
140143
}
144+
try {
145+
scanPolicyName = getConfig().getString(PARAM_SCAN_POLICY_NAME, "");
146+
} catch (Exception e) {
147+
LOGGER.error("Failed to load the cleared news item configuration", e);
148+
}
141149
}
142150

143151
@Override
@@ -250,6 +258,15 @@ public void addRecentUrl(String url) {
250258
QuickStartHelper.raiseOptionsChangedEvent();
251259
}
252260

261+
public String getScanPolicyName() {
262+
return scanPolicyName;
263+
}
264+
265+
public void setScanPolicyName(String scanPolicyName) {
266+
this.scanPolicyName = scanPolicyName;
267+
getConfig().setProperty(PARAM_SCAN_POLICY_NAME, scanPolicyName);
268+
}
269+
253270
public String getClearedNewsItem() {
254271
return clearedNewsItem;
255272
}

addOns/quickstart/src/main/javahelp/org/zaproxy/zap/extension/quickstart/resources/help/contents/quickstart.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ <H3>URL to attack</H3>
2929
This is because https://example.com/test/ is treated as a leaf node internally, which would mean that ZAP would not attack
3030
URLs like https://example.com/test/1 etc.
3131

32+
<H3>Scan Policy</H3>
33+
34+
The scan policy to use when performing the active scan.
35+
Note that the policies will not be shown dynamically, any added/removed policies will be missing until a restart is done.
36+
3237
<H3>Use traditional spider</H3>
3338

3439
The traditional spider explores the application by finding links in HTML pages.

addOns/quickstart/src/main/resources/org/zaproxy/zap/extension/quickstart/resources/Messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ quickstart.label.exploreurl = URL to explore:
8787
quickstart.label.hud = Enable HUD:
8888
quickstart.label.hud.warn.scope = Warning: the HUD is only enabled for URLs in scope
8989
quickstart.label.news = News
90+
quickstart.label.policy = Scan Policy:
9091
quickstart.label.progress = Progress:
9192
quickstart.label.show = Show this tab on start up:
9293
quickstart.label.tradspider = Use traditional spider:
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Zed Attack Proxy (ZAP) and its related class files.
3+
*
4+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
5+
*
6+
* Copyright 2026 The ZAP Development Team
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
package org.zaproxy.zap.extension.quickstart;
21+
22+
import static org.hamcrest.MatcherAssert.assertThat;
23+
import static org.hamcrest.Matchers.equalTo;
24+
import static org.hamcrest.Matchers.is;
25+
26+
import org.junit.jupiter.api.BeforeEach;
27+
import org.junit.jupiter.api.Test;
28+
import org.zaproxy.zap.utils.ZapXmlConfiguration;
29+
30+
/** Unit test for {@link QuickStartParam}. */
31+
class QuickStartParamUnitTest {
32+
33+
private QuickStartParam param;
34+
private ZapXmlConfiguration configuration;
35+
36+
@BeforeEach
37+
void setUp() {
38+
param = new QuickStartParam();
39+
configuration = new ZapXmlConfiguration();
40+
param.load(configuration);
41+
}
42+
43+
@Test
44+
void shouldDefaultScanPolicyNameToEmpty() {
45+
assertThat(param.getScanPolicyName(), is(equalTo("")));
46+
}
47+
48+
@Test
49+
void shouldSaveScanPolicyName() {
50+
// Given
51+
String policyName = "Test Policy";
52+
// When
53+
param.setScanPolicyName(policyName);
54+
// Then
55+
assertThat(param.getScanPolicyName(), is(equalTo(policyName)));
56+
}
57+
58+
@Test
59+
void shouldLoadScanPolicyNameFromConfig() {
60+
// Given
61+
configuration.setProperty("quickstart.scanPolicyName", "My Policy");
62+
// When
63+
param.load(configuration);
64+
// Then
65+
assertThat(param.getScanPolicyName(), is(equalTo("My Policy")));
66+
}
67+
}

0 commit comments

Comments
 (0)