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
- Select Custom scripts from the Advanced section in the configuration settings.
- Click the + Add button.
- Edit the prepopulated Name field as necessary.
- Choose the appropriate Execution context for your
script: :
- Before requestfor scripts to run before sending requests.
- After response for scripts to run after receiving responses.
- Parameter for tasks that involve multiple
steps or filling out forms. You can use this context in conjuction
with the
setResultValuemethod to allow scripts to return results to AppScan.
- Enter your JavaScript in the JavaScript field (code-editor) and use Ctrl+Space for auto-complete suggestions within the AppScan environment.
- Click Add to save your script. The script is added to the list and enabled by default.
- You can choose to enable or disable a script from the list of custom scripts using the Enable checkbox.
- Manage your scripts using the Enable checkbox or by
editing, deleting, or reordering them in the script list.

- Click Start full scan to run the scan.
- 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.
// 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.
// 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
- 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.
// 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
// 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") { ... }
// 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.
- 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.
- 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
- 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
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
- 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.
- 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
| 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") {{ ...
}} |
| Member | Type | Description | Example |
|---|---|---|---|
|
(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() |
|
(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") |
|
(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
| 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) { ...
} |
| 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
| Member | Type | Description | Example |
|---|---|---|---|
|
(value: string) |
void | Sets the result value for the current parameter context script. | setResultValue("ABC-" +
Date.now()) |
Common objects
| Member | Type | Description | Example |
|---|---|---|---|
| items | array |
Read only🔒 An array of all headers in the current HTTP request. |
|
| 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. |
|
set(name: string, value: string) |
void | Sets a header in the current HTTP request. If the header already exists, its value is replaced. |
|
|
(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. |
|
Environment Data
| 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() |
| Member | Type | Description | Example |
|---|---|---|---|
|
(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") |
|
(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") |
| 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
| 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")
|