Custom scripts

Custom scripts make your DAST scans more dynamic. You can add JavaScript to manipulate HTTP requests and responses during a scan, either before a request is sent to the server or after a response is received.

Overview

Custom scripts run inside AppScan and operate on in-memory request and response models, letting you programmatically adjust requests and inspect responses without building an extension or using a proxy.

At a glance

Before request: Executes a script to modify an HTTP request before it is sent to your application (adding/removing headers, encrypting data, handling tokens, etc).

After response: Process the HTTP response after it is received from your application (decrypt content, extract values, etc).

Parameter: Generate values for Multi-step operations and Form Filler using JavaScript only.

Use this feature wisely to enhance the efficiency and effectiveness of your scans. Test your scripts in a controlled environment before live deployment to ensure they function as expected.

Sample template path: C:\Program Files (x86)\HCL\AppScan Standard\Templates.

Custom scripts examples: GitHub repository.

Adding custom scripts

Add custom JavaScripts to your DAST scans as follows:
  1. Select Custom scripts from the Advanced section in the configuration settings.
  2. Click the + Add button.
  3. Edit the prepopulated Name field as necessary.
  4. Choose the appropriate Execution context for your script: :
    1. Before requestfor scripts to run before sending requests.
    2. After response for scripts to run after receiving responses.
    3. Parameter for tasks that involve multiple steps or filling out forms. You can use this context in conjuction with the setResultValue method to allow scripts to return results to AppScan.
  5. Enter your JavaScript in the JavaScript field (code-editor) and use Ctrl+Space for auto-complete suggestions within the AppScan environment.
  6. Click Add to save your script. The script is added to the list and enabled by default.
  7. You can choose to enable or disable a script from the list of custom scripts using the Enable checkbox.
  8. Manage your scripts using the Enable checkbox or by editing, deleting, or reordering them in the script list. Options menu
  9. Click Start full scan to run the scan.
  10. Result: The enabled scripts are executed for each request or response. You can view the details of the scripts from Data > Requests tab > Request/Response.

    Verify your script for syntax accuracy and compatibility with the supported JavaScript version in AppScan. For detailed guidelines, refer to JavaScript code.

    Note:
    • Custom scripts are saved in the scan configuration file and can be exported with a template. They are not included in scan results.
    • By default, custom scripts are encrypted when exported in a template. To disable encryption, set the General: Encrypt sensitive data setting to False in the scan configuration.

Activating custom scripts

Custom scripts are enabled by default and execute with every HTTP request and response during recording and scanning.

To disable the script execution, go to Tools > Options > Advanced tab and set the CustomScripts.Enable setting to "False".

Execution contexts

Before request

Purpose: Mutate outgoing HTTP requests.

Data: Only request and environment objects are available, other objects will be null.
// Attach Authorization from stored global variable
var token = environment.globalVariables.get("Authorization");
if (token) request.headers.set("Authorization", token);

After response

Purpose: Inspect responses and persist values.

Data: Only response and environment data objects are available. Other objects will be null.
// Capture token from JSON response and store it for reuse
try {
		var result = JSON.parse(response.body);
		if (result && result.Authorization) {
			environment.globalVariables.addOrUpdate("Authorization", result.Authorization);
		}
} catch(e) { log(e); }

Parameter

Purpose: Generate values for Multi‑step operations and Form Filler.
  • No data objects (request or response) are available in this context; using them returns null.
  • Return values with setResultValue(value).

In Form Filler, when you select Value source > Custom script, the list shows only scripts whose execution context is Parameter.

In Multi‑step operations, you can also provide dynamic values using Parameter scripts.
// Example: Return a unique email for registration flows
function random(n) { return Math.random().toString(36).slice(2, 2+n); }
var email = "test_" + Date.now() + "_" + random(6) + "@example.test";
setResultValue(email);

API reference

Request object (Before request context) - full API
// Examples:
// Handle headers
request.headers.set("Authorization", "Bearer");
request.headers.add("X-Trace", "abc");

// Manipulate body
request.body = JSON.stringify( { user:"admin" });
if(request.body.includes("admin") { ... }

// Read path
if (request.path.startsWith("/api/v1")) { ... }

// Edit query
request.query.addOrUpdate("lang","en")
request.query.remove("debug")
request.query.getQueryString()

// Read method
if (request.method == "GET") { ... }
CAUTION: Since the scripts might execute multiple times per request, it is advisable to use the set method to add new headers, as it replaces existing headers and prevents duplicates. Use the add method only when you need multiple headers with the same name and different values. The add method will not add a header if one with the same name and value already exists. Be careful to avoid duplicating headers, as this can cause errors.
Response object (After response context) - full API
// Examples:
// Handle headers
response.headers.set("Authorization", "Bearer");
response.headers.add("X-Trace", "abc");

// Read body (since it's read only)
var j = JSON.parse(response.body);

// Read path
if (response.path.startsWith("/api/v1")) { ... }

// Read response
if (response.status.statusCode == 200) { ... }

// Read parent request
if (response.request.path.startsWith("/api/v1")) { ... }
Parameter context - full API
// Update the result back to AppScan
setResultValue("ABC-" + Date.now());

Environment data

Short-term data is available only until the task ends—for example, when you pause, stop, or complete a scan, log in, or end a manual test. It is cleared at the start of each new scan or rescan.

  1. Global variables: The global variables data is a key-value data structure designed to store user-specific data pairs. The keys are unique (meaning no two elements can have the same key, though multiple elements can share the same value), which is useful for sharing data between running scripts.
  2. Scan status: Contains information about the current scan.
    // Check the status of the scan
    environment.status.isInExplore();
    environment.status.isInTest();

Logging - full API

Enable logging in your script to help with debugging and troubleshooting. The standard console.log command is not supported in this environment. Instead, use the log function with a quoted message, for example: log("Your message here"). If a runtime error occurs during the engine's operation that is not related to JavaScript syntax or usage, it is recorded in the engine trace log for further analysis.

Logs are written to the UserScript.log file in the AppScan logging folder.

By default, the folder is [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs.

Constraints and execution limits

  • Restricted functions: eval, Function (constructor), setTimeout, setlnterval. If any of these are used, the script fails.
  • Limits: Maximum execution time: 5 seconds; memory limit: 64 MB. Exceeding these limits causes the script to fail.

    On failure, the scan pauses and details are recorded in UserScript.log.

Supported JavaScript versions

ECMAScript ES6 (2015) through ES15 (2024), with exceptions:
  • ES6: Generators, Tail calls
  • ES8: Shared memory and atomics
  • ES15: Atomics.waitAsync, Regex flag \v

Objects available in auto-complete

These objects appear in the script editor’s auto-complete suggestions, making them easy to find and use:

  • Keyword
  • Array
  • Date
  • Object
  • String
  • RegExp
  • JSON
  • Map
  • Math
Supported but not in auto-complete

These objects are fully supported by the script engine but will not appear in autocomplete lists. You can still use them by typing their names directly in the editor:

  • ArrayBuffer
  • BigInt
  • Boolean
  • DataView
  • Error
  • Iterator
  • Number
  • Promise
  • Proxy
  • Reflect
  • SharedArrayBuffer
  • Symbol
  • TypedArray

  • WeakMap

  • WeakRef

  • WeakSet

    Note: “Not in auto-complete” means the editor will not suggest these items automatically; however, the objects are implemented and behave exactly as they do in standard JavaScript.

Troubleshooting

Common issues and solutions:
  1. Script failures: Check the logs folder (default: [UserDataFolder]\AppData\Roaming\HCL\AppScan Standard\logs) for details about the error. If you encounter an unhandled exception, wrap your code in a try...catch block to handle it gracefully.
  2. Script not executing: Make sure the script is enabled in the configuration settings.

    If the issue is related to login/authorization, consider removing the negotiate value from Configuration→ Advanced Configuration → Security Package Order to prevent AppScan from handling those authentications automatically.

Request full API

Table 1. Request object - properties
Member Type Description Example
headers object An object encapsulating the headers of the current HTTP request, providing methods to add, update, retrieve, or remove headers dynamically, enabling precise control over the request's metadata. request.headers.set("Authorization","Bearer ...")
body string The body of the current HTTP request. request.body = JSON.stringify({ user:"jsmith" })
path string

Read only🔒

The relative path of the current HTTP request.

if (request.path.startsWith("/api/v1/")) { ... }
query object An object that contains various methods to add, update, or remove query parameters in the current HTTP request, allowing dynamic manipulation of the query string. request.query.addOrUpdate("lang","en") request.query.remove("debug")
method string

Read only🔒

The method of the current HTTP request.

if (request.method == "GET") {{ ... }}
Table 2. Query object - methods
Member Type Description Example

addOrUpdate

(name: string, value: string)

void Adds a new value to the query string or updates an existing one. request.query.addOrUpdate("appscan","appscanvalue")
getQueryString() string

Returns the full query string of the current HTTP request, including all parameters and their values.

request.query.getQueryString()

contains

(name: string)

boolean

Checks if a specific query parameter exists in the current HTTP request.

Returns true if the parameter exists, false otherwise.

request.query.contains("lang")

remove

(name: string)

boolean

Removes a specific query parameter from the current HTTP request.

Returns true if the parameter was removed, false if not.

request.query.remove("lang")
clear() void

Removes all query parameters from the current HTTP request.

request.query.clear()

Response full API

Table 3. Response objectStatus object
Member Type Description Example
headers object An object encapsulating the headers of the current HTTP response, providing methods to add, update, retrieve, or remove headers dynamically, enabling precise control over the response's metadata. response.headers.set("Authorization","Bearer ...")
body string The body of the current HTTP response. response.body = JSON.stringify({ user:"jsmith" })
path string

Read only🔒

The relative path of the current HTTP response.

if (response.path.startsWith("/api/v1/")) { ... }
status object An object representing the status of the current HTTP response, including properties for the status code and status message. if (response.status.code == 200) { ... }
request object An object representing the request that initiated the response. The request data is read-only and includes all the properties defined in the previously described request object. if (response.request.path) { ... }
Table 4. Properties
Member Type Description Example
statusCode number

Read only🔒

The HTTP status code of the current response.

response.status.statusCode = 200
statusDescription string

Read only🔒

The HTTP status message of the current response.

response.status.statusDescription = "OK"
statusLine string

Read only🔒

The HTTP status line of the current response.

response.status.statusLine = "HTTP/1.1 200 OK"

Parameter full API

Table 5. Parameter object
Member Type Description Example

setResultValue

(value: string)

void Sets the result value for the current parameter context script. setResultValue("ABC-" + Date.now())

Common objects

Table 6. Headers object - properties
Member Type Description Example
items array

Read only🔒

An array of all headers in the current HTTP request.

if (request.headers.items.length > 0) { ... }

if (response.headers.items.length > 0) { ... }

Table 7. Headers object - methods
Member Type Description Example
add

(name: string, value: string)

void

Adds a new header to the current HTTP request. If a header with the same name and value already exists, it will not be added again.

request.headers.add("Authorization", "MyCoolApiKey")

response.headers.add("Authorization",MyCoolApiKey")

set

(name: string, value: string)

void Sets a header in the current HTTP request. If the header already exists, its value is replaced.

request.headers.set("Authorization", "SecondApiKey")

response.headers.set("Authorization","SecondApiKey")

remove

(name: string)

void Removes a header from the current HTTP request. request.headers.remove("Authorization")response.headers.remove("Authorization")
[name: string] string Retrieves the value of a specific header by its name. Returns null if the header does not exist.

request.headers['Authorization'] = "myapikey3"

response.headers['Authorization'] = "myapikey3"

Environment Data

Table 8. Environment object - properties
Member Type Description Example
globalVariables object A key-value data structure for storing user-specific data pairs. Keys must be unique, ensuring no duplicates, while values can be shared across multiple keys. This structure facilitates data sharing between running scripts. environment.globalVariables.addOrUpdate(key, value)
status object Information about the current status of the scan. environment.status.isInExplore()
Table 9. Globals variables object - methods
Member Type Description Example

addOrUpdate

(key: string, value:

string)

void Adds a new key-value pair to the global variables, or updates the value of an existing key. environment.globalVariables.addOrUpdate("mycoolkey", "testValue")

remove

(key: string)

boolean Removes a key-value pair from the global variables. Returns true if the key was found and removed, false otherwise. environment.globalVariables.remove("mycoolkey")
get

(key: string)

string Retrieves the value of a specific key from the global variables. Returns an empty string if the key does not exist. environment.globalVariables.get("mycoolkey")
Table 10. Status object - methods
Method Type Description Example
isInExplore() boolean Checks if the scan is currently in the explore phase. environment.status.isInExplore()
isInTest() boolean Checks if the scan is currently in the test phase. environment.status.isInTest()

Logging

Table 11. Methods
Member Type Description Example
log(message: string) log(message: string, source: string) void Adds a new log entry with the specified message and optional source. log("This is a log message")

log("This is a log message", "mySource")