Passive scan check worked example

You can extend Burp Scanner by writing your own scan checks. A custom scan check can report new security issues that Burp doesn't detect natively.

In this worked example, we'll use Java to write a passive custom scan check. Passive checks analyze traffic without modifying or sending any new requests. Use these to detect vulnerabilities that are visible directly in responses, such as:

Related pages

This example reports an issue when a response doesn't include a Content-Security-Policy header. It is intended to run once for every request in the scan:

if (!requestResponse.hasResponse()) { return AuditResult.auditResult(); } if (!requestResponse.response().hasHeader("Content-Security-Policy")) { var issueTitle = "Content Security Policy header missing"; var issueDetail = "The response does not include a Content-Security-Policy header. Without this header the browser cannot enforce a restrictive policy for scripts, styles, images and other resources, increasing exposure to XSS, click-jacking and content-injection attacks."; var remediation = "Add a suitable Content-Security-Policy header, for example: Content-Security-Policy: default-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'none';"; var background = "Content Security Policy (CSP) is an HTTP response header that tells the browser which sources are permitted for each resource type. A correctly configured CSP helps mitigate XSS and other code-injection flaws by limiting the origins from which content can be loaded."; var remediationBackground = "Create a baseline policy in report-only mode, review violation reports, then switch to enforcement. Start with default-src 'self' and add only the sources that the application legitimately requires."; return AuditResult.auditResult( AuditIssue.auditIssue( issueTitle, issueDetail, remediation, requestResponse.request().url(), AuditIssueSeverity.LOW, AuditIssueConfidence.FIRM, background, remediationBackground, AuditIssueSeverity.LOW, requestResponse ) ); } return AuditResult.auditResult();

Step 1: Make sure there's a response

if (!requestResponse.hasResponse()) { return AuditResult.auditResult(); }

Before doing anything, the check confirms there's a response to work with. It exits cleanly if a response doesn't exist.

Breakdown of the code

Step 2: Check for the CSP header

if (!requestResponse.response().hasHeader("Content-Security-Policy")) { // Build and return an issue }

This checks if the response sets a Content-Security-Policy header. If the header is missing, the code will continue to build an issue.

Breakdown of the code

Step 3: Build the issue variables

var issueTitle = "Content Security Policy header missing"; var issueDetail = "The response does not include a Content-Security-Policy header. Without this header the browser cannot enforce a restrictive policy for scripts, styles, images and other resources, increasing exposure to XSS, click-jacking and content-injection attacks."; var remediation = "Add a suitable Content-Security-Policy header, for example: Content-Security-Policy: default-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'none';"; var background = "Content Security Policy (CSP) is an HTTP response header that tells the browser which sources are permitted for each resource type. A correctly configured CSP helps mitigate XSS and other code-injection flaws by limiting the origins from which content can be loaded."; var remediationBackground = "Create a baseline policy in report-only mode, review violation reports, then switch to enforcement. Start with default-src 'self' and add only the sources that the application legitimately requires."

These variables define what appears in the reported issue.

Breakdown of the code

Step 4: Return an issue if no CSP header is present

return AuditResult.auditResult( AuditIssue.auditIssue( issueTitle, issueDetail, remediation, requestResponse.request().url(), AuditIssueSeverity.LOW, AuditIssueConfidence.FIRM, background, remediationBackground, AuditIssueSeverity.LOW, requestResponse ) );

This wraps the issue variables into an AuditIssue and returns an AuditResult containing that issue. When the check reports a finding, users can view it in the All issues panel (accessible from the bottom dock) or from the Issues tab for the relevant task on the Dashboard.

Breakdown of the code

Step 5: Return an empty result when the header is present

return AuditResult.auditResult();

If the Content-Security-Policy header exists, or the script exited early in Step 1, this returns an empty result so no issue is reported.