---
title: "Key Objects and Utilities"
description: "Reference guide for HawkScan SDK core classes - HttpMessage, Headers, Authentication helpers, and essential utilities for script development."
url: https://docs.stackhawk.com/scripting/key-objects-scripting/
---

# Key Objects and Utilities

Reference guide for HawkScan SDK core classes - HttpMessage, Headers, Authentication helpers, and essential utilities for script development.

This comprehensive reference covers the core classes, helper objects, and utility imports available in the HawkScan Scripting SDK.

## **HttpMessage**

**Package:** `org.parosproxy.paros.network.HttpMessage`

**Dokka Documentation:** [HttpMessage API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/org.parosproxy.paros.network/-http-message)

The HttpMessage class in the HawkScan SDK encapsulates the details of an HTTP message with sub-classes for interaction with request and response. This class is widely used in scripting and programmatic interaction with HawkScan for tasks such as scanning, analyzing traffic, and interacting with web services.

```java
class HttpMessage {
    HttpRequestHeader requestHeader;
    HttpRequestBody requestBody;
    HttpResponseHeader responseHeader;
    HttpResponseBody responseBody;
    int timeSentMillis;
    int timeElapsedMillis;
    boolean forceIntercept;
}
```

### **Key Methods**

#### **Request Handling**

- **`getRequestHeader(): HttpRequestHeader`**

  - Returns the HTTP request header as an HttpRequestHeader object.
  - Example: Retrieve and modify the User-Agent header.

- **`getRequestBody(): HttpRequestBody`**

  - Returns the HTTP request body as an object.
  - Example: Modify a POST request’s payload.

- **`setRequestHeader(header: HttpRequestHeader)`**
  - Sets the HTTP request header.

- **`setRequestBody(body: HttpRequestBody)`**
  - Sets the HTTP request body.

#### **Response Handling**

- **`getResponseHeader(): HttpResponseHeader`**

  - Returns the HTTP response header.
  - Example: Inspect response status code or headers.

- **`getResponseBody(): HttpResponseBody`**

  - Returns the HTTP response body.
  - Example: Analyze or extract data from the response.

- **`setResponseHeader(header: HttpResponseHeader)`**
  - Sets the HTTP response header.

- **`setResponseBody(body: HttpResponseBody)`**
  - Sets the HTTP response body.

#### **Timing**

- **`getTimeSentMillis(): Int`**
  - Returns the timestamp when the request was sent.
- **`getTimeElapsedMillis(): Int`**
  - Returns the time elapsed between request sent and response received, ie. RTT.

```java
val msg = HttpMessage()

// Set a custom User-Agent
val requestHeader = msg.requestHeader
requestHeader.setHeader("User-Agent", "MyCustomAgent/1.0")
msg.setRequestHeader(requestHeader)

// Set a custom request body for a POST request
val requestBody = msg.requestBody
requestBody.body = """{"key": "value"}""".trimIndent()
msg.setRequestBody(requestBody)

```

```java
val msg = HttpMessage()

// Check the status code of the response
val responseHeader = msg.getResponseHeader()
println("Status Code: ${responseHeader.statusCode}")

// Extract the response body
val responseBody = httpMessage.getResponseBody()
println("Response Body: ${responseBody.body}")
```

```java
val httpMessage = HttpMessage()

// Log request/response timing
val timeSent = httpMessage.getTimeSentMillis()
val timeElapsed = httpMessage.getTimeElapsedMillis()

println("Request sent at: $timeSent ms")
println("Response received in: $timeElapsed ms")
```

## **Headers and Body Management:**

The `HttpRequestHeader`, `HttpRequestBody`, `HttpResponseHeader`, and `HttpResponseBody` objects provide lower-level methods to manipulate headers and body content, and are typically accessed through the higher-level HttpMessage object discussed previously.

#### **1. HttpRequestHeader**

**Package:** `org.parosproxy.paros.network.HttpRequestHeader`

**Dokka Documentation:** [HttpRequestHeader API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/org.parosproxy.paros.network/-http-request-header)

**Represents the HTTP request headers.**

#### **Key Methods**

- **`setHeader(name: String, value: String)`**

  1. Sets or updates the value of a specific header.

  - **`getHeader(name: String): String?`**
    1. Retrieves the value of a specific header.
  - **`getHeaders(): Map&lt;String, String&gt;`**
    1. Returns all headers as a map.
  - **`toString(): String`**
    1. Converts the headers to their string representation for debugging or logging.

**Example in Kotlin**\
Kotlin

```java
val msg = HttpMessage() //often comes from the script contract
val requestHeader = msg.requestHeader //OR
//val requestHeader = msg.getRequestHeader() 

// Set headers
requestHeader.setHeader("User-Agent", "MyCustomAgent/1.0")
requestHeader.setHeader("Accept", "application/json")

// Retrieve a specific header
val userAgent = requestHeader.getHeader("User-Agent")
println("User-Agent: $userAgent")

// Display all headers
val headers = requestHeader.getHeaders()
headers.forEach { (key, value) -> println("$key: $value") }

// Print headers as a string to the HawkScan log.
logger.info(requestHeader.toString())
```

#### **2. HttpRequestBody**

**Package:** `com.stackhawk.hste.network.HttpRequestBody`

**Dokka Documentation:** [HttpRequestBody API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.network/-http-request-body)

**Represents the body of an HTTP request.**

#### **Key Methods**

- **`HttpRequestBody(body: String)`**

  1. Constructs the body object with default `body` if operating on a blank message, such as when writing authentication scripts.

  - **`setBody(body: String))`**
    1. Sets the request body content. Similar to the class constructor.
  - **`getBody(): String`**
    1. Retrieves the content of the request body.
  - **`length(): Int`**
    1. Returns the length of the body content. Essential for calculating the value of the “Content-Length” header when needed for POSTs.

**Example in Kotlin**\
Kotlin

```java
val msg = HttpMessage()
val requestBody = msg.requestBody

// Set request body
requestBody.setBody("{\"key\": \"value\"}")

// Retrieve body content
println("Request Body: ${requestBody.getBody()}")

// Check body length
println("Body Length: ${requestBody.length()}")
```

#### **3. HttpResponseHeader**

**Package:** `org.parosproxy.paros.network.HttpResponseHeader`

**Dokka Documentation:** [HttpResponseHeader API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/org.parosproxy.paros.network/-http-response-header)

**Represents the HTTP response headers.**

#### **Key Methods**

- **`getStatusCode(): Int`**

  1. Returns the HTTP status code from the response.

  - **`getReasonPhrase(): String`**
    1. Returns the reason phrase associated with the status code (e.g., “OK” for 200).
  - **`getHeader(name: String): String?`**
    1. Retrieves the value of a specific header.
  - **`getHeaders(): Map&lt;String, String&gt;`**
    1. Returns all headers as a map.
  - **`toString(): String`**
    1. Converts the headers to their string representation.

**Example in Kotlin**\
Kotlin

```java
val responseHeader = HttpResponseHeader()

// Retrieve status code and reason phrase
println("Status Code: ${responseHeader.getStatusCode()}")
println("Reason Phrase: ${responseHeader.getReasonPhrase()}")

// Retrieve a specific header
val contentType = responseHeader.getHeader("Content-Type")
println("Content-Type: $contentType")

// Display all headers
val headers = responseHeader.getHeaders()
headers.forEach { (key, value) -> println("$key: $value") }

// Print headers as a string
println(responseHeader.toString())
```

#### **4. HttpResponseBody**

**Package:** `com.stackhawk.hste.network.HttpResponseBody`

**Dokka Documentation:** [HttpResponseBody API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.network/-http-response-body)

**Represents the body of an HTTP response.**

#### **Key Methods**

- **`setBody(body: String)`**

  1. Sets the response body content.

  - **`getBody(): String`**
    1. Retrieves the response body content.
  - **`length(): Int`**
    1. Returns the length of the body content.

**Example in Kotlin**\
Kotlin

```java
val responseBody = HttpResponseBody()

// Set response body
responseBody.setBody("<html><body>Hello, World!</body></html>")

// Retrieve response body content
println("Response Body: ${responseBody.getBody()}")

// Check body length
println("Body Length: ${responseBody.length()}")
```

### Additional Notes

2. **Exception Handling**:

   - Always validate input when setting headers or bodies to ensure proper HTTP formatting.
   - Handle `null` values gracefully when retrieving headers that may not exist.

3. **Use Cases**:

   - `HttpRequestHeader` and `HttpRequestBody` are typically used to construct HTTP requests for scanning or interacting with targets.
   - `HttpResponseHeader` and `HttpResponseBody` are primarily used for analyzing responses received from the server.

## **Script-Specific Helper Objects**

### HttpSenderScriptHelper

**Package:** `com.stackhawk.hste.extension.script.HttpSenderScriptHelper`

**Dokka Documentation:** [HttpSenderScriptHelper API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.extension.script/-http-sender-script-helper)

**Used in:** HttpSender scripts (passed as the `helper` parameter)

**Purpose:** Provides utility methods for HttpSender scripts to interact with the HTTP communication layer.

#### Key Methods

**`sendAndReceive(HttpMessage msg)`**

- Sends an HTTP message and waits for the response
- Use this to send additional requests within an HttpSender script
- Example:
  ```kotlin
  val msg = helper.prepareMessage()
  msg.requestHeader = HttpRequestHeader(HttpRequestHeader.GET, URI("https://example.com/api/test", true), HttpHeader.HTTP11)
  helper.sendAndReceive(msg)
  logger.info("Response: ${msg.responseHeader.statusCode}")
  ```

**`getHttpSender(): HttpSender`**

- Returns the underlying HttpSender instance
- Provides access to lower-level HTTP operations
- Advanced usage for custom request handling

**Usage Example:**

```kotlin
import com.stackhawk.hste.extension.script.HttpSenderScriptHelper
import org.parosproxy.paros.network.HttpMessage

fun sendingRequest(msg: HttpMessage, initiator: Int, helper: HttpSenderScriptHelper) {
    // Add custom header before sending
    msg.requestHeader.setHeader("X-Custom-ID", "scan-${System.currentTimeMillis()}")

    // Could send additional requests if needed
    // val testMsg = HttpMessage()
    // helper.sendAndReceive(testMsg)
}

fun responseReceived(msg: HttpMessage, initiator: Int, helper: HttpSenderScriptHelper) {
    // Process response after receiving
    logger.info("Received response with status: ${msg.responseHeader.statusCode}")
}
```

**Reference:** [HttpSender script examples](https://github.com/kaakaww/hawkscan-examples/tree/main/scripts/examples/httpsender)

---

### AuthenticationHelper

**Package:** `com.stackhawk.hste.authentication.AuthenticationHelper`

**Dokka Documentation:** [AuthenticationHelper API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.authentication/-authentication-helper)

**Used in:** Authentication scripts (passed as the `helper` parameter)

**Purpose:** Provides methods for creating and sending HTTP messages during authentication workflows.

#### Key Methods

**`prepareMessage(): HttpMessage`**

- Creates a new, empty HttpMessage ready for configuration
- Use this to build authentication requests from scratch
- Returns an HttpMessage with no headers or body set
- Example:
  ```kotlin
  val msg = helper.prepareMessage()
  msg.requestHeader = HttpRequestHeader(HttpRequestHeader.POST, URI("https://example.com/login", true), HttpHeader.HTTP11)
  msg.requestBody = HttpRequestBody("{\"username\":\"user\",\"password\":\"pass\"}")
  ```

**`sendAndReceive(HttpMessage msg)`**

- Sends the HTTP message to the server and blocks waiting for response
- Populates `msg.responseHeader` and `msg.responseBody` when response arrives
- Handles connection management, timeouts, and retries automatically
- Example:
  ```kotlin
  helper.sendAndReceive(msg)
  logger.info("Authentication response status: ${msg.responseHeader.statusCode}")
  ```

**`sendAndReceive(HttpMessage msg, boolean followRedirects)`**

- Same as above, but with explicit control over redirect handling
- Set `followRedirects` to `false` to prevent automatic 3xx redirect following
- Useful when capturing intermediate responses

#### Usage Example

```kotlin
import com.stackhawk.hste.authentication.AuthenticationHelper
import com.stackhawk.hste.authentication.GenericAuthenticationCredentials
import org.parosproxy.paros.network.HttpMessage
import org.parosproxy.paros.network.HttpRequestHeader
import org.apache.commons.httpclient.URI

fun authenticate(
    helper: AuthenticationHelper,
    paramsValues: Map&lt;String, String&gt;,
    credentials: GenericAuthenticationCredentials
): HttpMessage {

    // Create a new message
    val msg = helper.prepareMessage()

    // Configure the request
    val loginUrl = "${paramsValues["baseUrl"]}/api/v1/login"
    msg.requestHeader = HttpRequestHeader(
        HttpRequestHeader.POST,
        URI(loginUrl, true),
        HttpHeader.HTTP11
    )

    // Add authentication body
    val username = credentials.getParam("username")
    val password = credentials.getParam("password")
    msg.requestBody = HttpRequestBody("{\"username\":\"$username\",\"password\":\"$password\"}")
    msg.requestHeader.setHeader("Content-Type", "application/json")
    msg.requestHeader.contentLength = msg.requestBody.length()

    // Send and receive
    helper.sendAndReceive(msg)

    logger.info("Authentication complete: ${msg.responseHeader.statusCode}")

    // Return the message (HawkScan extracts cookies/tokens automatically)
    return msg
}
```

**Reference:** [Authentication script examples](https://github.com/kaakaww/hawkscan-examples/tree/main/scripts/examples/authentication)

---

### SessionWrapper

**Package:** `com.stackhawk.hste.session.ScriptBasedSessionManagementMethodType.SessionWrapper`

**Dokka Documentation:** [SessionWrapper API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.session/-script-based-session-management-method-type/-session-wrapper)

**Used in:** Session management scripts (passed as the `sessionWrapper` parameter)

**Purpose:** Encapsulates session state and provides access to HTTP messages, session storage, and configuration parameters.

#### Key Properties and Methods

**`.httpMessage` or `.getHttpMessage(): HttpMessage`**

- In `extractWebSession`: Contains the final authentication response message

  - `responseBody` has the JSON/HTML response from authentication
  - `responseHeader` may contain Set-Cookie directives
  - `requestingUser` provides access to the user context

- In `processMessageToMatchSession`: Contains the current outbound request being prepared

  - `requestHeader` is populated and ready for modification
  - `responseHeader/responseBody` are empty (not yet sent)

**`.session` or `.getSession(): WebSession`**

- Provides access to session storage and HTTP state

- **Methods:**

  - `setValue(String key, Any value)` - Store values in session

  - `getValue(String key): Any?` - Retrieve stored values

  - `.httpState: HttpState` - Cookie jar for automatic cookie management

    - `addCookie(Cookie cookie)` - Add cookie to jar
    - `clearCookies()` - Remove all cookies
    - `.cookies: Array&lt;Cookie&gt;` - Access current cookies

**`.getParam(String key): String?`** or **`.paramValues[key]`**

- Retrieves configuration parameters from `stackhawk.yml`
- Parameters come from the `hawkAddOn.scripts.vars` section
- Returns `null` if parameter not found (check optional vs required params)

#### Usage Example

```kotlin
import com.stackhawk.hste.session.ScriptBasedSessionManagementMethodType
import com.fasterxml.jackson.databind.ObjectMapper
import com.nimbusds.jwt.SignedJWT

val mapper = ObjectMapper()

fun extractWebSession(sessionWrapper: ScriptBasedSessionManagementMethodType.SessionWrapper) {
    // Get configuration parameter
    val tokenField = sessionWrapper.getParam("jwt_token_field") ?: "access_token"

    // Parse the authentication response
    val responseBody = sessionWrapper.httpMessage.responseBody.toString()
    val jsonObject = mapper.readTree(responseBody)
    val token = jsonObject.get(tokenField).asText()

    // Store token in session
    sessionWrapper.session.setValue("jwt_token", token)

    // Parse JWT claims for expiration
    val jwt = SignedJWT.parse(token)
    sessionWrapper.session.setValue("jwt_expires", jwt.jwtClaimsSet.expirationTime.time)

    logger.info("Extracted JWT token, expires: ${jwt.jwtClaimsSet.expirationTime}")
}

fun processMessageToMatchSession(sessionWrapper: ScriptBasedSessionManagementMethodType.SessionWrapper) {
    // Check token expiration
    val expiresAt = sessionWrapper.session.getValue("jwt_expires") as? Long
    if (expiresAt != null && System.currentTimeMillis() > expiresAt) {
        logger.warn("Token expired, re-authenticating")
        synchronized(this) {
            sessionWrapper.httpMessage.requestingUser.authenticate()
        }
        return
    }

    // Inject Authorization header
    val token = sessionWrapper.session.getValue("jwt_token") as? String
    if (token != null) {
        sessionWrapper.httpMessage.requestHeader.setHeader("Authorization", "Bearer $token")
    }
}

fun clearWebSessionIdentifiers(sessionWrapper: ScriptBasedSessionManagementMethodType.SessionWrapper) {
    sessionWrapper.session.setValue("jwt_token", null)
    sessionWrapper.session.setValue("jwt_expires", null)
    sessionWrapper.session.httpState.clearCookies()
}
```

**Reference:** [Session script examples](https://github.com/kaakaww/hawkscan-examples/tree/main/scripts/examples/session)

---

### ScriptsActiveScanner

**Package:** `com.stackhawk.hste.extension.scripts.scanrules.ScriptsActiveScanner`

**Used in:** Active scanning scripts (passed as the `activeScanner` parameter)

**Purpose:** Provides methods for active vulnerability testing including request modification, sending requests, and raising alerts.

#### Key Methods

**`setParam(HttpMessage msg, String param, String value)`**

- Modifies a parameter value in the HTTP message

- Intelligently handles different parameter types:

  - URL query parameters: `?userId=123`
  - POST form data: `userId=123`
  - JSON body fields: `{"userId": "123"}`
  - XML elements (with appropriate parsing)

- Example:
  ```kotlin
  val msg = origMessage.cloneRequest()
  activeScanner.setParam(msg, "userId", "admin")
  ```

**`sendAndReceive(HttpMessage msg, boolean followRedirects, boolean handleAntiCSRF)`**

- Sends the modified request and waits for response
- `followRedirects` - Whether to automatically follow 3xx redirects (usually `false`)
- `handleAntiCSRF` - Whether to process anti-CSRF tokens (usually `false`)
- Example:
  ```kotlin
  activeScanner.sendAndReceive(msg, false, false)
  if (msg.responseHeader.statusCode >= 500) {
      // Found a vulnerability
  }
  ```

**`newAlert(): AlertBuilder`**

- Returns a builder for constructing vulnerability alerts

- **Required methods:**

  - `.setPluginId(int id)` - Unique ID for the custom rule
  - `.setRisk(int risk)` - 0=info, 1=low, 2=medium, 3=high
  - `.setConfidence(int confidence)` - 0=false positive, 1=low, 2=medium, 3=high, 4=confirmed
  - `.setName(String title)` - Alert title
  - `.setMessage(HttpMessage msg)` - The request/response that triggered the alert
  - `.raise()` - Submit the alert

- **Recommended methods:**

  - `.setDescription(String desc)` - Detailed explanation
  - `.setEvidence(String evidence)` - Proof of vulnerability
  - `.setSolution(String solution)` - How to fix
  - `.setReference(String reference)` - Links to documentation
  - `.setOtherInfo(String info)` - Additional context
  - `.setCweId(int cwe)` - CWE classification
  - `.setWascId(int wasc)` - WASC classification

**`getBaseMsg(): HttpMessage`**

- Returns the base message for the current scan
- Useful for accessing original request context

#### Usage Example

```kotlin
import com.stackhawk.hste.extension.scripts.scanrules.ScriptsActiveScanner
import org.parosproxy.paros.network.HttpMessage

fun scan(activeScanner: ScriptsActiveScanner, origMessage: HttpMessage, param: String, value: String) {
    // Test with SQL injection payload
    val payload = "' OR '1'='1"
    val msg = origMessage.cloneRequest()

    // Modify parameter
    activeScanner.setParam(msg, param, payload)

    // Send request
    activeScanner.sendAndReceive(msg, false, false)

    // Check for SQL error indicators
    val responseBody = msg.responseBody.toString()
    if (responseBody.contains("SQL syntax", ignoreCase = true) ||
        responseBody.contains("SQLException", ignoreCase = true)) {

        // Raise alert
        activeScanner.newAlert()
            .setPluginId(1000001)
            .setRisk(3) // High risk
            .setConfidence(4) // Confirmed
            .setName("SQL Injection Detected")
            .setDescription("The application appears vulnerable to SQL injection in parameter '$param'")
            .setEvidence("SQL error in response: ${responseBody.substring(0, 200)}")
            .setSolution("Use parameterized queries or prepared statements")
            .setReference("https://owasp.org/www-community/attacks/SQL_Injection")
            .setOtherInfo("Payload: $payload")
            .setMessage(msg)
            .raise()

        logger.warn("SQL injection found in parameter: $param")
    }
}
```

**Important Notes:**

- Both `risk` and `confidence` must be > 0, or the alert will not be included in results
- Always call `.setMessage(msg)` to associate the alert with the HTTP request/response
- Use unique plugin IDs (1000000+) to avoid conflicts with built-in rules

**Reference:** [Active script examples](https://github.com/kaakaww/hawkscan-examples/tree/main/scripts/examples/active)

---

### ScriptsPassiveScanner

**Package:** `com.stackhawk.hste.extension.scripts.scanrules.ScriptsPassiveScanner`

**Used in:** Passive scanning scripts (passed as the `ps` parameter)

**Purpose:** Provides methods for analyzing HTTP traffic without sending additional requests, and raising alerts for detected issues.

#### Key Methods

**`newAlert(): AlertBuilder`**

- Returns a builder for constructing vulnerability alerts (same interface as ScriptsActiveScanner)

- **Required methods:**

  - `.setPluginId(int id)` - Unique ID for the custom rule
  - `.setRisk(int risk)` - 0=info, 1=low, 2=medium, 3=high
  - `.setConfidence(int confidence)` - 0=false positive, 1=low, 2=medium, 3=high, 4=confirmed
  - `.setName(String title)` - Alert title
  - `.setMessage(HttpMessage msg)` - The message being analyzed
  - `.raise()` - Submit the alert

- **Recommended methods:**

  - `.setDescription(String desc)` - What was found
  - `.setEvidence(String evidence)` - The sensitive data or issue found
  - `.setSolution(String solution)` - Remediation guidance
  - `.setReference(String reference)` - Links to standards/docs
  - `.setParam(String param)` - Parameter where issue was found
  - `.setCweId(int cwe)` - CWE classification
  - `.setWascId(int wasc)` - WASC classification

**`addHistoryTag(String tag)`**

- Adds a tag to the current HTTP message in the history
- Useful for marking messages that match certain criteria
- Tags appear in HawkScan’s history view for manual review
- Example:
  ```kotlin
  ps.addHistoryTag("sensitive-data-found")
  ```

**`getAlertThreshold(): Plugin.AlertThreshold`**

- Returns the current alert threshold setting (LOW, MEDIUM, HIGH)
- Use this to adjust detection sensitivity based on scan configuration
- Example:
  ```kotlin
  if (ps.getAlertThreshold() == Plugin.AlertThreshold.LOW) {
      // Raise alerts with lower confidence when in LOW threshold mode
  }
  ```

**`getDefaultHistoryTypes(): List&lt;Int&gt;`**

- Returns the list of default history types that passive scanners should process
- Typically includes: TYPE_PROXIED, TYPE_SPIDER, TYPE_ZAP_USER, TYPE_AJAX_SPIDER
- Use in `appliesToHistoryType()` function

#### Usage Example

```kotlin
import com.stackhawk.hste.extension.scripts.scanrules.ScriptsPassiveScanner
import org.parosproxy.paros.network.HttpMessage
import net.htmlparser.jericho.Source

val PLUGIN_ID = 1000050
val emailPattern = Regex("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")

fun scan(ps: ScriptsPassiveScanner, msg: HttpMessage, src: Source) {
    // Check content type to avoid scanning images/PDFs
    val contentType = msg.responseHeader.getHeader("Content-Type") ?: ""
    if (contentType.contains("image/") || contentType.contains("application/pdf")) {
        return
    }

    // Search for email addresses in response body
    val body = msg.responseBody.toString()
    val emails = emailPattern.findAll(body)

    if (emails.any()) {
        // Add tag for manual review
        ps.addHistoryTag("email-disclosure")

        // Collect all found emails
        val foundEmails = emails.map { it.value }.distinct().toList()

        // Raise alert
        ps.newAlert()
            .setPluginId(PLUGIN_ID)
            .setRisk(1) // Low risk
            .setConfidence(3) // High confidence
            .setName("Email Address Disclosure")
            .setDescription("Email addresses were found in the response body. This may represent " +
                          "PII disclosure and could be used for phishing or social engineering attacks.")
            .setEvidence(foundEmails.first()) // Show first email as evidence
            .setOtherInfo("Found ${foundEmails.size} email address(es):\n${foundEmails.joinToString("\n")}")
            .setSolution("Avoid exposing email addresses in responses. Use user IDs or anonymized " +
                        "identifiers instead. If email display is necessary, implement proper access controls.")
            .setReference("https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url")
            .setCweId(200) // CWE-200: Exposure of Sensitive Information
            .setMessage(msg)
            .raise()

        logger.info("Found ${foundEmails.size} email addresses in ${msg.requestHeader.uri}")
    }
}

fun appliesToHistoryType(historyType: Int): Boolean {
    // Use default history types (spider, proxy, ajax spider, etc.)
    return ScriptsPassiveScanner.getDefaultHistoryTypes().contains(historyType)
}
```

**Important Notes:**

- Passive scripts should **never** send additional HTTP requests
- Both `risk` and `confidence` must be > 0 for alerts to appear in results
- Use regex patterns efficiently to avoid performance issues on large responses
- Filter unwanted content types (images, PDFs) early to improve performance

**Reference:** [Passive script examples](https://github.com/kaakaww/hawkscan-examples/tree/main/scripts/examples/passive)

---

## **Additional Utility Classes**

### ScriptVars

**Package:** `com.stackhawk.hste.extension.script.ScriptVars`

**Dokka Documentation:** [ScriptVars API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.extension.script/-script-vars)

**Purpose:** Provides access to script configuration variables and global variable storage across script types.

#### Key Methods

**`getScriptVars(String scriptName): Map&lt;String, String&gt;`**

- Returns a map of variables configured for a specific script
- Variables come from `hawkAddOn.scripts.vars` in `stackhawk.yml`
- Example:
  ```kotlin
  val vars = ScriptVars.getScriptVars("fuzzer.kts")
  val iterations = vars["iterations"]?.toInt() ?: 10
  ```

**`setGlobalVar(String key, String value)`**

- Sets a global variable accessible across all script types
- Useful for passing data between authentication, session, and httpsender scripts
- Example:
  ```kotlin
  ScriptVars.setGlobalVar("auth_token", "Bearer $token")
  ```

**`getGlobalVar(String key): String?`**

- Retrieves a global variable value
- Returns `null` if variable not set
- Example:
  ```kotlin
  val authHeader = ScriptVars.getGlobalVar("auth_token")
  if (authHeader != null) {
      msg.requestHeader.setHeader("Authorization", authHeader)
  }
  ```

### Cookie

**Package:** `org.apache.commons.httpclient.Cookie`

**Purpose:** Represents an HTTP cookie for session management.

#### Constructor

```kotlin
Cookie(
    domain: String,      // Cookie domain (e.g., "example.com")
    name: String,        // Cookie name (e.g., "JSESSIONID")
    value: String,       // Cookie value
    path: String,        // Cookie path (usually "/")
    expires: Date?,      // Expiration date (null = session cookie)
    secure: Boolean      // Whether cookie requires HTTPS
)
```

#### Usage Example

```kotlin
import org.apache.commons.httpclient.Cookie

val cookie = Cookie(
    "example.com",           // domain
    "JSESSIONID",            // name
    "abc123xyz",             // value
    "/",                     // path
    null,                    // expires (session cookie)
    false                    // secure
)

sessionWrapper.session.httpState.addCookie(cookie)
```

## **Additional High-Value Imports**

### **Apache Commons HttpClient**

#### **URI**

**Package:** `org.apache.commons.httpclient.URI`

**Purpose:** Represents a Uniform Resource Identifier (URI) reference for constructing and parsing HTTP URLs.

**Common Usage:**

```kotlin
import org.apache.commons.httpclient.URI

val uri = URI("https://api.example.com/v1/users", true)
msg.requestHeader = HttpRequestHeader(HttpRequestHeader.GET, uri, HttpHeader.HTTP11)
```

**Use Cases:**

- Constructing HTTP request URIs programmatically
- Parsing and manipulating URL components
- Building authentication request URLs

#### **Cookie**

**Package:** `org.apache.commons.httpclient.Cookie`

**Purpose:** Represents an HTTP cookie for session management.

**Constructor:**

```kotlin
Cookie(
    domain: String,      // Cookie domain (e.g., "example.com")
    name: String,        // Cookie name (e.g., "JSESSIONID")
    value: String,       // Cookie value
    path: String,        // Cookie path (usually "/")
    expires: Date?,      // Expiration date (null = session cookie)
    secure: Boolean      // Whether cookie requires HTTPS
)
```

**Common Usage:**

```kotlin
import org.apache.commons.httpclient.Cookie

val cookie = Cookie("example.com", "JSESSIONID", "abc123", "/", null, false)
sessionWrapper.session.httpState.addCookie(cookie)
```

**Use Cases:**

- Session management scripts
- Manual cookie injection
- External authentication integration

### **Apache Commons Codec**

#### **DigestUtils**

**Package:** `org.apache.commons.codec.digest.DigestUtils`

**Purpose:** Utility class for creating message digests (hashing) including SHA-256, MD5, etc.

**Common Usage:**

```kotlin
import org.apache.commons.codec.digest.DigestUtils

// SHA-256 hash
val hash = DigestUtils.sha256Hex("content to hash")

// MD5 hash
val md5 = DigestUtils.md5Hex("content")
```

**Use Cases:**

- AWS SigV4 request signing
- Content integrity verification
- Custom authentication schemes requiring hashing

#### **HmacUtils**

**Package:** `org.apache.commons.codec.digest.HmacUtils`

**Purpose:** Utility class for HMAC (Hash-based Message Authentication Code) operations.

**Common Usage:**

```kotlin
import org.apache.commons.codec.digest.HmacUtils
import org.apache.commons.codec.digest.HmacAlgorithms

val hmac = HmacUtils(HmacAlgorithms.HMAC_SHA_256, secretKey.toByteArray())
val signature = hmac.hmacHex("data to sign")
```

**Use Cases:**

- API request signing (AWS, Azure, custom APIs)
- JWT signature verification
- HMAC-based authentication

### **Jackson JSON Processing**

#### **ObjectMapper**

**Package:** `com.fasterxml.jackson.databind.ObjectMapper`

**Purpose:** Main class for JSON serialization and deserialization.

**Common Usage:**

```kotlin
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode

val mapper = ObjectMapper()

// Parse JSON response
val jsonObject = mapper.readValue(responseBody, ObjectNode::class.java)
val accessToken = jsonObject.get("access_token").asText()

// Create JSON request
val requestJson = mapper.createObjectNode()
requestJson.put("username", "user")
requestJson.put("password", "pass")
val jsonString = mapper.writeValueAsString(requestJson)
```

**Use Cases:**

- Parsing authentication responses for JWT tokens
- Creating JSON request bodies
- Extracting data from JSON responses

### **Nimbus JWT**

#### **SignedJWT**

**Package:** `com.nimbusds.jwt.SignedJWT`

**Purpose:** Parses and validates JSON Web Tokens (JWT).

**Common Usage:**

```kotlin
import com.nimbusds.jwt.SignedJWT
import com.nimbusds.jwt.JWTClaimsSet

// Parse JWT
val jwt = SignedJWT.parse(tokenString)

// Extract claims
val claims: JWTClaimsSet = jwt.jwtClaimsSet
val expirationTime = claims.expirationTime
val subject = claims.subject
val issuer = claims.issuer

// Check expiration
val isExpired = expirationTime.before(Date())
```

**Use Cases:**

- JWT token management in session scripts
- Token expiration detection
- Extracting user information from tokens
- Token validation

### **Jericho HTML Parser**

#### **Source**

**Package:** `net.htmlparser.jericho.Source`

**Purpose:** Parses and analyzes HTML content for passive scanning.

**Common Usage:**

```kotlin
import net.htmlparser.jericho.Source
import net.htmlparser.jericho.HTMLElementName

val src = Source(msg.responseBody.toString())

// Find all script tags
val scriptTags = src.getAllElements(HTMLElementName.SCRIPT)
scriptTags.forEach { scriptTag ->
    val scriptContent = scriptTag.content?.toString() ?: ""
    // Analyze script content
}

// Find all forms
val forms = src.getAllElements(HTMLElementName.FORM)
forms.forEach { form ->
    val action = form.getAttributeValue("action")
    val method = form.getAttributeValue("method")
}

// Extract all links
val links = src.getAllElements(HTMLElementName.A)
links.forEach { link ->
    val href = link.getAttributeValue("href")
}
```

**Use Cases:**

- Passive scanning for hardcoded secrets in JavaScript
- Form analysis
- Link extraction
- HTML structure validation

### **Java Standard Library Utilities**

#### **URLEncoder / URLDecoder**

**Package:** `java.net.URLEncoder`, `java.net.URLDecoder`

**Purpose:** Encodes and decodes URL components.

**Common Usage:**

```kotlin
import java.net.URLEncoder
import java.net.URLDecoder
import java.nio.charset.StandardCharsets

// Encode parameter for URL
val encoded = URLEncoder.encode("value with spaces", StandardCharsets.UTF_8.toString())

// Decode URL parameter
val decoded = URLDecoder.decode("value%20with%20spaces", StandardCharsets.UTF_8.toString())
```

**Use Cases:**

- Building query strings
- Encoding authentication parameters
- Decoding URL-encoded data

#### **UUID**

**Package:** `java.util.UUID`

**Purpose:** Generates universally unique identifiers.

**Common Usage:**

```kotlin
import java.util.UUID

// Generate random UUID
val correlationId = UUID.randomUUID().toString()
msg.requestHeader.setHeader("X-Correlation-ID", correlationId)
```

**Use Cases:**

- Request correlation IDs
- Unique identifiers for testing
- Transaction tracking

### **Date and Time**

#### **SimpleDateFormat**

**Package:** `java.text.SimpleDateFormat`

**Purpose:** Formats and parses dates.

**Common Usage:**

```kotlin
import java.text.SimpleDateFormat
import java.util.Date
import java.util.TimeZone

val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
dateFormat.timeZone = TimeZone.getTimeZone("UTC")
val timestamp = dateFormat.format(Date())
```

**Use Cases:**

- AWS SigV4 timestamp generation
- Custom authentication timestamp headers
- Log timestamp formatting

#### **Instant / Duration (Java 8+)**

**Package:** `java.time.Instant`, `java.time.Duration`

**Purpose:** Modern date-time handling with timezone awareness.

**Common Usage:**

```kotlin
import java.time.Instant
import java.time.Duration

// Current time
val now = Instant.now()

// Add/subtract time
val later = now.plus(Duration.ofHours(1))
val earlier = now.minus(Duration.ofMinutes(15))

// Compare times
val isExpired = tokenExpiry.isBefore(now)

// Calculate duration
val elapsed = Duration.between(startTime, endTime)
```

**Use Cases:**

- JWT token expiration handling
- Timestamp comparisons
- Rate limiting calculations

### **Logging**

#### **LogManager / Logger**

**Package:** `org.apache.log4j.LogManager`, `org.apache.log4j.Logger`

**Purpose:** Logging framework for debugging and monitoring scripts.

**Common Usage:**

```kotlin
import org.apache.log4j.LogManager

val logger = LogManager.getLogger("script-name")

logger.debug("Detailed debug information")
logger.info("General information")
logger.warn("Warning message")
logger.error("Error message", exception)
```

**Log Levels:**

- **DEBUG**: Detailed diagnostic information
- **INFO**: General informational messages
- **WARN**: Warning messages for potentially harmful situations
- **ERROR**: Error events that might still allow the application to continue

**Use Cases:**

- Script debugging
- Authentication flow tracking
- Performance monitoring
- Error diagnosis

### **Selenium WebDriver (for Browser-Based Authentication)**

#### **WebDriver / ChromeDriver / FirefoxDriver**

**Packages:**

- `org.openqa.selenium.WebDriver`
- `org.openqa.selenium.chrome.ChromeDriver`
- `org.openqa.selenium.firefox.FirefoxDriver`

**Purpose:** Automates browser interactions for complex authentication flows.

**Common Usage:**

```kotlin
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.By
import org.openqa.selenium.support.ui.WebDriverWait
import org.openqa.selenium.support.ui.ExpectedConditions

val options = ChromeOptions()
options.addArguments("--headless")  // Run without GUI
val driver = ChromeDriver(options)

try {
    driver.get("https://example.com/login")
    
    // Fill form
    driver.findElement(By.id("username")).sendKeys("user")
    driver.findElement(By.id("password")).sendKeys("pass")
    driver.findElement(By.id("submit")).click()
    
    // Wait for element
    val wait = WebDriverWait(driver, 10)
    wait.until(ExpectedConditions.presenceOfElementLocated(By.id("dashboard")))
    
    // Extract cookies
    val cookies = driver.manage().cookies
    cookies.forEach { cookie ->
        // Add to session
    }
} finally {
    driver.quit()
}
```

**Use Cases:**

- OAuth flows requiring browser interaction
- Multi-factor authentication
- CAPTCHA handling (with additional tools)
- JavaScript-heavy authentication

### **JavaFaker (for Test Data Generation)**

**Package:** `com.github.javafaker.Faker`

**Purpose:** Generates realistic fake data for fuzzing and testing.

**Common Usage:**

```kotlin
import com.github.javafaker.Faker

val faker = Faker()

// Generate random data
val name = faker.name().fullName()
val email = faker.internet().emailAddress()
val phone = faker.phoneNumber().cellPhone()
val address = faker.address().fullAddress()
val uuid = faker.internet().uuid()

// Generate random strings
val randomString = faker.lorem().characters(10, 100)

// Fun data generators
val spell = faker.harryPotter().spell()
val quote = faker.gameOfThrones().quote()
```

**Use Cases:**

- Active scan fuzzing payloads
- Dynamic test data generation
- Parameter value randomization
- Boundary value testing

## **Complete Import Reference**

### **Essential Imports for Each Script Type**

#### **Authentication Scripts**

```kotlin
import com.stackhawk.hste.authentication.AuthenticationHelper
import com.stackhawk.hste.authentication.GenericAuthenticationCredentials
import org.parosproxy.paros.network.HttpMessage
import org.parosproxy.paros.network.HttpRequestHeader
import org.parosproxy.paros.network.HttpHeader
import org.apache.commons.httpclient.URI
import com.stackhawk.hste.network.HttpRequestBody
import org.apache.log4j.LogManager
import com.fasterxml.jackson.databind.ObjectMapper
```

#### **Session Management Scripts**

```kotlin
import com.stackhawk.hste.session.ScriptBasedSessionManagementMethodType
import com.stackhawk.hste.extension.script.ScriptVars
import org.parosproxy.paros.network.HttpMessage
import org.apache.commons.httpclient.Cookie
import com.nimbusds.jwt.SignedJWT
import com.nimbusds.jwt.JWTClaimsSet
import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.log4j.LogManager
```

#### **HttpSender Scripts**

```kotlin
import com.stackhawk.hste.extension.script.HttpSenderScriptHelper
import com.stackhawk.hste.extension.script.ScriptVars
import org.parosproxy.paros.network.HttpMessage
import org.parosproxy.paros.network.HttpSender
import org.apache.log4j.LogManager
```

#### **Active Scanning Scripts**

```kotlin
import com.stackhawk.hste.extension.scripts.scanrules.ScriptsActiveScanner
import org.parosproxy.paros.network.HttpMessage
import com.stackhawk.hste.extension.script.ScriptVars
import com.github.javafaker.Faker
import org.apache.log4j.LogManager
```

#### **Passive Scanning Scripts**

```kotlin
import com.stackhawk.hste.extension.scripts.scanrules.ScriptsPassiveScanner
import org.parosproxy.paros.network.HttpMessage
import net.htmlparser.jericho.Source
import net.htmlparser.jericho.HTMLElementName
import org.parosproxy.paros.core.scanner.Plugin
import org.apache.log4j.LogManager
import kotlin.text.Regex
```

## **SDK Documentation Index**

For complete API documentation, refer to the HawkScript SDK documentation:

**Base Path:** [HawkScript SDK API Reference](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k)

**Key Package Documentation:**

- [com.stackhawk.hste.authentication](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.authentication) - Authentication classes and helpers
- [com.stackhawk.hste.session](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.session) - Session management classes
- [com.stackhawk.hste.extension.script](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.extension.script) - Script helper classes
- [com.stackhawk.hste.network](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/com.stackhawk.hste.network) - Network and HTTP utilities
- [org.parosproxy.paros.network](https://github.com/kaakaww/hawkscript-docs/tree/main/hawkscript-sdk-4.7.1/-hawk-script-s-d-k/org.parosproxy.paros.network) - Core HTTP message classes
