--- url: /app/tutorials/add_header.md description: >- Learn how to create a passive workflow that automatically adds custom headers to in-scope requests and resends them in Caido. --- # Add a Header Workflow In this tutorial, we will create a passive workflow that will add a header to an in-scope request and resend the request with it. ## Creating a Passive Workflow To begin, navigate to the Workflows interface, select the `Passive` tab, and **click** the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections Too add nodes to the workflow, **click** on `+ Add Node` button and then the `+ Add` button of a specific node. For this workflow, the overall node layout will be: ::: tip Passive workflows do not require `Passive End` nodes in order to exit execution properly. ::: * The `On Intercept Request` node outputs `$on_intercept_request.request` objects which represent proxied requests. * The `In Scope` node checks if the value of a request's Host header is included in the in-scope list of a scope preset. If it is not - the workflow will end. * In-scope requests will be passed to the `Javascript` node. * Once a request has been processed by the script in the `Javascript` node, the workflow will end. ## Adding a Header to a Request 1. **Click** on the `Javascript` node to access its editor. 2. Then, **click** within the coding environment, select all of the existing code, and replace it with the following script: ```js /** * @param {HttpInput} input * @param {SDK} sdk * @returns {MaybePromise} */ export async function run({ request, response }, sdk) { if (request) { const spec = request.toSpec(); spec.setHeader("Header-Name", "header-value"); let resend = await sdk.requests.send(spec); if (resend.response) { let finding = { title: `Custom Header Passive Workflow.`, description: `Request ${resend.request.getId()} ${resend.request.getMethod()} ${resend.request.getPath()} to ${resend.request.getHost()} was resent with custom header.`, reporter: "Add Header & Resend Request", request: resend.request }; await sdk.findings.create(finding); } } } ``` 3. Next, ensure the `$on_intercept_request.request` object is [referenced as input data](/app/guides/workflows_references.md). Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ## Script Breakdown First, an asynchronous function is defined that takes a proxied `request` and `response` object pair and the `sdk` interface object as parameters. The script will execute every time an in-scope request object is passed from the `In Scope` node. ```js export async function run({ request, response }, sdk) { if (request) { ``` As request objects are initially immutable, the `.toSpec()` method is used to make a copy of the request object so modifications can be made. The mutable request is stored in the `spec` variable. ```js const spec = request.toSpec(); ``` Next, the `.setHeader("Header-Name", "header-value")` method is used to add a header to the copy of the request object. ```js spec.setHeader("Header-Name", "header-value"); ``` Then, `sdk.requests.send(spec)` is used to send the modified request. Since we must wait for the request to be sent and response to be returned, the `await` directive is used. The request and its corresponding response are stored in the `resend` variable. ```js let resend = await sdk.requests.send(spec); ``` If a response is returned, a `finding` object is created. The `request` property is the request that includes our custom header. ```js if (resend.response) { let finding = { title: `Custom Header Passive Workflow.`, description: `Request ${resend.request.getId()} ${resend.request.getMethod()} ${resend.request.getPath()} to ${resend.request.getHost()} was resent with custom header.`, reporter: "Add Header & Resend Request", request: resend.request }; ``` Finally, the creation of the finding is awaited to give it time to be processed on the backend. ```js await sdk.findings.create(finding); } } } ``` ## Testing the Workflow To test the workflow: 1. Type in an in-scope domain in the connection URL input field. 2. Ensure the domain is also the value of the request's Host header. 3) Next, **click** on the `Run` button. A message will appear notifying you that the workflow executed successfully. ## The Result The generated finding should resemble: The full workflow is provided below, ready to be imported. ```json { "description": "Adds a header to a proxied request.", "edition": 2, "graph": { "edges": [ { "source": { "exec_alias": "exec", "node_id": 0 }, "target": { "exec_alias": "exec", "node_id": 2 } }, { "source": { "exec_alias": "true", "node_id": 2 }, "target": { "exec_alias": "exec", "node_id": 3 } }, { "source": { "exec_alias": "false", "node_id": 2 }, "target": { "exec_alias": "exec", "node_id": 1 } }, { "source": { "exec_alias": "exec", "node_id": 3 }, "target": { "exec_alias": "exec", "node_id": 4 } } ], "nodes": [ { "alias": "on_intercept_request", "definition_id": "caido/on-intercept-request", "display": { "x": -210, "y": -20 }, "id": 0, "inputs": [], "name": "On intercept request", "version": "0.1.0" }, { "alias": "passive_end", "definition_id": "caido/passive-end", "display": { "x": 210, "y": 70 }, "id": 1, "inputs": [], "name": "Passive End", "version": "0.1.0" }, { "alias": "in_scope", "definition_id": "caido/in-scope", "display": { "x": 0, "y": -10 }, "id": 2, "inputs": [ { "alias": "request", "value": { "data": "$on_intercept_request.request", "kind": "ref" } } ], "name": "In Scope", "version": "0.1.0" }, { "alias": "javascript", "definition_id": "caido/http-code-js", "display": { "x": 210, "y": -90 }, "id": 3, "inputs": [ { "alias": "request", "value": { "data": "$on_intercept_request.request", "kind": "ref" } }, { "alias": "code", "value": { "data": "/**\n * @param {HttpInput} input\n * @param {SDK} sdk\n * @returns {MaybePromise}\n */\nexport async function run({ request, response }, sdk) {\n if (request) { \n const spec = request.toSpec();\n spec.setHeader(\"Header-Name\", \"header-value\");\n\n let resend = await sdk.requests.send(spec);\n \n if (resend.response) {\n let finding = {\n title: `Custom Header Passive Workflow.`,\n description: `Request ${resend.request.getId()} ${resend.request.getMethod()} ${resend.request.getPath()} to ${resend.request.getHost()} was resent with custom header.`,\n reporter: \"Add Header & Resend Request\",\n request: resend.request\n };\n await sdk.findings.create(finding);\n }\n }\n}", "kind": "string" } } ], "name": "Javascript", "version": "0.1.0" }, { "alias": "passive_end_1", "definition_id": "caido/passive-end", "display": { "x": 420, "y": -90 }, "id": 4, "inputs": [], "name": "Passive End 1", "version": "0.1.0" } ] }, "id": "eb670e67-9752-4324-9fb8-1aa529e7e9da", "kind": "passive", "name": "Add Header" } ``` --- --- url: /app/guides/match_replace_header.md description: >- A step-by-step guide to adding custom headers to HTTP requests and responses in Caido's Match & Replace feature for traffic modification. --- # Adding a Header To add an additional header to either HTTP requests or responses, **click** on the `Section` drop-down menu and select either `Request Header` or `Response Header`. Next, **click** on the `Add` button and type the header key name and its value in the associated input fields. Select the traffic source/s and **click** on the `+ Add` button to add the rule to the Default Collection. ::: tip Give rules descriptive names for quick identification of their purpose. ::: To enable the rule, **click** on its associated checkbox. Applied rules will be listed in the `Active Rules` table. --- --- url: /app/guides/ai.md description: A guide to adding AI provider API keys in Caido. --- # Adding AI Provider API Keys In addition to the [Assistant](/app/guides/assistant_model.md), Caido supports the following major AI providers: * Anthropic * Google * OpenAI * OpenRouter ::: tip To configure other AI providers, view the [LiteLLM](/app/tutorials/litellm.md) tutorial. ::: To set an API key for one of these providers, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `AI` tab. --- --- url: /app/tutorials/android_add_certificate.md description: >- Learn how to add Caido's CA certificate to the system-store of a virtual Android device. --- # Adding Caido's CA Certificate to the System Partition In this tutorial, we will cover the process of adding Caido's CA certificate to the system-store of a virtual Android device. ::: warning NOTE This tutorial is a continuation of [Setup & Configuration](/app/tutorials/android_virtual_device.md) and [Proxying Browser Traffic](/app/tutorials/android_browser_virtual.md). Ensure you have completed the previous steps before proceeding. ::: ## Renaming Caido's CA Certificate In order for Caido's CA certificate to be compatible with the Android system, it will need to meet the expected naming format. The format is the legacy hash of a CA certificate's subject field with a `.0` extension. To generate the correct certificate file name: 1. Navigate to `http://127.0.0.1:8080/ca.crt` in a browser on your computer to download Caido's CA certificate. 2. Open a terminal and navigate to the file system location of the certificate and enter the following command: ```bash openssl x509 -inform PEM -subject_hash_old -in ca.crt ``` 3. Rename the certificate to the returned hash (*located between the command and `-----BEGIN CERTIFICATE-----`*) with a `.0` extension. ## Adding the Certificate ::: warning NOTE This method will only work for virtual devices with an Android API level <= 33. ::: To add the certificate to the system level certificate storage of the device: 1. In the **Projects** interface of the Android Studio window, **click** on the More Actions button and select `SDK Manager`. 2) Select `Android SDK` from the **Languages & Frameworks** drop-down menu. 3) Add the `emulator` directory (*a subdirectory of the file system location stated in the `Android SDK Location` field*) to your system's PATH environment variable 4. Open a terminal and execute the **emulator** tool with `-list-avds` to ensure the device is listed. ```bash emulator -list-avds ``` 5. Execute the **emulator** tool with the name of your device as the value of the `-avd` argument and `writeable-system` (*if your device is currently running, terminate it first by clicking the button of its associated row in the Device Manager window*). ```bash emulator -avd -writable-system ``` 6. Once the device has booted up, open a new terminal and execute the `adb` tool with `devices` to ensure the device is listed. ```bash adb devices ``` 7. Execute the `adb` tool with the device ID as the value of the `-s` argument and `root` to gain root privileges. ```bash adb -s root ``` 8. Execute the `adb` tool against the device with `shell avbctl disable-verification` to disable secure boot verification. ```bash adb -s shell avbctl disable-verification ``` 9. Execute the `adb` tool against the device with `reboot` to reboot the device. ```bash adb -s reboot ``` 10. Once the device has rebooted, gain root privileges again. ```bash adb -s root ``` 11. Execute the `adb` tool against the device with `remount` to modify the partition permissions as read/write. ```bash adb -s remount ``` 12. In your terminal, navigate to the file system location of the renamed certificate. 13. Execute the `adb` tool against the device with the filename of the renamed certificate as the value of the `push` argument to move it into the System partition. ```bash adb -s push /system/etc/security/cacerts/ ``` 14. Execute the `adb` tool with `shell chmod 664 -v` to set the proper permissions on the certificate by specifying its file system location on the device. ```bash adb -s shell chmod 664 -v /system/etc/security/cacerts/ ``` 15. Reboot the device again for the changes to take effect. ```bash adb -s reboot ``` 16. Once the device has rebooted, execute the `adb` tool against the device with `reverse tcp:8080 tcp:8080` to forward traffic to Caido. ```bash adb -s reverse tcp:8080 tcp:8080 ``` ::: tip To verify the addition of the certificate: 1. On the device, navigate to the **Settings** interface. 2. In the Search settings input field, search for and select `Trusted credentials`. 3. **Click** on `Trusted credentials` and locate `Caido` in the **System** tab certificate list. ::: Once the certificate has been installed, interacting with certain applications on the device will add rows to the **HTTP History** traffic table in Caido. ::: warning NOTE If traffic is not appearing in the **HTTP History** table in Caido, try: * Disabling `Mobile data` usage. * Disabling any VPN connections. * Setting the Wi-Fi **Proxy hostname** to `10.0.2.2`. ::: If application traffic is still not proxied through Caido or you are encountering errors/limitations in functionality, continue with the [Modifying an Android Application](/app/tutorials/modifying_apk.md) tutorial. --- --- url: /app/guides/filters_applying.md description: >- A step-by-step guide to applying filter presets in Caido traffic tables using the Advanced button and filter selection interface. --- # Applying a Filter To apply a filter preset, **click** on the `Advanced` button, located above traffic tables it is available to, and select the filter preset by its name. Applied filter presets will have their checkboxes filled. ::: info To remove a filter preset, **click** on it to remove its checkbox fill. ::: --- --- url: /app/guides/scopes_applying.md description: >- A step-by-step guide to applying scope presets in Caido using the Unset Scope dropdown menu to control which domains are included or excluded from traffic analysis. --- # Applying a Scope To apply a scope preset, **click** on the `Unset Scope` drop-down menu and select the scope preset by its name. ::: info To remove a scope preset, revert back to the `Unset Scope` selection. ::: --- --- url: /dashboard/guides/education_plan.md description: How to get Caido for free by applying for the Education plan. --- # Applying for the Education Plan Students can get access to Caido for free through the Education plan. You need to verify your academic status in the [Caido Dashboard](https://dashboard.caido.io); once approved, your benefit is valid for a limited time. ## Opening the Education Settings 1. Go to [dashboard.caido.io](https://dashboard.caido.io) and sign in. 2. Open the **Settings** page. 3. Select the **Education** tab (alongside User, Integrations, and Policy). You will see the education plan section where you can apply or check the status of your application. ## Submitting Your Application On the Education tab, fill in the form with your **level of study** (e.g. secondary, undergraduate, graduate) and **field of study**. If your field is not in the list, choose the option to specify it manually. Then click **Submit application**. ::: warning If you already have a paid subscription, you must cancel it before you can submit an application. The form will show a message: "You already have a subscription. You need to cancel it to submit an application." ::: ## Verifying Your Email After you submit, your application is processed. You will see **Application in progress** and a note that processing usually takes a short moment. You will receive a verification code by email. Enter that code in the **Verification code** field and click **Submit**. If you need to start over, click **Start over** to return to the application form. ## After Approval or Rejection * **Approved**: Your academic status has been verified. You now have access to Caido's Education plan for free. The benefit is valid until the date shown on the page. * **Rejected**: Your last application was not approved. The page will show a reason (e.g. Invalid email, Not academic, or others). You can review your details and submit a new application using the form on the same page. --- --- url: /app/quickstart/assistant.md description: >- A step-by-step guide to Caido's AI Assistant feature for security research, attack vector suggestions, and proof-of-concept generation. --- # Assistant The `Assistant` interface provides you with access to Caido's fine-tuned AI model, specifically tailored for security research, that can help you understand traffic elements, suggest attack vectors, and generate proof-of-concept exploits. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Generating CSRF PoCs](/app/guides/assistant_csrf.md) * [Prompting the Assistant to Explain Requests](/app/guides/assistant_explain.md) * [Changing the LLM Model](/app/guides/assistant_model.md) ::: --- --- url: /app/concepts/instance_authentication.md --- # Authentication Each instance requires access control to authenticate the Caido GUI (*client component*) to the Caido CLI (*server component*). ::: danger Although the API is authenticated, the proxy traffic is currently unprotected. We **strongly** advise not to expose your Caido instances to the open internet. ::: Authentication in Caido is based on [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc6749) protocol. ## User Authentication Like we mentioned in [instance registration](./instance_registration.md), each Caido instance registers itself with our Cloud as an `OAuth 2.0 client`. When you click on `Login` on the instance, it performs a Device Authorization flow. This flow is usually approved with the consent form on the [Dashboard](https://dashboard.caido.io). It can also be approved using [Personal Access Tokens](./pat.md) if you want to interact with the instance in headless mode (CICD for example). ::: warning NOTE We do not make any guarantees on the lifetime of the tokens. Currently the access token is valid for 7 days and the refresh token is valid for 3 months. ::: ## Instance Authentication Under the cover, the instance will also perform a Client Credentials flow to have a token to identify itself with the cloud. This allows the instance to retrieve metadata like the [Workspace](/dashboard/concepts/workspace) in which it lives. --- --- url: /app/quickstart/automate.md description: >- A step-by-step guide to Caido's Automate feature for programmatic request sending, brute-force attacks, and fuzzing campaigns. --- # Automate The `Automate` interface gives you the ability to send requests programatically. Using placeholders, this feature allows you to execute brute-force or fuzzing campaigns that systematically test numerous modifications in rapid succession. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Sending Requests to Automate](/app/guides/automate_requests.md) * [Sending Payloads from a Wordlist](/app/guides/automate_wordlists.md) * [Sending Numerical Payloads](/app/guides/automate_numerical.md) * [Repeating Requests with No Payload](/app/guides/automate_null.md) * [Sending Multiple Payloads](/app/guides/automate_multiple.md) * [Preprocessing Payloads](/app/guides/automate_preprocessors.md) * [Avoiding Rate-Limiting Protections](/app/guides/automate_rate_limiting.md) * [Customizing Result Columns with Extractors](/app/guides/automate_extractors.md) ::: --- --- url: /app/tutorials/autorize.md description: >- Learn how to configure and use the Autorize plugin for automated authorization and access control vulnerability detection, including passive and active scanning with template-based checks. --- # Autorize [Autorize](https://github.com/caido-community/autorize) is Caido's official authorization/access control vulnerability testing plugin. In this tutorial you will learn how to configure the plugin to conduct both passive and active scanning. ::: info Autorize is available for [installation](/app/guides/plugins_installing.md) in the `Official` tab of the Plugin interface. ::: Autorize creates templates for proxied requests that are modified to simulate requests sent by users with three different permission levels. The three requests sent for each template are the: 1. `Baseline Request`: This request is the original, high-privilege user request. 2. `Mutated Request`: This request is modified to replace the baseline request with the credentials of a lower-privilege user. 3. `No-Auth Request`: This request is stripped of all authentication headers. By comparing the corresponding responses of these requests to each other, Autorize is able to determine if low-privilege or unauthenticated users are able to access the same resources or functionality available to the high-privilege user. ## Autorize IDOR Testing Lab Walkthrough The Autorize IDOR Testing Lab features registered accounts for two users: John and Bob. By designating John as the low-privilege user and Bob as the high-privilege user, we will use Autorize passively test for authorization vulnerabilities against API endpoints that return sensitive account data based on the `user_id` query parameter: * `/autorize.php?action=profile&user_id={id}` * `/autorize.php?action=orders&user_id={id}` * `/autorize.php?action=messages&user_id={id}` * `/autorize.php?action=settings&user_id={id}` 1. With your proxy settings enabled, navigate to in your browser and **click** on the `Get John's Token` button to authenticate as John. 2. Under the authenticated session, **clicking** on the `Get Profile`, `Get Orders`, `Get Messages`, and `Get Settings` buttons return John's sensitive data. Notice that the `user_id` assigned to John's account is `101`. ### Mutations The modifications to each request are referred to as "mutations" and are applied to configuration profiles that represent the three template requests: * `Mutated`: The low-privilege user request. * `No Auth`: The unauthenticated user request. * `Baseline`: The original high-privilege user request. The mutation that will apply John's low-privilege session token to the high-privilege baseline requests sent by Bob can be configured either manually or via a context-menu shortcut. #### Manual Configuration To set the mutation for the low-privilege `Mutated` profile manually: 1. Copy the value of John's session token from the `token` parameter in the response to the `/autorize.php?action=login` POST request or from the `Authorization` header of subsequent API calls. 2. Navigate to the `Configuration` tab of the Autorize plugin interface, **click** on the `Mutations` tab, and select `Mutated` from the drop-down menu. 3. Next, select the `Header: Set` option from the `Add Mutation` drop-down menu, type in `Authorization` in the `Header name` input field, paste the token value into the `Value` input field, and **click** on the `+` button to update and save the configuration. *** #### Context-Menu Shortcut To quickly add a `Header: Set` mutation to the `Mutated` profile: 1. **Click**, **hold**, and **drag** over a header name and value within a low-privilege user request pane. 2. Then, **right-click** on the highlighted selection to open the context menu, hover your mouse cursor over `Plugins` and `Autorize`, and select Send Headers to Autorize. ::: info By default, Autorize automatically removes common authentication headers like `Authorization` and `Cookie` from the `No Auth` profile. However, mutations can still be configured to account for application-specific implementations. ::: ::: warning NOTE Baseline mutations will apply to all three template requests. ::: ### Scanning With the mutation set, testing can be conducted either passively against requests as they pass through Caido or actively against specific requests. #### Passive Scanning 1. To enable passive scanning **click** on the `Enable Passive Scanning` radio button in the top-right corner of the plugin interface. 2) Now, return to the lab interface and **click** on the `Get Bob's Token` button to authenticate as Bob and make requests to the API endpoints that return sensitive data. *** #### Active Scanning To execute a scan manually against a specific request **right-click** within a request pane or on a traffic table row, hover your mouse cursor over `Plugins` and `Autorize`, and select Send Request to Autorize. ### Viewing Results To view the results of template scans, **click** on the `Dashboard` tab of the Autorize plugin interface. By default, the result of a template scan will be assigned one of three access states that will indicate whether the request succeeded or failed: * `ALLOW`: The server accepted the request and returned a successful response. This might indicate an authorization vulnerability if a low-privilege user was able to access protected resources. * `DENY`: The server denied the request, usually with status codes like 401, 403, or 404. This means access controls are working as expected. * `UNCERTAIN`: Autorize could not determine if the request was allowed or denied. This happens when the response is different from the baseline but does not show clear denial indicators. You should manually review these cases. To switch between HTTP request and response data for each profile, **click** on their associated buttons. The original requests made with Bob's session can be viewed by selecting `baseline` from the request pane. Select `mutated` to view the mutation that overwrote Bob's session token with John's. Notice that John is able to access Bob's data in requests to the `orders`, `messages`, and `settings` endpoints. Even unauthenticated users are able to access the sensitive information of other users in requests to the `settings` endpoint. The only endpoint with proper access control to prevent unauthenticated or unauthorized users from viewing Bob's data is the `profile` endpoint. ## Additional Configuration Options Within the `Configuration` tab of the Autorize plugin interface, additional template settings are divided across several tabs. ### Filtering The `Filtering` tab options apply [scope presets](/app/guides/scopes_defining.md), [filter presets](/app/guides/filters_defining.md), or [HTTPQL](/app/reference/httpql.md) query statements to passive scans. ::: info By default, Autorize automatically excludes requests for common static files (images, CSS, JS) and analytic endpoints. ::: ### Detection By default, Autorize uses smart logic to determine if a request was authorized or denied. However, for unique response patterns, custom HTTPQL query statements can be defined in the `Authorized Response Detection` and `Unauthorized Response Detection` input fields within the `Detection` tab. ::: warning NOTE * If both queries match, the unauthorized query takes precedence. * If neither query matches, the default detection logic will be used. * This is optional. If not configured, the default detection logic will be used. ::: ### Queue The `Queue` tab provides options to specify concurrency, rate limit, and timeout settings for the request templates generated by the plugin. ### General The `General` tab provides the option to include/exclude the `No Auth` request from template tests and an option to enable/disable detailed logging. ### UI The `UI` tab provides options to customize the results table within the `Dashboard` tab. --- --- url: /app/tutorials/autorize_sessions.md description: >- Learn how to automatically refresh authenticated sessions in the Autorize plugin. --- # Autorize Session Management In this tutorial, you will learn how to automatically refresh authenticated sessions in the Autorize plugin. ## Example Authentication Flow We will use the API to demonstrate the workflow. According to the documentation, any user credentials returned from the `/users` endpoint can be used to authenticate with the `/auth/login` endpoint. By including the `expiresInMins` parameter, we can simulate a short-lived JWT. ```http POST /auth/login HTTP/1.1 Host: dummyjson.com Content-Type: application/json Content-Length: 63 {"username":"emilys","password":"emilyspass","expiresInMins":3} ``` In the response to this request, an `accessToken` and `refreshToken` are returned. Until the `accessToken` expires, it can be used to access sensitive user data from the `/auth/me` endpoint: ```http GET /auth/me HTTP/1.1 Host: dummyjson.com Connection: close Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJlbWlseXMiLCJlbWFpbCI6ImVtaWx5LmpvaG5zb25AeC5kdW1teWpzb24uY29tIiwiZmlyc3ROYW1lIjoiRW1pbHkiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJnZW5kZXIiOiJmZW1hbGUiLCJpbWFnZSI6Imh0dHBzOi8vZHVtbXlqc29uLmNvbS9pY29uL2VtaWx5cy8xMjgiLCJpYXQiOjE3Nzk2NDM0MDEsImV4cCI6MTc3OTY0MzQ2MX0.t-mV4fcqjvQmRu-I2is_iWV7_1MoJ2h8eVmCQMNhlnk ``` Once three minutes have passed, a **401 Unauthorized** response is returned instead of user data with a body notifying the `accessToken` has expired: ```http { "message": "Token Expired!" } ``` With the `refreshToken` that was returned in the initial login response, a new valid `accessToken` can be obtained from the response to a POST request to the `/auth/refresh` endpoint: ```http POST /auth/refresh HTTP/1.1 Host: dummyjson.com Content-Type: application/json Content-Length: 397 {"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJlbWlseXMiLCJlbWFpbCI6ImVtaWx5LmpvaG5zb25AeC5kdW1teWpzb24uY29tIiwiZmlyc3ROYW1lIjoiRW1pbHkiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJnZW5kZXIiOiJmZW1hbGUiLCJpbWFnZSI6Imh0dHBzOi8vZHVtbXlqc29uLmNvbS9pY29uL2VtaWx5cy8xMjgiLCJpYXQiOjE3Nzk2NDA4OTIsImV4cCI6MTc4MjIzMjg5Mn0.kmaBxCM5Sq1ybQFZcspzf1HnJBPpZ9maMwOUjxreoYI","expiresInMins":3} ``` ## Configuration To begin, send the initial login request via Replay: ```http POST /auth/login HTTP/1.1 Host: dummyjson.com Content-Type: application/json Content-Length: 63 {"username":"emilys","password":"emilyspass","expiresInMins":3} ``` [Create environment variables](/app/guides/environment_variables.md) named `ACCESS_TOKEN` and `REFRESH_TOKEN` and set their values to the `accessToken` and `refreshToken` JWTs that are returned in the response to this request respectively. Next, **click** on the `Configuration` tab of the Autorize plugin interface and select the `Session` tab. If this is the first time you are accessing this interface, **click** on the sliding radio button of the **Enable Session Management** feature. In the **Invalid Session Condition** input field, enter the following [HTTPQL](/app/reference/httpql.md) query statement to specify the condition for when a session is considered invalid: ```txt resp.raw.cont:"Token Expired!" ``` In the **Re-authentication Request** input field, enter the request to the `/auth/refresh` endpoint that exchanges the `refreshToken` for a new `accessToken`. Using double curly braces syntax, you can set placeholders for environment variables: ```http POST /auth/refresh HTTP/1.1 Host: dummyjson.com Content-Type: application/json Content-Length: 397 {"refreshToken":"{{ REFRESH_TOKEN }}","expiresInMins":3} ``` To update the environment variables, set the following as rules in the **Extraction Rule** section: | Type | Field | Env Variable | | ---- | ----- | ------------ | | JsonBody | refreshToken | REFRESH\_TOKEN | | JsonBody | accessToken | ACCESS\_TOKEN | Next, **click** on the `Mutations` tab of the Autorize plugin interface. Set the following mutation in the **Add Mutation** section: | Type | Header Name | | ---- | ----- | | Header: Set | Authorization | For the value, use double curly braces syntax to reference the `ACCESS_TOKEN` environment variable: ```txt Bearer {{ ACCESS_TOKEN }} ``` ## The Result In Replay, send the following request to Autorize as a template by **right-clicking** on the request pane and selecting `Plugins`, `Autorize`, and Send Request to Autorize: ```http GET /auth/me HTTP/1.1 Host: dummyjson.com Connection: close ``` In the **Dashboard** tab, **click** on the Rescan All button to test the request again. Viewing the **Mutated** request, you will notice the `Authorization` header is constantly updated with a valid `accessToken` value. Now, even after the original token has expired, requests to the `/auth/me` endpoint will return **200 OK** responses with sensitive user data. This configuration method can be adapted to the authentication flow of your target application for continuous testing via Autorize. --- --- url: /app/guides/automate_rate_limiting.md description: >- A step-by-step guide to configuring rate limiting and concurrency settings in Caido's Automate feature to avoid triggering rate-limiting protections. --- # Avoiding Rate-Limiting Protections By **clicking** on the `Settings` tab of an Automate session, you can control the rate at which Automate sessions send requests via the `Delay (ms) between requests` and `# of workers` input fields. ::: info If `Close Connection` is disabled in the `Settings` tab, the TCP connection is maintained through the session until it is terminated by the server. ::: --- --- url: /burp-suite/extensibility/bambdas.md description: Map Burp Suite Pro Bambdas to Caido workflows and plugins. --- # Bambdas Burp Suite Pro Bambdas — in-app JavaScript snippets — and their Caido equivalents. ## Indirectly Available ### Bambdas Bambdas are lightweight JavaScript snippets that run inside Burp for filtering, custom actions, and UI automation. Caido offers native **Workflows** for traffic filtering, transformation, and passive or active analysis — the closest equivalent to Bambdas that operate on requests and responses. The **Workflows Store** plugin distributes community workflow packages similar to sharing Bambda snippets. Caido also supports UI-level automation through plugins with custom pages and commands via the plugin SDK. Workflows replace Bambdas' traffic logic; plugins replace Bambdas' UI automation. #### Resources * [Workflows](/app/concepts/workflows_intro.md) * [Workflows Quickstart](/app/quickstart/workflows.md) * [Creating Workflows](/app/guides/workflows_creating.md) * [Workflow JavaScript](/app/guides/workflows_javascript.md) * [Workflows Store](https://github.com/caido-community/workflows) (GitHub) * [Creating a Page](https://developer.caido.io/guides/page.html) (developer docs) --- --- url: /burp-suite/core/browser-and-setup.md description: 'Map Burp Suite Pro browser, mobile, and setup features to Caido.' --- # Browser & Setup Burp Suite Pro browser integration, transport, and setup features and their Caido equivalents. ## Available ### Testing Mobile Applications Burp proxies traffic from iOS and Android devices through the intercepting proxy. Caido supports proxying mobile device traffic the same way as Burp: install Caido's CA certificate on the device and point the proxy settings to your Caido instance. Caido supports mobile proxying natively through its listening proxy. #### Resources * [Setup](/app/quickstart/setup.md) * [Managing CA Certificates](/app/guides/ca_certificate_managing.md) * [Importing CA Certificates](/app/guides/ca_certificate_importing.md) * [Android Introduction Tutorial](/app/tutorials/android_introduction.md) ### External Browser Configuration Burp lets you use a system browser other than its embedded browser with the proxy. Caido supports using a **preconfigured browser** or manually set any browser's proxy to point at Caido. Caido does not require its own embedded browser for proxy testing. #### Resources * [Using a Preconfigured Browser](/app/guides/preconfigured_browser.md) * [FoxyProxy Guide](/app/guides/foxyproxy.md) * [ZeroOmega Guide](/app/guides/zeroomega.md) ### Invisible Proxying Burp forwards non-proxy-aware clients through the proxy without explicit proxy configuration. Caido offers an **Invisible Proxy** setup to intercept traffic from clients that cannot be configured to use an explicit proxy. This requires network-level forwarding similar to Burp's invisible proxying mode. #### Resources * [Invisible Proxy Tutorial](/app/tutorials/invisible_proxy.md) * [Invisible Proxying Guide](/app/guides/invisible_proxying.md) ### Managing CA Certificates Burp lets you install and manage its CA certificate for intercepting HTTPS traffic. Caido lets you export and install its CA certificate from **Settings → Network → TLS**. Certificate management is built into Caido's network settings rather than a separate Burp-style CA tool tab. #### Resources * [Setup](/app/quickstart/setup.md) * [Managing CA Certificates](/app/guides/ca_certificate_managing.md) * [Importing CA Certificates](/app/guides/ca_certificate_importing.md) ## Indirectly Available ### Burp's Browser Burp ships a Chromium-based browser preconfigured to proxy through Burp with DOM Invader integration. Caido supports configuring a **preconfigured browser** to proxy through Caido automatically. The **PwnFox** plugin integrates multi-profile Firefox containers for parallel sessions. Caido does not ship an embedded browser with DOM testing integration like Burp's browser; pair a system browser with **DOMLogger++** for partial DOM sink monitoring. #### Resources * [Using a Preconfigured Browser](/app/guides/preconfigured_browser.md) * [Setup](/app/quickstart/setup.md) * [PwnFox](https://github.com/caido-community/pwnfox) (GitHub) * [DOMLogger++](https://github.com/kevin-mizu/domloggerpp-caido) (GitHub) ## Not Available ### Testing with HTTP/2 Burp lets you send and manipulate HTTP/2 requests, including exclusive attacks. Caido does not support HTTP/2 in the intercepting proxy or in **Replay**. Traffic is handled over HTTP/1.1; HTTP/2-specific testing and attacks are not available in Caido today. #### Resources * [Replay](/app/quickstart/replay.md) * [Intercept](/app/quickstart/intercept.md) --- --- url: /burp-suite/core/ai.md description: Map Burp Suite Pro AI features to Caido AI plugins. --- # Burp AI Burp Suite Pro AI features and their Caido equivalents. ## Available ### Generating AI-Powered Explanations Burp can generate natural-language explanations of HTTP requests and responses from Repeater. Caido offers the **Chatio** and **Shift** community plugins to explain and analyze HTTP traffic in natural language. **Chatio** provides a dedicated chat interface for security-focused Q\&A; **Shift** adds in-context explanations and analysis on requests in **Replay**. #### Resources * [Chatio](https://github.com/caido-community/Chatio) (GitHub) * [Shift](https://github.com/caido-community/shift) (GitHub) * [Shift Tutorial](/app/tutorials/shift.md) ### Using Burp AI in Repeater In Burp, AI actions run directly inside Repeater tabs to modify or analyze the current request. Caido offers the **Shift** plugin for AI-assisted request editing alongside native **Replay**. Shift provides in-context AI actions on requests, similar to Burp AI in Repeater. #### Resources * [Shift](https://github.com/caido-community/shift) (GitHub) * [Shift Tutorial](/app/tutorials/shift.md) * [Replay](/app/quickstart/replay.md) ## Indirectly Available ### Burp AI Burp AI is PortSwigger's built-in assistant for explaining requests, suggesting payloads, and running custom actions inside Repeater. Caido does not ship a single bundled AI product like Burp AI. Use **Shift** (including **Shift Agents** for autonomous background tasks) and **Chatio** for explanations, payload suggestions, and request editing. Each plugin manages its own API keys rather than a central credits system. #### Resources * [Shift](https://github.com/caido-community/shift) (GitHub) * [Shift Tutorial](/app/tutorials/shift.md) * [Chatio](https://github.com/caido-community/Chatio) (GitHub) ### Automating Tasks with Custom Actions Burp AI custom actions automate repetitive Repeater tasks with prompts and predefined workflows. Caido offers **Shift Agents** to assign autonomous background tasks to a model, and **Shift** custom prompts for repeatable AI actions on requests. Caido also covers non-AI repetitive task automation through native **Workflows** and **Automate**. #### Resources * [Shift Tutorial](/app/tutorials/shift.md) * [Shift](https://github.com/caido-community/shift) (GitHub) * [Workflows](/app/quickstart/workflows.md) * [Automate](/app/quickstart/automate.md) ## Not Available ### AI Credits Burp tracks AI usage through a credits system tied to your PortSwigger subscription. Caido has no central AI credits system. AI plugins such as **Shift** and **Chatio** use your own API keys (OpenAI, Anthropic, etc.) or plugin-specific billing configured in each plugin's settings. #### Resources * [Shift Tutorial](/app/tutorials/shift.md) * [Shift](https://github.com/caido-community/shift) (GitHub) * [Chatio](https://github.com/caido-community/Chatio) (GitHub) --- --- url: /app/guides/ca_certificate_managing.md description: >- A step-by-step guide to managing CA certificates in Caido including importing, exporting, and regenerating certificates for HTTPS traffic interception. --- # CA Certificate Management Each Caido instance generates its own CA certificate to be able to negotiate TLS handshakes and proxy HTTPS traffic. To access the certificate management options, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `Certificate` tab. * Import: Import a CA certificate from another Caido instance or a backup file to use it in this instance. * Export: Export the CA certificate to transfer it to another Caido instance or for backup purposes. * Regenerate: Regenerate the CA certificate for this Caido instance. You will need to reinstall the new certificate on your system after regeneration. ::: warning NOTE Caido does not currently support CA certificates from other tools. ::: --- --- url: /app/guides/athena_os.md description: >- A step-by-step guide to using Caido on Athena OS with native support across security roles and launch instructions for the penetration testing distribution. --- # Caido :handshake: Athena OS *** [Athena OS](https://athenaos.org/) is an Arch-derived Linux distribution designed for penetration testing and security research. Athena's [cybersecurity role-based system](https://athenaos.org/en/resources/athena-welcome/#cyber-security-roles) equips you with the relevant tools needed to conduct comprehensive security assessments, making it an exceptional choice for security professionals. Additionally, with Athena's ability to connect directly to educational platforms, it's an ideal operating system for information security students. ## Native Support Caido now comes pre-installed with the following roles in Athena OS: * Bug Bounty Hunter * Network Analyst * Red Teamer * Enthusiast Student * Web Pentester ::: info Caido is also available as a [Athena Cyber Hub Docker container](https://athenaos.org/en/resources/cyber-hub/) and within [AthenaOS WSL](https://athenaos.org/en/wsl/wsl/). ::: ## Launching Caido To launch Caido, select the `Web Application Analysis` category from either the menu or application wheel and select `Caido`. *** --- --- url: /app/guides/exegol.md description: A step-by-step guide to using Caido on Exegol. --- # Caido :handshake: Exegol *** [Exegol](https://exegol.com/) is a comprehensive cybersecurity environment designed by offensive security experts, for fellow hackers, in collaboration with its community. It solves the common pain points of traditional security distributions by providing a modular and reliable toolkit that's made for the field. Available as containerized environments, Exegol is for professionals, students, CTF players, bug hunters, researchers, *and you*. ## Native Support Caido now comes pre-installed in Exegol's free image (`free`), advanced images (`full`, `web`, `ad`, `nightly`), and private images. ## Launching Caido To launch the Caido desktop application, enter the following command in you container terminal: ```bash caido --no-sandbox ``` To launch the Caido CLI, enter: ```bash caido-cli --help ``` --- --- url: /app/guides/kali_linux.md description: A step-by-step guide to using Caido on Kali Linux. --- # Caido :handshake: Kali Linux *** [Kali Linux](https://www.kali.org/) is an open-source, Debian-based Linux distribution widely regarded as the industry standard for penetration testing and security auditing. Backed by [OffSec](https://www.offsec.com/), it features an extensive tool repository for security research, digital forensics, and reverse engineering - making it the go-to choice for security professionals worldwide. [We are excited to announce that Caido is now included in the rolling distribution of Kali Linux.](https://www.kali.org/tools/caido/) ## Download & Installation To download and install Caido from the official Kali Linux repository, update your package list and install the package: ```bash sudo apt update sudo apt install caido ``` To download and install the Caido CLI, use: ```bash sudo apt install caido-cli ``` ## Launching Caido Once Caido has been installed, enter the following terminal command from any directory to launch Caido: ```bash caido ``` --- --- url: /app/guides/parrot_os.md description: >- A step-by-step guide to using Caido on Parrot Security OS with native support, Docker integration, and launch instructions for the security-focused Linux distribution. --- # Caido :handshake: Parrot Security *** [ParrotOS](https://parrotsec.org/) is a versatile, security-focused Linux distribution designed for penetration testing, security research, and privacy protection. With a rich suite of security tools, it's an ideal operating system for ethical hackers, security professionals, and privacy-conscious users. Known for its intuitive interface, regular updates, and strong commitment to open-source principles, ParrotOS stands out as an exceptional option in the security space. [Caido is thrilled to maintain a partnership with the Parrot team.](https://parrotsec.org/blog/2025-01-11-parrot-caido/) ## Native Support Caido now comes pre-installed in: * [ParrotOS Security](https://parrotsec.org/download/) * [ParrotOS WSL](https://parrotsec.org/docs/installation/install-with-wsl/) * [ParrotOS Docker](https://hub.docker.com/r/parrotsec/security) ::: info Caido can also be ran as a Docker container inside ParrotOS, with [Rocket](https://gitlab.com/parrotsec/project/rocket)! ::: Parrot also provides an image of their operating system that has been optimized for virtual environments, compatible with: VirtualBox, VMware, and UTM. ## Launching Caido To launch Caido, select the `Applications` menu tab in the top-left corner of the desktop interface and select `Pentesting`, `Web Application Analysis`, `Web Application Proxies`, and `Caido`. Or, enter the following terminal command from any directory: ```bash caido ``` --- --- url: /app/concepts/cli_vs_desktop.md description: >- Understand the core concepts behind the comparison between Caido CLI and Desktop application - the client/server architecture and choosing the right option. --- # Caido CLI vs Desktop Caido is built around a client/server architecture and the two components are decoupled by a [traffic splitting](/app/concepts/traffic_splitting.md) algorithm: * The **client** component is the Caido GUI (*desktop or web application graphical user-interface*). * The **server** component is the Caido CLI that handles proxying and processing. ## Caido CLI The standalone Caido CLI installation is versatile as it can be ran on a variety of different platforms (*[virtual private servers](/app/guides/vps.md), [containers](/app/guides/docker.md), etc.*). Once the Caido CLI is launched, the GUI is available as a web application in the browser. ::: info Certain [options](/app/reference/cli.md) for advanced configuration and management are only available to the Caido CLI. ::: ## Desktop Application The desktop application also runs the Caido CLI (*as a background process*) and provides the GUI as a local installation via a webview window. ::: tip In addition to the installed webview, you can still access the GUI from the browser once the desktop application is launched. ::: ::: info Although either installation provides the same functionality, the desktop application has some slight advantages over the standalone Caido CLI: * It provides centralized management for multiple [instances](/app/concepts/instance.md). * It includes [browser pre-configurations](/app/guides/preconfigured_browser.md). * It can be used in environments without internet access. ::: --- --- url: /app/concepts/cloud.md description: >- Understand the core concepts behind Caido Cloud services including billing, access control, API transparency, data collection, and security measures. --- # Caido Cloud Caido Cloud is comprised of your account dashboard (*accessible at *) and an API that handles [instance](/app/concepts/instance.md) registration and authentication. ::: info For transparency, the OpenAPI specification of the cloud API can be viewed at . ::: ## Data Collection ::: warning NOTE We are aware that tying Caido to a cloud may be controversial to some. However, **we do not collect any data stored on your instances.** View our [privacy policy](https://www.caido.io/privacy) for more information. ::: The data collected upon account registration (*name, email address, and user-agent information*) allows for: * Billing on a per-user basis rather than per-license, so Caido can be installed on multiple devices. * Access control to facilitate collaboration on instances belonging to the same account workspace. * Complementary services such as the [Assistant](/app/quickstart/assistant.md) and sharing capabilities (*planned for a future release*). ::: info Accounts can **always** be deleted upon request by contacting us at `security[at]caido.io`. ::: The data collected as you use Caido (*IP address and API call actions/timestamps*) facilitates instance registration to your account and authenticated sessions. The associated API calls mainly relate to: * `/instance/alive`: Instance startup and active status is tracked once per 24H. * `/instance/user/session` / `/instance/user/profile`: Instance interaction is tracked upon first interaction and once per hour. * `/instance/assistant/complete`: Assistant token usage is tracked (*message content data is **not** collected*). We also have opt-out analytics for UI interactions performed within the application. We NEVER collect project data, HTTP requests, payloads, etc. ## Endpoints Used If you need to whitelist endpoints, here are all the endpoints we use: * api.caido.io: Main Caido API * sync.caido.io: Synchronization service * caido.download: Update checking and download * github.com: Plugins download * storage.googleapis.com: Chromium download Only `api.caido.io` is absolutely required. ## Location & Security * Our cloud services are currently hosted on [Render](https://render.com) in their Oregon (*US*) region. Refer to Render's [Security and Trust](https://trust.render.com/) page for more information. * The Assistant uses [OpenAI](https://openai.com) services hosted in the US. Data sent to it can be stored for [up to 30 days](https://platform.openai.com/docs/models/how-we-use-your-data). * The public facing portion of our API is protected by [Cloudflare](https://cloudflare.com). * We perform daily backups that are stored encrypted for 30 days on [Google Cloud](https://cloud.google.com/) in the US. * Our data in transit uses HTTPS with TLS 1.2 and data at rest uses AES-256. * Our production environment can only be accessed by the founding team using [Tailscale](https://tailscale.com). ::: tip To report a security issue, please contact us at `security[at]caido.io`. ::: --- --- url: /app/guides/request_response_modes.md description: >- A step-by-step guide to viewing, editing, and switching between Pretty and Raw view modes in HTTP request and response editors. --- # Changing Request & Response View Modes HTTP request and response data can be viewed in two different formats: * `Pretty`: Formats the data with whitespaces, indentation, and new lines for enhanced readability. * `Raw`: Represents the data exactly as it was transmitted. To switch between the two views, **click** on their associated buttons. *** --- --- url: /app/guides/data_location.md description: >- A step-by-step guide to configuring the data directory location in Caido CLI and Desktop application for custom data storage paths. --- # Changing the Data Storage Location All the data Caido creates is stored in a single directory. The default location of this directory is dependent on your operating system: | OS | Location | | ------- | ------------------------------------------------ | | Linux | `~/.local/share/caido` | | MacOS | `~/Library/Application\ Support/io.caido.Caido/` | | Windows | `%APPDATA%\Caido\Caido\data` | ::: warning NOTE Caido does not currently support storing projects outside of this directory. However, you can change the location of the directory if needed. Before changing the location, ensure to copy the existing data before restarting your instance. Otherwise the instance will restart as if you were on a new device. ::: ## Caido CLI To change the default location of the data storage directory with the Caido CLI, launch Caido with the `--data-path ` option. ```bash caido --data-path /alternate/data/location ``` ## Desktop Application To change the default location of the data storage directory within the Caido desktop application, in the launch window, **click** on the button attached to an instance and select `Edit`. Then, **click** on Advanced to expand the drop-down settings menu options, **click** on the `Data path` checkbox, and type the location in the input field. Once you have defined the location, **click** on the `Save` button to update and save the configuration. ::: info The `/logs` subdirectory stores the log files that contain the output from workflow nodes using the [Workflow SDK](https://developer.caido.io/reference/sdks/workflow/). ::: --- --- url: /app/guides/listening_address.md description: >- A step-by-step guide to changing the listening address and port in Caido CLI and Desktop application for network accessibility and security configuration. --- # Changing the Listening Address/Port By default, Caido listens on the IP address `127.0.0.1` and port `8080`. This means that Caido will only be accessible from the same device it is running on. ::: warning Please note that if you change the listening address to something other than 127.0.0.1, Caido will be accessible from any device on the network, so it is important to consider the security implications of doing so. ::: ## Caido CLI To change the listening address/port with the Caido CLI, launch Caido with the `-l ` or `--listen ` command-line option. For example, to listen on all available network interfaces on port `8000`, enter: ```bash caido -l 0.0.0.0:8000 ``` ## Desktop Application To change the listening address/port within the Caido desktop application, in the launch window, **click** on the button attached to an instance and select `Edit`. Then, either: * **Click** on a radio button under `Listening addresses` to select `Localhost (127.0.0.1)` or `All interfaces (0.0.0.0)`. * Or **click** on the radio button for the `Custom` option and type in an address. Next, type a port number in the `Listening port` input field. Once you have defined the listening address/port, **click** on the `Save` button to update and save the configuration. --- --- url: /app/guides/assistant_model.md description: >- A step-by-step guide to changing the LLM model in Caido's AI Assistant including available models, token costs, and credit usage. --- # Changing the LLM Model ::: warning Submitted data is sent to the LLM's third-party provider (OpenAI) and can be stored for up to 30 days. Due to this, **anonymize sensitive data** when using the Assistant. Sensitive data may be unintentionally submitted when using the Assistant context menu options. Before using any context menu option, manually review all content to ensure no sensitive data is included. For more information, review: * [OpenAI's Privacy Policy](https://openai.com/policies/privacy-policy) * [Caido's Privacy Policy](https://www.caido.io/privacy) ::: ::: info "Tokens" are the measurement used by OpenAI LLMs when processing text. Each Individual and Team tier subscription user gets 500,000 credits per month which can be exchanged for tokens. Since LLMs maintain context based on all tokens in a session, be aware that each subsequent message in a conversation will incur a greater credit cost as the sum of all tokens is consumed. [Estimate credit costs with the OpenAI Tokenizer tool.](https://platform.openai.com/tokenizer) ::: The Assistant supports the following OpenAI LLM models, each with a different credit to token cost ratio: * GPT-4o Mini (1:1) * GPT-3.5 Turbo (2:1) * GPT-4o (10:1) To switch models, **click** on the drop-down menu within a new conversation and make a selection. ::: info Currently, the Assistant does not support API keys for other AI providers or configuration for use with local LLMs. [View Issue #1480 on GitHub for more information.](https://github.com/caido/caido/issues/1480) ::: --- --- url: /app/reference/cli.md description: >- Find detailed reference information on Caido CLI command-line options and flags for advanced configuration and troubleshooting. --- # CLI Options To view the options available to the Caido CLI, use `-h` or `--help`. ```txt Options: -l, --listen Listening address --invisible Enable invisible mode for all listeners --proxy-listen Proxy listening addresses --ui-listen UI listening addresses --ui-domain Allowed domains for UI --no-open Do not open the UI a browser tab --debug Record and display debug logs --reset-cache Reset the instance cache of cloud data --reset-credentials Reset the instance credentials (DANGEROUS) --data-path Directory to store data --no-logging Disable file logging --no-renderer-sandbox Disable sandboxing for the renderer --import-ca-cert Import CA certificate --import-ca-cert-pass Import CA certificate password --allow-guests Allow login as guest -h, --help Print help (see more with '--help') -V, --version Print version ``` --- --- url: /app/concepts/collaboration.md description: >- Understand the pros and cons of both collaboration via shared instances and collaboration via the Drop plugin. --- # Collaboration Besides sharing the same device, there are two ways to collaborate with other users using Caido: **remote hosting** and the **Drop** plugin. ## Remote Hosting By remote hosting an instance, multiple users can access it from their own local devices, either sequentially or simultaneously. This allows for a shared workspace where all users view the same data. However, since all users are working on the same data, if one user makes certain changes to the instance, it will be reflected for all other users. While many Caido features retain a history of changes, other actions, such as deleting a project entirely, are irreversible. So, while shared remote instances can be advantageous as they provide each user with the full context of an assessment, this can also be a disadvantage as a lack of coordination and communication between users can lead to data loss. ::: tip [Learn how to host an instance remotely.](/app/tutorials/remote.md) ::: ## Drop The Drop plugin allows for more granular collaboration as each user operates within their own instance and shares specific data with others over a secure end-to-end encrypted channel. This ensures that each user can work on their own data without affecting others. However, since all data is shared manually, it can become a disadvantage as doing so can be time-consuming. ::: tip [Learn how to use the Drop plugin.](/app/tutorials/drop.md) ::: --- --- url: /app/tutorials/color_requests.md description: >- Learn how to create a passive workflow that color highlights in-scope GET requests in Caido traffic tables for visual identification. --- # Color Request Rows Workflow In this tutorial, we will create a passive workflow that will color highlight in-scope GET requests within traffic tables. ## Creating a Passive Workflow To begin, navigate to the Workflows interface, select the `Passive` tab, and **click** the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections Too add nodes to the workflow, **click** on `+ Add Node` button and then the `+ Add` button of a specific node. For this workflow, the overall node layout will be: ::: tip Passive workflows do not require `Passive End` nodes in order to exit execution properly. ::: * The `On Intercept Request` node outputs `$on_intercept_request.request` objects which represent proxied requests. * The `In Scope` node checks if the value of a request's Host header is included in the in-scope list of a scope preset. If it is not - the workflow will end. * In-scope requests will be passed to the `Matches HTTPQL` node, which checks if a request satisfies an HTTPQL query statement. If it does not - the workflow will end. * If a request satisfies the HTTPQL query statement, it is passed to the `Set Color` node. If it does not - the workflow will end. * Once a request has been processed by the `Set Color` node, the workflow will end. ## Coloring In-Scope GET Requests 1. **Click** on the `Matches HTTPQL` node to access its editor. 2. Then, **click** within the query environment and type in the following HTTPQL query statement: ```httpql req.method.eq:"GET" ``` 3. Next, ensure the `$on_intercept_request.request` object is [referenced as input data](/app/guides/workflows_references.md). 4) Close the editor window and **click** on the `Set Color` node to access its editor. 5) Reference the `$on_intercept_request.request` object as input data. 6) Next, type in a color hex code in the `Color` input field. Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ## Testing the Workflow To test the workflow, enable proxying and navigate to an in-scope domain in the browser. ## The Result All in-scope GET requests will be color highlighted within the traffic tables: The full workflow is provided below, ready to be imported. ```json { "description": "In-scope GET request rows in traffic tables are highlighted in blue.", "edition": 2, "graph": { "edges": [ { "source": { "exec_alias": "exec", "node_id": 0 }, "target": { "exec_alias": "exec", "node_id": 2 } }, { "source": { "exec_alias": "true", "node_id": 2 }, "target": { "exec_alias": "exec", "node_id": 3 } }, { "source": { "exec_alias": "false", "node_id": 3 }, "target": { "exec_alias": "exec", "node_id": 1 } }, { "source": { "exec_alias": "true", "node_id": 3 }, "target": { "exec_alias": "exec", "node_id": 6 } }, { "source": { "exec_alias": "exec", "node_id": 6 }, "target": { "exec_alias": "exec", "node_id": 5 } }, { "source": { "exec_alias": "false", "node_id": 2 }, "target": { "exec_alias": "exec", "node_id": 7 } } ], "nodes": [ { "alias": "on_intercept_request", "definition_id": "caido/on-intercept-request", "display": { "x": -200, "y": -10 }, "id": 0, "inputs": [], "name": "On intercept request", "version": "0.1.0" }, { "alias": "passive_end", "definition_id": "caido/passive-end", "display": { "x": 450, "y": 80 }, "id": 1, "inputs": [], "name": "Passive End 1", "version": "0.1.0" }, { "alias": "in_scope", "definition_id": "caido/in-scope", "display": { "x": 10, "y": 0 }, "id": 2, "inputs": [ { "alias": "request", "value": { "data": "$on_intercept_request.request", "kind": "ref" } } ], "name": "In Scope", "version": "0.1.0" }, { "alias": "matches_httpql", "definition_id": "caido/httpql-matches", "display": { "x": 230, "y": -10 }, "id": 3, "inputs": [ { "alias": "query", "value": { "data": "req.method.eq:\"GET\"", "kind": "string" } }, { "alias": "request", "value": { "data": "$on_intercept_request.request", "kind": "ref" } } ], "name": "Matches HTTPQL", "version": "0.2.0" }, { "alias": "passive_end_1", "definition_id": "caido/passive-end", "display": { "x": 660, "y": -90 }, "id": 5, "inputs": [], "name": "Passive End 2", "version": "0.1.0" }, { "alias": "set_color", "definition_id": "caido/color-set", "display": { "x": 450, "y": -90 }, "id": 6, "inputs": [ { "alias": "color", "value": { "data": "#185A6C", "kind": "string" } }, { "alias": "request", "value": { "data": "$on_intercept_request.request", "kind": "ref" } } ], "name": "Set Color", "version": "0.1.0" }, { "alias": "passive_end_2", "definition_id": "caido/passive-end", "display": { "x": 230, "y": 80 }, "id": 7, "inputs": [], "name": "Passive End", "version": "0.1.0" } ] }, "id": "bbf38766-0f9d-45af-a823-f230b9134606", "kind": "passive", "name": "Color In-Scope GET Requests" } ``` --- --- url: /app/reference/command_shortcuts.md description: >- Find detailed reference information on Caido keyboard shortcuts and commands for efficient navigation and operation across all interfaces. --- # Command Shortcuts ::: tip To set, unset, or change shortcut keybindings, view the [Creating Shortcuts](/app/guides/shortcuts.md) guide. ::: ::: info Additional commands may be available depending on the Plugins you have installed. ::: ## Automate | Command | Description | Default Keybinding | macOS Keybinding | |------------------|-------------------------------------------------|--------------------|------------------| | Send to Automate | Send the currently focused request to Automate. | `CTRL` + `M` | `⌘` + `M` | ## Editor | Command | Description | Default Keybinding | macOS Keybinding | |---------------|-------------------------------------------------|--------------------|------------------| | Search | Search within the currently focused request/response. | `CTRL` + `F` | `⌘` + `F` | | Cancel Search | Close the search interface. | `ESC` | `ESC` | | Undo | Undo an edit to a request/response. | `CTRL` + `Z` | `⌘` + `Z` | | Redo | Redo an edit to a request/response. | `CTRL` + `SHIFT` + `Z` | `⌘` + `SHIFT` + `Z` | ## Findings | Command | Description | Default Keybinding | macOS Keybinding | |------------------|----------------------------|--------------------|------------------| | Send to Findings | Manually create a finding. | | | ## Intercept | Command | Description | Default Keybinding | macOS Keybinding | |----------|-----------------------------------|--------------------|------------------| | Drop | Drop an intercepted request/response. | | | | Forward | Forward an intercepted request/response. | `CTRL` + `;` | `⌘` + `;` | ## Miscellaneous | Command | Description | Default Keybinding | macOS Keybinding | |------------------------|-------------------------------------------------|--------------------|------------------| | Close Tab | Close the currently focused tab. | | | | Reload Window | Refreshes Caido and reloads all components. | | | | Toggle Command Palette | Open/close the command palette window. | `CTRL` + `K` | `⌘` + `K` | | Toggle Sidebar | Open/close the command palette window. | | | ## Navigation | Command | Description | Default Keybinding | macOS Keybinding | |-----------------------|-------------------------------------------------|--------------------|------------------| | Go to Assistant | Navigate to the Assistant interface. | | | | Go to Automate | Navigate to the Automate interface. | `CTRL` + `SHIFT` + `A` | `⌘` + `SHIFT` + `A` | | Go to Exports | Navigate to the Exports interface. | | | | Go to Files | Navigate to the Files interface. | | | | Go to Filters | Navigate to the Filters interface. | | | | Go to HTTP History | Navigate to the HTTP History interface. | `CTRL` + `\|` | `⌘` + `\|` | | Go to Intercept | Navigate to the Intercept interface. | | | | Go to Match & Replace | Navigate to the Match & Replace interface. | | | | Go to Plugins | Navigate to the Plugins interface. | | | | Go to Replay | Navigate to the Replay interface. | `CTRL` + `SHIFT` + `R` | `⌘` + `SHIFT` + `R` | | Go to Scope | Navigate to the Scope interface. | | | | Go to Search | Navigate to the Search interface. | | | | Go to Settings | Navigate to the application settings interface. | | | | Go to Sitemap | Navigate to the Sitemap interface. | | | | Go to Workflows | Navigate to the Workflows interface. | | | | Go to Workspace | Navigate to the Workspace interface. | | | | Go to WS History | Navigate to the WS History interface. | | | | Next Tab | Navigate to the next tab from the currently selected tab. | `CTRL` + `]` | `⌘` + `]` | | Previous Tab | Navigate to the previous tab from the currently selected tab. | `CTRL` + `[` | `⌘` + `[` | ## Proxy | Command | Description | Default Keybinding | macOS Keybinding | |---------------------------|----------------------------|--------------------|------------------| | Toggle Proxy Interception | Enable/disable interception. | `CTRL` + `P` | `⌘` + `P` | ## Replay | Command | Description | Default Keybinding | macOS Keybinding | |-------------------|-------------------------------------------------|--------------------|------------------| | Select Next Entry | Go forward through the request session history. | | | | Select Previous Entry | Go backward through the request session history. | | | | Send Request | Forward the request. | `CTRL` + `ENTER` | `⌘` + `ENTER` | | Send to Replay | Send the currently focused request to Replay. | `CTRL` + `R` | `⌘` + `R` | ## Request | Command | Description | Default Keybinding | macOS Keybinding | |-------------------|-------------------------------------------------|--------------------|------------------| | Copy URL | Copy the request URL to your clipboard. | | | | Go to Stream | Navigate to the WebSocket stream view for the current request. | | | | Replay in Browser | Copy the request to your clipboard. | | | | Show in Browser | Copy the response data to your clipboard. | | | ## Runtime | Command | Description | Default Keybinding | macOS Keybinding | |-------------------|----------------------------|--------------------|------------------| | Toggle Logs Panel | Enable/disable interception. | | | ## Table | Command | Description | Default Keybinding | macOS Keybinding | |-------------------|----------------------------|--------------------|------------------| | Select Next Row | Move downward through table rows. | `DOWN ARROW` | `DOWN ARROW` | | Select Previous Row | Move upward through table rows. | `UP ARROW` | `UP ARROW` | --- --- url: /app/concepts.md description: Understand the core concepts behind Caido's features and design philosophy. --- # Concepts The Concepts section explains the foundational ideas and principles behind Caido. It’s designed to help you understand what features are, why they exist, and how they fit into the broader workflow. This section provides the context you need to fully grasp the purpose and design of Caido’s tools and features. --- --- url: /dashboard/concepts.md description: Understand the core concepts of the Caido dashboard --- # Concepts The Concepts section explains the foundational ideas and principles in the Dashboard. It’s designed to help you understand what features are, why they exist, and how they fit into the broader ecosystem of Caido tooling. --- --- url: /app/guides/config.md description: A guide to the configuration file for Caido. --- # Configuration File As an alternative to including [command-line options](/app/reference/cli.md) directly, you can launch Caido with the `--config` command-line option to specify a configuration file. ```bash caido-cli --config /path/to/caido.yaml ``` ::: info [View the configuration file schema.](https://raw.githubusercontent.com/caido/schemas/main/.schemastore/proxy/config.schema.json) ::: ::: tip TIPS * To obtain the Caido CA certificate in the required P12 format, export it from the [CA Certificate Management](/app/guides/ca_certificate_managing.html#ca-certificate-management) options. * Installation of the [YAML VSCode extension](https://marketplace.cursorapi.com/items/?itemName=redhat.vscode-yaml) and naming the configuration file as `caido.yaml` provides auto-completion and validation of the configuration file. * The development of options is ongoing. To request an option property, [submit a templated issue.](https://github.com/caido/caido/issues/new?template=feature.md\&title=New%20Configuration%20File%20Option) ::: ## Example ```yaml # The target Caido version for the configuration file. version: "0.57.0" # Configuration (Required) config: # Directory to store data data_path: "/alternate/data/location" # Cloud configuration cloud: # This is used to automatically register the instance in a workspace. registration_key: null # Enable sync with sync server sync: false # Reset the instance cache of cloud data reset_cache: false # Reset the instance credentials (DANGEROUS) reset_credentials: false # Security configuration security: # Allowed domains for UI allow_domains: [] # Allow login as guest allow_guests: false # Enable sandboxing for the renderer render_sandbox: false # Networking configuration networking: # Enable invisible mode for all listeners invisible: false # CA certificate configuration ca: # CA certificate path (Required if ca is provided) path: "/path/to/certificate.p12" # CA certificate password password: null # Listeners configuration listeners: - # Listener address (Required) address: "127.0.0.1:8080" # Listener usage: Allowed values are 'ui', 'proxy', or 'both' usage: "both" # Project configuration project: # Project name (Required if project is provided) name: "Default_Assessment_Project" # Project scopes scopes: - # Import direct scope (Required fields: name, allowlist, denylist) name: "Example Scope" allowlist: - "*.example.com" denylist: - "admin.example.com" # Plugins configuration plugins: # Can install via 'store' identifier OR via local 'path' - store: "scanner" - path: "/path/to/plugin_package.zip" # Logging configuration logging: # Record and display debug logs debug: true # Enable file logging file: true # Runtime configuration runtime: # Enable safe mode safe: false # Parent PID (Must be a positive integer) parent_pid: null # Open browser automatically on startup open_browser: true # Strict mode # When enabled, the instance will refuse to start if part of the configuration cannot be # used. For example, if a requested plugin cannot be installed. strict: false ``` --- --- url: /app/reference/context_menu.md description: >- Find detailed reference information on all context menu options available in Caido interfaces for request manipulation and workflow operations. --- # Context Menu Options | Option | Description | |--------|-------------| | Copy | Copies the highlight selected text to your clipboard. | | Copy as cURL | Copies a request as a curl command to your clipboard. | | Copy URL | Copies a request URL to your clipboard. | | Send to Replay | Sends a request to the Replay interface. Hovering over this option will allow you to specify the collection to add the request to. | | Add session | Creates a new request. | | Delete sessions | Deletes the specified number of request in a collection. | | Move | Moves a request to a different collection. | | Close | Closes a request tab. | | Close Others | Closes all other request tabs besides the one selected. | | Close to the Left | Closes all other request tabs to the left of the one selected. | | Close to the Right | Closes all other request tabs to the right of the one selected. | | Close All | Closes all request tabs. | | Send to Automate | Sends a request to the Automate interface. | | Send to Findings... | Sends a request and response pair to the findings interface. Selecting this option will present a window in which you can enter finding details. | | Replay in browser | Copies a request to your clipboard as a URL. This request includes any modifications that have been made and can be entered into your browser while actively proxying traffic. | | View response in browser | Copies a URL to your clipboard that allows you to view a response in your browser while actively proxying traffic. | | Highlight | Color highlights a request's table row. | | Add in Scope | Adds a request's host as in scope to either an existing or new scope preset. | | Add out of Scope | Adds a request's host as out of scope to either an existing or new scope preset. | | Convert (Preview) | Displays a preview of the result of a convert workflow on a selection. | | Convert (Replace) | Replaces a selection with the result of a convert workflow. | | Run workflow | Executes an active workflow. | | Assistant | Prompts the Assistant to either explain a request or generate a CSRF proof-of-concept. | | Set request | Generates a corresponding request to a URL. | | Toggle GET/POST | Toggles a request between GET and POST methods. | | Plugins | Plugin specific options. These will vary depending on which plugins are installed. | | Select | Loads the associated project. | | Rename | Allows you to rename an entity. | | Duplicate | Creates a copy of an entity. | | Copy path | Copies an entity's file system location to your clipboard. | | Create backup | Creates a backup of a project. | | Restore | Recreates a project from a backup. | | Download | Downloads a backup. | | Delete... | Deletes an entity. | | Delete selected | Deletes all selected entities. | | Delete all... | Deletes all related entities. | --- --- url: /app/guides/documentation.md description: >- A step-by-step guide to contributing to Caido's open-source documentation including setup, style guidelines, and pull request submission process. --- # Contributing to the Documentation Caido's documentation is [open source](https://github.com/caido/documentation) and is open to community member contributions. ::: info You will need a [Github](https://github.com) account, [Git](https://git-scm.com/downloads), and the [pnpm](https://pnpm.io/installation) package manager. ::: ## Creating a Workspace To contribute to the documentation, first [fork the repository](https://docs.github.com/en/get-started/quickstart/fork-a-repo) and create a clone. ```bash git clone https://github.com//documentation ``` Then, navigate into the directory and create a new branch. ```bash cd documenation && git branch -b ``` ## Style Guidelines * Pages are primarily written in Markdown, although HTML can be used as well. * Ensure to always link pages in the correct sidebar by editing the `.vitepress/sidebars` file. * Button icons are sourced from the [FontAwesome Classic Solid](https://fontawesome.com/search?f=classic\&s=solid\&o=r) collection. ::: tip To serve the documentation locally and view edits live run `pnpm dev`. ::: ## Publishing When you are finished editing, commit the changes and push them to your fork. ```bash git add . && git commit -m "" && git push ``` Then, open a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) on the [documentation repository](https://github.com/caido/documentation). ::: info To contribute, you must sign the Contributor License Agreement which will be available as a link within the pull request. ::: Your pull request will await and undergo review. You will be notified of any requested changes and its status. Once the changes are merged, you work will appear in the official documentation. --- --- url: /burp-suite/core/overview.md description: Map Burp Suite Pro built-in features to Caido. --- # Core This section maps **Burp Suite Pro** built-in tools and product features to Caido. ## How to Use This Section 1. **Search by Burp feature name** — Use the site search or your browser's find-in-page for the Burp feature you used (for example, `Intruder`, `HTTP history`, or `Collaborator`). 2. **Open the matching page** — Pick the page that best fits what you used in Burp. New to Caido? Start with [Browser & Setup](/burp-suite/core/browser-and-setup), then [Tools](/burp-suite/core/tools). 3. **Read the mapping** — Entries are grouped under **Available**, **Indirectly Available**, and **Not Available**. Each entry explains the Caido equivalent, how it differs from Burp, and links under **Resources**. ::: tip New to Caido? After finding your equivalents, continue with the [application quickstart](/app/quickstart/). ::: ## Pages * **[Browser & Setup](/burp-suite/core/browser-and-setup)** — Browser, mobile, proxy, and TLS setup. * **[Project & Configuration](/burp-suite/core/project-and-configuration)** — Project files, sessions, macros, and saved configuration. * **[Target & Scope](/burp-suite/core/target-and-scope)** — Site map, scope, and target management. * **[Tools](/burp-suite/core/tools)** — Proxy, Repeater, Intruder, Decoder, Collaborator, Logger, and other Burp tools. * **[AI](/burp-suite/core/ai)** — Burp AI features and Caido AI plugins (Shift, Chatio). * **[Scans](/burp-suite/core/scans)** — Scanner, live tasks, and scan operations. * **[Reporting](/burp-suite/core/reporting)** — Exporting findings and reports. Looking for BApps, Bambdas, or custom scan checks? See [Extensibility](/burp-suite/extensibility/overview). --- --- url: /dashboard/guides/create_pat.md --- # Creating a Personal Access Token [PAT](/dashboard/concepts/pat) can be used as the authentication method for the [Caido Cloud API](https://developer.caido.io/client-sdk/reference/api.html). To create a new PAT, visit . You can then click on `+ Create Token`. You will be presented with a form. The options are: * `Name`: A descriptive name for the PAT * `Resource Owner`: Either Yourself or one of the Teams you belong to. * `Expiration`: When will the PAT expire, we strongly recommend setting an expiration date ::: tip If you want to access resources (instances, users, subscription, etc.) for a Team, you need to select that Team as the resource owner. On the contrary, if you want to access resources for your own account, choose `Yourself` as the owner. ::: --- --- url: /dashboard/guides/create_registration_key.md description: Step-by-step instructions to create a registration key. --- # Creating a Registration Key Registration keys are used to register instances automatically in a Team workspace. To learn more check our documentation on the [instance registration process](/app/concepts/instance_registration). To create a registration key, click on the Create Key button. Only admins are allowed to create keys. The options are: * `Description`: Describe the usage for the key * `Prefix`: The instance claimed using this key will have a name with this prefix, if not set the instance name will be purely random * `Expiration`: When will the key expire, we strongly recommend setting an expiration date * `Reusable`: Whether the key can be used to claim more than one instance. If not allowed, the key is revoked on first use. --- --- url: /dashboard/guides/create_team.md description: Step-by-step instructions for creating a new team in the Caido Dashboard. --- # Creating a Team Teams allow you to invite members to a group to collaborate on instances associated with an account workspace. Access management, license assignment, and permission controls for teams are configured via the Caido Dashboard. To permit workspace access, **click** on the `+ Create a Team` button in the Home page. Name the team, enter the email address of the team owner that will act as the initial administrative user, and **click** on the Next button. ## Inviting Team Members Each team member can be assigned one of two roles: * **Admin**: Has full control over a team including its members, billing information, access tokens, and settings. * **Member**: Has access to team instances and workspaces. Can also create access tokens. To add a team member, enter their email address, select a permission level from the `Role` drop-down menu, and click on the `Add Member` button. Once members have been added, **clicking** the Next button allows you to review and confirm the team settings. To edit any details, **click** on the `Back` button. **Clicking** on the `Create Team` button will issue invitation emails to all of the listed members. ## Managing Team Members Once a team is created, members can be managed from the `Users` page of the Caido Dashboard. --- --- url: /app/guides/environment_variables.md description: >- A step-by-step guide to creating and managing environment variables in Caido including global and custom environments with secret variable support. --- # Creating Environment Variables ::: info Global environment variables are accessible across all projects. Custom environment variables are only accessible if the environment is selected. ::: To create a new environment variable, **click** on the `+ Add` button. A new variable row will be added to the table. Next, **click** on the edit button to edit it. Once you have made the desired edits, **click** on the save button to save the variable. Then, depending on if the environment is new or existing, **click** on either the `+ Create` or Update button in the bottom left corner of the pane. ::: warning NOTE If a `Global` environment variable and a custom environment variable share the same name, the custom variable value will take precedence. ::: ::: info Environment variables set to `Secret` are obfuscated in both the frontend and on-disk. ::: *** --- --- url: /app/guides/workflows_findings.md description: >- A step-by-step guide to creating findings in Caido workflows using nodes or JavaScript to document security discoveries and anomalous requests. --- # Creating Findings Findings consist of the following set of properties: * `Title` (*required*): A string value header. * `Request` (*required*): The alias of the associated request. * `Reporter` (*optional*): An string value that identifies the reporting process. * `Description` (*optional*): Details about the finding. * `Dedupe Key` (*optional*): A string value that is matched against the raw request or response to prevent duplicate findings. ::: info The `Dedupe Key` can also be set with the `Check Finding` node. ::: ## Creating a Finding with a Node To create a finding, **click** on the `+ Add Node` button within the workflow editor and **click** on the `+ Add` button attached to the `Create Finding` node. Connect this node to your workflow. The editor of the `Create Finding` node contains input fields for all of the properties available to a finding. ::: info Descriptions support Markdown syntax. ::: ## Creating a Finding with JavaScript To create a finding programmatically, **click** on the `+ Add Node` button within the workflow editor and **click** on the `+ Add` button attached to the `Javascript` node. Connect this node to your workflow. The editor of the `Javascript` node contains a coding environment. Findings are defined as objects and created using the `sdk.findings.create()` method. ```js /** * @param {HttpInput} input * @param {SDK} sdk * @returns {MaybePromise} */ export async function run({ request, response }, sdk) { if (request) { const path = request.getPath(); if (path === "/admin") { let finding = { title: "Admin Path Detected", request: request, reporter: "Admin Path Detection Workflow", description: `A request to the ${request.getPath()} path was proxied.`, dedupeKey: request.getPath() }; await sdk.findings.create(finding); } } } ``` ::: tip [View the workflow SDK reference](https://developer.caido.io/) in the developer documentation to learn more about JavaScript in workflows. ::: ## Viewing Findings All generated findings can be viewed in the `Findings` interface. ::: info Findings are project-specific. ::: --- --- url: /app/guides/shortcuts.md description: >- A step-by-step guide to creating, modifying, and removing keyboard shortcuts in Caido for efficient navigation and command execution. --- # Creating Shortcuts To set, unset, or change shortcut keybindings, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `Shortcuts` tab. ::: info View all of the available [command shortcuts.](/app/reference/command_shortcuts.md) ::: ## Set or Change a Shortcut To set or change a shortcut keybinding, **click** on the command row from the table and execute the keystroke sequence by pressing and holding each keystroke in the desired order. Once the sequence is recorded, **click** on the `Save` button. ## Remove a Shortcut To remove a shortcut keybinding, **click** on the command row from the table and **click** the `Unset` button. --- --- url: /app/guides/workflows_creating.md description: >- A step-by-step guide to creating new workflows in Caido including node addition, connection setup, and workflow configuration. --- # Creating Workflows To create a new workflow, select a [workflow type](/app/concepts/workflows_intro.md) by **clicking** on either the `Passive`, `Active`, or `Convert` tabs and **click** the `+ New workflow` button. Once the workflow is created, you can edit its display name and provide an optional description. ::: tip View the Tutorials section of the documentation for detailed walk-throughs on creating a variety of workflows. ::: ## Adding Nodes To add new nodes, **click** on the `+ Add Node` button and the `+ Add` button of a listed node. In the workflow editor, **click**, **hold** and **drag** a node to rearrange its position. Once the nodes are arranged, **click** and **hold** on a node's output socket and **drag** the line to the next node's input socket to create connections. ## Editing Nodes **Click** on a node to access its individual editor. ::: tip To open the editor in a larger window, **click** on the button. ::: ::: info A node's `Alias` is a unique identifier used to reference it within a workflow. Aliases can only contain the following characters: * Lowercase letters: `a`-`z` * Numbers: `0`-`9` * Symbols: `-`, `_` ::: Once you are done creating the workflow, **click** on the Save button. A message will appear notifying you that the operation was successful and the new workflow will be added to its associated type list. Workflows are enabled by default, to disable a workflow **click** on it's sliding radio button. ::: info By default, workflows are globally available across all your projects. **Click** on `( Switch to project-specific )` within a workflow row to limit its scope. ::: --- --- url: /burp-suite/extensibility/custom-scan-checks.md description: Map Burp Suite Pro custom scan checks to Caido Scanner and workflows. --- # Custom Scan Checks Burp Suite Pro custom scan checks and their Caido equivalents. ::: info Related BApps Several BApp Store extensions also add scan checks — for example, Active Scan++ and Additional Scanner Checks. See [Extensions](/burp-suite/extensibility/extensions) for those mappings. ::: ## Available ### Custom Scan Checks Burp lets you define passive and active scan rules in BCheck format or via the custom scan checks API. Caido lets you define custom checks through the **Scanner** plugin's check definition API for active and passive vulnerability detection. Caido also supplements this with **Passive Workflows** for traffic-level rules that run on every request. Caido splits scanning between the Scanner plugin (issue detection) and workflows (traffic analysis) rather than a single BCheck format. #### Resources * [Scanner: Custom Checks](https://github.com/caido-community/scanner#check-definition) (GitHub) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [Workflows](/app/quickstart/workflows.md) * [Scanner Tutorial](/app/tutorials/scanner.md) --- --- url: /app/guides/automate_extractors.md description: >- A step-by-step guide to using extractors in Caido's Automate feature to create custom columns. --- # Customizing Result Columns with Extractors The `Extractors` tab of an Automate session allows you to create custom columns in a session's result table. Values for these columns are determined based on whether or not a matching condition is met in the responses to the requests. To configure an extractor, define the matcher in the `Regex` input field. [Workflows](/app/concepts/workflows_intro.md) can be applied to matched data that will be presented as the value of a custom column. To test the matcher, input test data into the `Body` input field and **click** on the `Test` button. Successful matches will reflect the data in the `Result` field. Once an extractor has been configured, it will be applied to the session and the custom will be presented in the result table. --- --- url: /app/guides/ui.md description: >- A step-by-step guide to customizing Caido's user interface including pane resizing, font size adjustment, and custom JavaScript/CSS modifications. --- # Customizing the User Interface Caido offers a high-degree of customization, so you can adjust the user-interface to suit your preferences and needs. ## Resizing Panes To customize the layout of an interface, hover your mouse cursor between two panes until it is replaced with the grip icon or its vertical equivalent. Then, **left-click**, **hold**, and **drag** the gutter to resize a pane according to your preferences. ## Adjusting the Font Size Caido allows you to adjust the font size of text within the user-interface and editors separately by providing two horizontal sliders. To access the font size settings, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `Appearance` tab. ## Custom JavaScript and CSS For advanced customization, Caido offers two coding environments in the `Settings` interface. To apply your own CSS rules to the user-interface, open the `Custom CSS` tab. To apply custom JavaScript to the user-interface, open the `Custom JavaScript` tab. *** --- --- url: /dashboard/quickstart.md description: >- Manage your Caido account, billing information, and teams through the web dashboard. --- # Dashboard The Caido Dashboard is a web application that provides a centralized interface for managing your Caido account, subscription, and related services. Accessible at [dashboard.caido.io](https://dashboard.caido.io), once authenticated using your account credentials, you can: * Update your profile information, preferences, and account settings. * View and manage your subscription, payment methods, and billing history. * Create and manage teams, invite members, and configure team settings and permissions. --- --- url: /app/reference/data_storage.md description: >- Find detailed reference information on Caido's internal file structure, storage locations, and database organization across different operating systems. --- # Data Storage All the data Caido creates is stored in a single directory. The default location of this directory is dependent on your operating system: | OS | Location | | ------- | ------------------------------------------------ | | Linux | `~/.local/share/caido` | | MacOS | `~/Library/Application\ Support/io.caido.Caido/` | | Windows | `%APPDATA%\caido\Caido\data` | ::: info The `/logs` subdirectory stores the log files that contain the output from workflow nodes using the [Workflow SDK](https://developer.caido.io/reference/sdks/workflow/). ::: ## Structure ::: danger We do not recommend modifying the files directly as this might result in problems in the application and/or corruption of data. Proceed at your own risk. ::: ### Files * `config.db`: Contains all the non-critical configurations of the instance and the cached data from the cloud for offline support. * `secrets.db`: Contains all the sensitive configurations. Currently, it is AES encrypted with a static secret, but we plan to support a user-specified password in the future. * `projects.db`: Contains the metadata of the projects and hosted files. ::: info Each file is a sqlite3 database in `journal` mode. We usually use pretty recent sqlite3 versions, but we do not make any guarantees on exactly which. ::: ### Subdirectories * `files`: Hosted files that have been uploaded to your instance. * `browsers`: The binary of the browser used for rendering. * `projects`: The data for each project. Each subdirectory name is the UUID of the project. For each project, you will see the following: * `database.caido`: The majority of the data of the project is contained in that database. * `database_raw.caido`: Contains the raw data of the requests and responses, it is split for performance reasons. * `exports`: Folder containing the exported data. ::: info Each file is a sqlite3 database in `wal` mode. If you copy them, ensure to also copy the `-wal` files. ::: --- --- url: /app/tutorials/decode_jwt.md description: >- Learn how to create a convert workflow to decode JSON Web Tokens (JWT) and extract header and payload information. --- # Decode a JWT Workflow In this tutorial, we will create a convert workflow that will decode a [JSON Web Token](https://en.wikipedia.org/wiki/JSON_Web_Token) (JWT). ## Creating a Convert Workflow To begin, navigate to the Workflows interface, select the `Convert` tab, and **click** the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections To add nodes to the workflow, **click** on `+ Add Node` button and then the `+ Add` button of a specific node. For this workflow, the overall node layout will be: * The `Convert Start` node outputs `$convert_start.data` that represents the input that will undergo conversion. * The JWT input will be passed to the `JWT Decode` node, which will extract the header and body segments of the JWT, decode them, and output them separately as `$jwt_decode.header` and `$jwt_decode.payload`. * The `Join` node will concatenate the decoded header and body segments with a specified separator and output `$join.data`. * Once the decoded segments have been processed by the `Join` node, the data will be output, and the workflow will end. ## Decoding a JWT 1. **Click** on the `JWT Decode` node to access its editor and ensure the `$convert_start.data` is [referenced as input data](/app/guides/workflows_references.md). 2) Close the editor window and **click** on the `Join` node to access its editor. 3) Reference `$jwt_decode.header` as the value of the `Left (bytes)` input data and `$jwt_decode.payload` as the value of the `Right (bytes)` input data. 4. Next, type in a `.` character in the `Separator` input field. 5) Close the editor window and **click** on the `Convert End` node to access its editor. 6) Reference `$join.data` as input data. Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ## Testing the Workflow To test the workflow, add the following JWT in the `Input` text area: ```text eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ``` and **click** on the `Run` button. To test the workflow, paste a valid JWT in the `Input` text area and **click** on the `Run` button. A message will appear notifying you that the workflow executed successfully. ## The Result The decoded and joined header and payload of the JWT will appear in the `Output` text area: The full workflow is provided below, ready to be imported. ```json { "description": "Decodes the header and payload segments of a JWT.", "edition": 2, "graph": { "edges": [ { "source": { "exec_alias": "exec", "node_id": 0 }, "target": { "exec_alias": "exec", "node_id": 2 } }, { "source": { "exec_alias": "exec", "node_id": 2 }, "target": { "exec_alias": "exec", "node_id": 3 } }, { "source": { "exec_alias": "exec", "node_id": 3 }, "target": { "exec_alias": "exec", "node_id": 1 } } ], "nodes": [ { "alias": "convert_start", "definition_id": "caido/convert-start", "display": { "x": -90, "y": 0 }, "id": 0, "inputs": [], "name": "Convert Start", "version": "0.1.0" }, { "alias": "convert_end", "definition_id": "caido/convert-end", "display": { "x": 530, "y": 0 }, "id": 1, "inputs": [ { "alias": "data", "value": { "data": "$join.data", "kind": "ref" } } ], "name": "Convert End", "version": "0.1.0" }, { "alias": "jwt_decode", "definition_id": "caido/jwt-decode", "display": { "x": 120, "y": 0 }, "id": 2, "inputs": [ { "alias": "data", "value": { "data": "$convert_start.data", "kind": "ref" } } ], "name": "JWT Decode", "version": "0.1.0" }, { "alias": "join", "definition_id": "caido/join-two", "display": { "x": 330, "y": 0 }, "id": 3, "inputs": [ { "alias": "left", "value": { "data": "$jwt_decode.header", "kind": "ref" } }, { "alias": "right", "value": { "data": "$jwt_decode.payload", "kind": "ref" } }, { "alias": "separator", "value": { "data": ".", "kind": "string" } } ], "name": "Join", "version": "0.1.0" } ] }, "id": "786191d6-a205-4360-9122-715629645280", "kind": "convert", "name": "JWT Decode" } ``` --- --- url: /app/guides/filters_defining.md description: >- A step-by-step guide to creating and defining filter presets in Caido using HTTPQL queries to organize and categorize traffic analysis. --- # Defining a Filter Filters are defined by creating sets of HTTPQL queries referred to as "filter presets". ## Creating a New Filter Preset To create a new filter preset, **click** on the `+ New Preset` button. Once the filter preset is created, you can edit its display name and code alias by typing within the `Name *` and `Alias` input fields. Names and aliases must be unique across all filter presets for referencing purposes. To save the changes, press `ENTER`. ::: info Aliases can only contain the following characters: * Lowercase letters: `a`-`z` * Numbers: `0`-`9` * Symbols: `-`, `_` ::: ### Defining Filters To define filters, **click** in the `Expression` input field to type your HTTPQL queries. ::: tip [View the HTTPQL Reference documentation to learn statement syntax.](/app/reference/httpql.md) ::: ::: info Filter presets do not support the `preset` HTTPQL namespace. ::: Once you have defined the filter, **click** on the Save button to update and save the filter preset. --- --- url: /app/guides/scopes_defining.md description: >- A step-by-step guide to creating and defining scope presets in Caido to include or exclude specific domains and IP addresses from traffic analysis. --- # Defining a Scope Scopes are defined by creating sets of target lists referred to as "scope presets". * Targets added to the `In Scope` list will be included in traffic tables and operations. * Targets added to the `Out of Scope` list will be excluded in traffic tables and operations. The targets in either list will be compared against the value of the `Host` header or destination IP address of proxied requests. ::: info Scope presets are specific to the project they are created in. ::: ::: tip Paths are not supported in scope presets but can be included or excluded from traffic tables with filter presets. ::: ## Creating a New Scope Preset Manually To create a new scope presets, **click** on the `+ New Preset` button and press `ENTER`. Once the scope preset is created, you can edit its display name by typing within the `Name *` input field. To save the new name, press `ENTER`. ### Defining Targets To define targets, **click** in either the `In Scope` input field or `Out of Scope` input field and type in either IP addresses or domains, each on a new line. ::: info Domains can only contain the following characters: * Lowercase letters: `a`-`z` * Numbers: `0`-`9` * Symbols: `.`, `-`, `_`, `*`, `?` ::: ::: tip The `*` and `?` characters in a target domain act as wildcard characters that can be used to account for subdomains and top-level domains: * `*`: Matches multiple characters. * `?`: Matches a single character. For example, to account for all subdomains of `example.com`, add `*.example.com` to a list. ::: Once you have defined the target lists, **click** on the Save button to update and save the scope preset. ## Creating a New Scope from the Context Menu To quickly create a new scope preset and add a request's target domain to be either in-scope or out-of-scope, **right-click** within a request pane to open the context menu, hover your mouse cursor over `Add in Scope` or `Add out of Scope`, and select `+ Create New Scope`. A message will appear notifying you that the operation was successful. You can view the generated scope preset by navigating to the Scopes interface. It will be automatically named with the target domain. --- --- url: /app/guides/data_deleting.md description: >- A step-by-step guide to manually deleting data in Caido using SQLite CLI with detailed instructions and safety warnings. --- # Deleting Data in Caido ::: danger We do not recommend modifying the files directly as this might result in problems in the application and/or corruption of data. Proceed at your own risk. ::: Caido does not currently support a CLI option or desktop application functionality for deleting data. However, although it is not recommended, data can be deleted manually using the SQLite CLI. ::: tip View the [internal files](/app/reference/data_storage.md) reference to learn about the file system structure. ::: ## Finding a Project 1. Decide which project you want to clean. 2. Navigate to your Caido data path. 3. Open the projects database using `sqlite3 projects.db`. 4. Run `select * from projects;` and keep the UUID of the project you want to modify. `08c09bfa-a9fd-41e5-909e-2338a28319f9` ## Preparing the Project Database 1. If Caido is running, kill the application. 2. Navigate to `projects//`. 3. Open the main data: `sqlite3 database.caido` 4. Switch to WAL mode: `PRAGMA main.journal_mode = WAL;` 5. Attach the raw database: `ATTACH DATABASE 'database_raw.caido' AS raw;` 6. Switch to WAL mode: `PRAGMA raw.journal_mode = WAL;` 7. Enable foreign keys: `PRAGMA foreign_keys = ON;` ::: danger Do NOT skip the foreign keys step! ::: ## Deleting Requests ::: danger As traffic is stored in multiple tables, to avoid data corruption, ensure to follow the order of operations below. ::: ### Determining Requests & Responses to Delete The first step is to find a list of requests we want to delete. We will keep that in a temporary table. ```sql CREATE TEMP TABLE requests_to_delete AS SELECT id, response_id, raw_id FROM requests WHERE -- Replace with your condition. ``` For example, the condition could be: `host = "www.youtube.com"`. ```sql CREATE TEMP TABLE responses_to_delete AS WITH RECURSIVE recursive_responses AS ( SELECT r.id, r.parent_id, r.raw_id FROM responses r INNER JOIN requests_to_delete rd ON r.id = rd.response_id UNION ALL SELECT r.id, r.parent_id, r.raw_id FROM responses r INNER JOIN recursive_responses rr ON r.parent_id = rr.id ) SELECT id FROM recursive_responses; ``` ### Cleaning Requests Raw ```sql DELETE FROM requests_raw WHERE id IN ( SELECT raw_id FROM requests_to_delete ); ``` ### Cleaning Responses Raw ```sql DELETE FROM responses_raw WHERE id IN ( SELECT raw_id FROM responses_to_delete ); ``` ### Cleaning Sitemap Entries ```sql DELETE FROM sitemap_entries WHERE request_id IN ( SELECT id FROM requests_to_delete ); ``` ### Cleaning Requests This will also clean `scoped_requests` and `requests_metadata`. ```sql DELETE FROM requests WHERE id IN ( SELECT id FROM requests_to_delete ); ``` ### Cleaning Responses ```sql DELETE FROM responses WHERE id IN ( SELECT id FROM responses_to_delete ); ``` --- --- url: /app/guides/sitemap_deleting.md description: >- A step-by-step guide to deleting sitemap nodes in Caido including parent and child node deletion with permanent removal warnings. --- # Deleting Sitemap Nodes To permanently delete a Sitemap node, **click** on the `...` button attached to it and select Delete entry. ::: warning Deleting a parent node will delete all of its child nodes. ::: --- --- url: /app/guides/assistant_disable.md description: A step-by-step guide to disabling Caido's AI Assistant. --- # Disabling the Assistant ::: warning NOTE No data will be sent to OpenAI once the Assistant is disabled. ::: To disable the Assistant, **click** on the account button in the top-right corner of the Caido user-interface and select Logout. Then, click the `Login` button. In the subsequent permissions prompt, **click** on the Enable the AI assistant feature checkbox to remove its fill, and **click** on the `Allow` button to continue. If the Assistant is disabled, the following message will be on display in its interface: --- --- url: /app/guides/dns_rewrites.md description: >- A step-by-step guide to configuring DNS rewrites in Caido including upstream servers, static IP resolution, and host filtering for custom domain resolution. --- # DNS Rewrites To control the domain to IP address resolutions for specified hosts, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `Network` tab. ## Upstream Servers To resolve DNS queries using an alternative upstream DNS server, instead of your local or ISP's DNS server, either: * Select Google's or Cloudflare's public recursive DNS servers from the drop-down menu. - Or the DNS server can be explicitly defined by **clicking** on the `+` button, providing the server's IP address along with an arbitrary name, and **clicking** `+ Create`. This will add the server as an option in the drop-down menu. ## Static IP To resolve a domain names to a specific IP address, **click** on the `Use static IP` checkbox and type in the IP address in the `Redirect to static IP` input field. ## Hosts To define which hosts your custom DNS configurations do/do not apply to, add them to the `Included Hosts` and `Excluded Hosts` lists. ::: tip Glob syntax (*`*`*) is supported to account for varying subdomains and top-level domains/extended top-level domains. ::: ::: info If multiple rewrites are defined, traffic is directed to the first matching rule. **Click**, **hold**, and **drag** a rule to change its order position. ::: --- --- url: /app/guides/domain_allowlist.md description: >- A step-by-step guide to configuring domain allowlists in Caido CLI, Desktop application, and Docker to control API and interface access security. --- # Domain Allowlist For security, only defined domains can access the Caido API and interface. For example, when utilizing a domain that resolves to `127.0.0.1` to [proxy local traffic](/app/guides/proxy_local.md), the domain must be added to the `Allowed Domains` list. ## Caido CLI To add a domain to the allowlist with the Caido CLI, launch Caido with the `--ui-domain ` command-line option. ```bash --ui-domain example.com ``` ## Desktop Application To add a domain to the allowlist within the Caido desktop application, in the launch window, **click** on the button attached to an instance and select `Edit`. Type a domain name in the `Enter domain (e.g., example.com)` input field and **click** on the `+` button. Once you have defined the allowlist, **click** on the `Save` button to update and save the configuration. ## Docker To add a domain to the allowlist when running the Caido Docker image, either: * Override the default command with: ```bash docker run caido/caido caido-cli --no-renderer-sandbox --no-open --listen 0.0.0.0:8080 --ui-domain=example.com ``` * Or override the Docker Compose: ```yaml services: caido: image: caido/caido command: ["caido-cli", "--no-renderer-sandbox", "--no-open", "--listen", "0.0.0.0:8080", "--ui-domain", "example.com"] ``` --- --- url: /app/reference/download_links.md description: >- Find detailed reference information on Caido download links API and file formats for automated download systems and third-party integrations. --- # Download The download links of Caido are hosted under the domain `caido.download`. ::: warning NOTE You may encounter outdated Google Cloud bucket links. These are deprecated and should not be used. ::: ## Latest To obtain the latest release links, use `GET https://caido.download/releases/latest`. The API will return JSON data resembling: ```json { "id": "01J4KSCQQFY1E9SWEEKJ1WMJWD", "version": "0.47.3", "links": [ { "display": "Linux x86_64", "platform": "linux-x86_64", "kind": "cli", "link": "https://caido.download/releases/v0.47.3/caido-cli-v0.47.3-linux-x86_64.tar.gz", "os": "linux", "arch": "x86_64", "format": "tar.gz", "hash": "gu9MUK4jnHZSQUENeP+29JXz79kPaJO8QHZlagSxLdNJ1qaC3IRwTbcLeU+g2M10WGsdWlrwua6meL1gYQ3tYw==" }, { "display": "macOS Desktop x86_64", "platform": "mac-x86_64", "kind": "desktop", "link": "https://caido.download/releases/v0.47.3/caido-desktop-v0.47.3-mac-x86_64.dmg", "os": "macos", "arch": "x86_64", "format": "dmg", "hash": "1Be/o7cHKaEGELuq24d0yonI9TRCwlWLfzviafYVXKT6RUZ4YBdfI2RNAqZJ6jz+ViLj02XgVciTATJHn2c7xA==" }, { "display": "Windows Desktop x86_64", "platform": "win-x86_64", "kind": "desktop", "link": "https://caido.download/releases/v0.47.3/caido-desktop-v0.47.3-win-x86_64.exe", "os": "windows", "arch": "x86_64", "format": "exe", "hash": "p8Rr3wOe3Fbm7eETOogP0ulpifeDFAm+gVxDVItuK4B5wbAOgqqjwZEKoJArcDnAclvmVRtOAQlSXM7dg+amZA==" } // ... Other links ], "released_at": "2025-03-27T19:52:00.851138Z" } ``` | Field | Description | |-------|-------------| | `display` | The display name. | | `platform` | (Deprecated) Operating system (`linux`/`mac`/`win`) + `-` + architecture (`x86_64`/`aarch64`). | | `kind` | Either `desktop` or `cli` ([CLI vs Desktop](/app/concepts/cli_vs_desktop.md)). | | `link` | The download link. | | `os` | The operating system of the binary (`linux`/`macos`/`windows`). | | `arch` | The architecture of the binary (`x86_64`/`aarch64`). | | `format` | The archive/binary format (`zip`/`tar.gz`/`deb`/`AppImage`/`dmg`/`exe`). | | `hash` | The Base64-encoded SHA512 hash of the file (may be `null` for older releases). | ::: info If you prefer a file-based hash, we also build `[link].sha256` and `[link].sha512` files for each binary. These are hex encoded and will produce the same output as `shasum -a 256` and `shasum -a 512`. ::: ::: warning The download links **will redirect** to a signed URL, ensure your download client follows redirects. ::: --- --- url: /app/troubleshooting/download.md description: Download issue due to IP address blocking and resolutions. --- # Download Issues ## "This site can't be reached" This error may occur when your IP address has been blocked by the storage provider's firewall. If you encounter this error message after attempting to download Caido use a VPN or change your DNS provider and then refresh the page. --- --- url: /app/tutorials/drop.md --- # Drop The [Drop](https://github.com/caido-community/drop) plugin gives you the ability to share project data, over an end-to-end encrypted channel, with other Caido users, including: * [Replay Sessions](/app/quickstart/replay.md) * [Match & Replace Rules](/app/quickstart/match_replace.md) * [Scope Presets](/app/quickstart/scopes.md) * [Filter Presets](/app/quickstart/filters.md) ::: info Support for sharing [workflows](/app/quickstart/workflows.md), [files](/app/quickstart/files.md), [findings](/app/quickstart/findings.md), and [HTTPQL](/app/reference/httpql.md) query statements is planned for upcoming releases. ::: In this tutorial you will learn how to collaborate with other Caido users as well as how to self-host the plugin's backend server. ::: info Drop is available for [installation](/app/guides/plugins_installing.md) in the `Community` tab of the Plugin interface. ::: ## Collaboration To ensure data is shared securely, Drop users are identified by **Share Codes** that are associated with their [Pretty Good Privacy (PGP)](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) public encryption key. To collaborate with another Caido user, paste their **Share Code** in the input field in the `Friends` section of the `Settings` tab. Or, send your code to them to do the same. Once a user has been added to your friends list, data can be sent to them via messages by selecting their alias from the Drop to... drop-down menu that is available in certain Caido interfaces. To accept a message from another user, **click** on Claim button in either the notification banner or the `Received Messages` tab of the Drop interface. *** ::: warning NOTE Drop is not a storage mechanism, as all messages will be stored on the server for a maximum of 7 days. Due to this temporary lifespan, all messages should be assumed to be ephemeral. ::: ## Self-Hosting As Drop requires a centralized server, Caido provides the default message broker service at `drop.cai.do`. All messages sent via Drop are encrypted using the public key of the recipient before they reach the server. However, for users with privacy concerns or organizations that must be in compliance with regulations, it is possible to [host your own Drop API server](https://github.com/caido-community/drop/blob/main/packages/server/README.md). --- --- url: /app/tutorials/feature_flags.md description: >- Learn how to create Match & Replace rules in Caido to gain access to additional client-side features. --- # Enable Feature Flags In this tutorial, you will learn how to configure Match & Replace rules to gain access to features intended for admin users in an intentionally vulnerable application from Caido's Web Security Labs. Many applications implement feature flag services to hide or display elements and conduct A/B testing for upcoming features. Typically, access to these additional features is determined by Boolean values, user permission levels, or subscription tiers. However, when access checks are only performed client-side, they can be easily bypassed by creating Match & Replace rules to modify the response before it reaches the client. ## Match & Replace Lab Walkthrough ::: warning NOTE To access the lab, navigate to , sign in with your account credentials, and **click** on the `Launch hub` button. ::: The Match & Replace Lab displays different user-interface components based on a user's permission role: either `basic` or `admin`. 1. With your proxy settings enabled, **click** on the Open in new tab button to launch your lab instance. 2. Within the corresponding response is a `user` object: ```js [user] let user = { name: "john", role: "basic", featureFlags: [] // Update this array to enable/disable features }; ``` 3. If `(user.role === "admin")` in the `checkUserRole()` function: ```js [checkUserRole()] // Check if role is admin and update feature flags function checkUserRole() { if (user.role === "admin") { displayAdminUI(); } displayUserInfo(); checkFeatureFlags(); } ``` 4. The `displayAdminUI()` function will execute and append an administrative panel to the page: ```js [displayAdminUI()] // Display admin UI elements function displayAdminUI() { const adminContainer = document.createElement('div'); adminContainer.id = 'admin-container'; adminContainer.className = 'container'; adminContainer.style.marginTop = '20px'; adminContainer.style.backgroundColor = 'var(--card-bg)'; adminContainer.style.border = '1px solid #333'; const heading = document.createElement('h2'); heading.textContent = 'Admin Controls'; const adminButton = document.createElement('button'); adminButton.textContent = 'Do admin action'; adminButton.style.padding = '8px 16px'; adminButton.style.backgroundColor = 'var(--button-bg)'; adminButton.style.color = 'var(--text)'; adminButton.style.border = 'none'; adminButton.style.borderRadius = '4px'; adminButton.style.cursor = 'pointer'; adminButton.addEventListener('click', function() { fetch("/superSecretAdminStuff.php").then(a => a.json()).then(data => { alert(data.message); }); }); adminContainer.appendChild(heading); adminContainer.appendChild(adminButton); document.body.appendChild(adminContainer); } ``` 5. The `checkFeatureFlags()` function will parse the `user.featureFlags` property array and append additional components to the user-interface: ```js [checkFeatureFlags()] // Check feature flags and activate features function checkFeatureFlags() { // Check for bouncy ball feature if (user.featureFlags.includes('bouncy-ball')) { createBouncyBall(); } // Check for sparkle background feature if (user.featureFlags.includes('sparkle-background')) { enableSparkleBackground(); } } // Create and show bouncy ball function createBouncyBall() { const ball = document.createElement('div'); ball.className = 'bouncy-ball'; // Random starting position ball.style.left = Math.random() * 80 + 10 + '%'; ball.style.top = Math.random() * 50 + 25 + '%'; document.body.appendChild(ball); } // Enable sparkle background function enableSparkleBackground() { document.body.classList.add('sparkle-bg'); // Create sparkles setInterval(createSparkle, 300); } // Create individual sparkle function createSparkle() { const sparkle = document.createElement('div'); sparkle.className = 'sparkle'; // Random position, size and color const size = Math.random() * 5 + 2; sparkle.style.width = size + 'px'; sparkle.style.height = size + 'px'; sparkle.style.left = Math.random() * 100 + '%'; sparkle.style.top = Math.random() * 100 + '%'; const colors = ['var(--accent)', '#FFC0CB', '#ADD8E6', '#90EE90', 'var(--text)']; sparkle.style.background = colors[Math.floor(Math.random() * colors.length)]; document.body.appendChild(sparkle); // Fade out and remove setTimeout(() => { sparkle.style.opacity = '0'; sparkle.style.transition = 'opacity 1s'; setTimeout(() => { document.body.removeChild(sparkle); }, 1000); }, 1000); } ``` ### Accessing the Administrative Panel To display the administrative panel: 1. Navigate to the Match & Replace interface and **click** on the `+ New Rule` button. ::: tip **Click** on the button to rename the rule to a name that quickly identifies the rule's purpose such as "Change Role: basic to admin". ::: 2. Select `Response Body` from the `Section` drop-down menu and `String` from the `Matcher` drop-down menu. 3. Type in `basic` in the `Matcher` input field and `admin` in the `Replacer` input field. 4. Next, **click** on the `Intercept` checkbox to apply the modification to all proxied responses. 5. **Click** on the Update button to add the rule to the Default Collection. 6. Expand the Default Collection by **clicking** on the button attached to it and **click** on the rule's associated checkbox to enable it. 7) Reload the page. Since the rule automatically changed `role` from `"basic"` to `"admin"` in the response before it reached the browser, the conditional check is satisfied and `displayAdminUI()` is executed, rendering the administrative panel in the user-interface. ### Accessing the Additional Features To access the additional user-interface features that are only intended for admin users: 1. Copy `featureFlags: []` from the response body. ::: warning NOTE When copying values to match against from requests or responses, ensure to [view their raw representation](/app/guides/request_response_modes.md) to ensure correct formatting. ::: 2. Create another rule in the Match & Replace interface that targets the `Request Body`. 3. Select `String` from the `Matcher` drop-down menu and paste `featureFlags: []` in the input field. 4. In the `Replacer` input field, type in `featureFlags: ['bouncy-ball', 'sparkle-background']`. 5. **Click** on the `Intercept` checkbox, the Update button, and the rule's associated checkbox in the Default Collection to add and enable the rule. 6) Reload the page. In combination with the previous rule, since the rule automatically added the features to the array in the response before it reached the browser, when `checkFeatureFlags()` is executed, `if (user.featureFlags.includes('bouncy-ball'))` and `if (user.featureFlags.includes('sparkle-background'))` is satisfied and the `createBouncyBall()` and `enableSparkleBackground()` functions are executed. ### Additional Modification Rules can also be created to target entire blocks instead of just individual values or lines. For example, by matching against the `setTimeout` function and replacing it with an empty string or comment, you can effectively remove the code from the page. #### Matcher: String ```txt // Fade out and remove setTimeout(() => { sparkle.style.opacity = '0'; sparkle.style.transition = 'opacity 1s'; setTimeout(() => { document.body.removeChild(sparkle); }, 1000); }, 1000); ``` #### Replacer: String ```txt // Leave empty or add this comment ``` Now, once the page is reloaded, the sparkles will persist. --- --- url: /app/troubleshooting/debugging.md description: >- Enabling debug logging in Caido CLI and Desktop application for troubleshooting and bug reporting purposes. --- # Enabling Debug Mode To assist with troubleshooting, Caido can be configured to include debug entries in the generated log files. ## Caido CLI To enable the inclusion of debug entries in the log files with the Caido CLI, launch Caido with the `--debug` command-line option. ```bash caido --debug ``` ## Desktop Application To enable the inclusion of debug entries in the log files within the Caido desktop application, in the launch window, **click** on the button attached to an instance and select `Edit`. Then, **click** on Advanced to expand the drop-down settings menu options and **click** on the `Debug logging` checkbox. **Click** on the `Save` button to update and save the configuration. ::: warning NOTE Debug information is required when [reporting bugs](/app/troubleshooting/report_bug.md) to the Caido team. ::: --- --- url: /app/guides/plugins_managing.md description: A step-by-step guide to enabling/disabling plugins in Caido. --- # Enabling/Disabling Plugins Caido plugin packages consist of a backend component, frontend component, or both and each component can be enabled/disabled independently. To enable/disable a plugin component, navigate to the `Installed` tab within the Plugins interface, **click** on the button of a plugin row, and **click** on either the backend or frontend checkbox to toggle its fill. --- --- url: /app/guides/match_replace_encoding.md description: >- A step-by-step guide to encoding request and response body data in Caido's Match & Replace feature using workflows and various encoding methods. --- # Encoding Request Body Data To encode the body data of either HTTP requests or responses, **click** on the `Section` drop-down menu and select either `Request Body` or `Response Body`. Next, select an option from the `Matcher` drop-down menu to specify what data to encode: * `Full`: All of the body data. * `Regex`: Matches a value determined by a regular expression. * `String`: Matches a string value. Then, select the `Workflow` option from the `Replacer` drop-down menu and select the encoding method. Select the traffic source/s and **click** on the `+ Add` button to add the rule to the Default Collection. ::: tip Give rules descriptive names for quick identification of their purpose. ::: To enable the rule, **click** on its associated checkbox. Applied rules are listed in the `Active Rules` table. --- --- url: /app/quickstart/environment.md description: >- A step-by-step guide to Caido's Environment feature for managing variables and context switching during security testing. --- # Environment The `Environment` interface gives you the ability to define collections of variables that can be inserted into requests, enabling quick context switching while testing. ::: tip HOW-TO GUIDE * [Creating Environment Variables](/app/guides/environment_variables.md) ::: --- --- url: /app/guides/exports_requests.md description: >- A step-by-step guide to exporting request data from Caido traffic tables in JSON or CSV format for analysis, reporting, and integration with other security tools. --- # Exporting Request Data By **clicking** on the `Export` drop-down menu, you can export the data stored in traffic tables. Once a selection is made between `Export all` or `Export current rows`, the data can be exported as either a `.json` or `.csv` file. ::: tip To further refine which requests are included when exporting the currently displayed rows, use HTTPQL query statements. ::: The files will be available for download in the `Exports` interface. ## JSON Format ```json [ {"id":1,"host":"www.example.com","method":"GET","path":"/","length":500,"port":443,"raw":"R0VUIC8gSFRUUC8xLjENCkhvc3Q6IHd3dy5leGFtcGxlLmNvbQ0KVXNlci1BZ2VudDogTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTQxLjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTQxLjANCkFjY2VwdDogdGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksKi8qO3E9MC44DQpBY2NlcHQtTGFuZ3VhZ2U6IGVuLVVTLGVuO3E9MC41DQpBY2NlcHQtRW5jb2Rpbmc6IGd6aXAsIGRlZmxhdGUsIGJyLCB6c3RkDQpETlQ6IDENCkNvbm5lY3Rpb246IGtlZXAtYWxpdmUNClVwZ3JhZGUtSW5zZWN1cmUtUmVxdWVzdHM6IDENClNlYy1GZXRjaC1EZXN0OiBkb2N1bWVudA0KU2VjLUZldGNoLU1vZGU6IG5hdmlnYXRlDQpTZWMtRmV0Y2gtU2l0ZTogbm9uZQ0KU2VjLUZldGNoLVVzZXI6ID8xDQpQcmlvcml0eTogdT0wLCBpDQpQcmFnbWE6IG5vLWNhY2hlDQpDYWNoZS1Db250cm9sOiBuby1jYWNoZQ0KDQo=","is_tls":true,"query":"","file_extension":null,"source":"intercept","response":{"id":1489,"status_code":200,"raw":"SFRUUC8xLjEgMjAwIE9LDQpBY2NlcHQtUmFuZ2VzOiBieXRlcw0KQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwNCkVUYWc6ICI4NDIzOGRmYzgwOTJlNWQ5YzBkYWM4ZWY5MzM3MWEwNzoxNzM2Nzk5MDgwLjEyMTEzNCINCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMTMgSmFuIDIwMjUgMjA6MTE6MjAgR01UDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkNvbnRlbnQtTGVuZ3RoOiAxMjU2DQpDYWNoZS1Db250cm9sOiBtYXgtYWdlPTk0OA0KRGF0ZTogU2F0LCAxNiBBdWcgMjAyNSAxMjo1NTozNSBHTVQNCkFsdC1TdmM6IGgzPSI6NDQzIjsgbWE9OTM2MDAsaDMtMjk9Ijo0NDMiOyBtYT05MzYwMA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KDQo8IWRvY3R5cGUgaHRtbD4KPGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPkV4YW1wbGUgRG9tYWluPC90aXRsZT4KCiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4KICAgIDxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiAvPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPgogICAgPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KICAgIGJvZHkgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjI7CiAgICAgICAgbWFyZ2luOiAwOwogICAgICAgIHBhZGRpbmc6IDA7CiAgICAgICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCAiT3BlbiBTYW5zIiwgIkhlbHZldGljYSBOZXVlIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsKICAgICAgICAKICAgIH0KICAgIGRpdiB7CiAgICAgICAgd2lkdGg6IDYwMHB4OwogICAgICAgIG1hcmdpbjogNWVtIGF1dG87CiAgICAgICAgcGFkZGluZzogMmVtOwogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZGZkZmY7CiAgICAgICAgYm9yZGVyLXJhZGl1czogMC41ZW07CiAgICAgICAgYm94LXNoYWRvdzogMnB4IDNweCA3cHggMnB4IHJnYmEoMCwwLDAsMC4wMik7CiAgICB9CiAgICBhOmxpbmssIGE6dmlzaXRlZCB7CiAgICAgICAgY29sb3I6ICMzODQ4OGY7CiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQogICAgQG1lZGlhIChtYXgtd2lkdGg6IDcwMHB4KSB7CiAgICAgICAgZGl2IHsKICAgICAgICAgICAgbWFyZ2luOiAwIGF1dG87CiAgICAgICAgICAgIHdpZHRoOiBhdXRvOwogICAgICAgIH0KICAgIH0KICAgIDwvc3R5bGU+ICAgIAo8L2hlYWQ+Cgo8Ym9keT4KPGRpdj4KICAgIDxoMT5FeGFtcGxlIERvbWFpbjwvaDE+CiAgICA8cD5UaGlzIGRvbWFpbiBpcyBmb3IgdXNlIGluIGlsbHVzdHJhdGl2ZSBleGFtcGxlcyBpbiBkb2N1bWVudHMuIFlvdSBtYXkgdXNlIHRoaXMKICAgIGRvbWFpbiBpbiBsaXRlcmF0dXJlIHdpdGhvdXQgcHJpb3IgY29vcmRpbmF0aW9uIG9yIGFza2luZyBmb3IgcGVybWlzc2lvbi48L3A+CiAgICA8cD48YSBocmVmPSJodHRwczovL3d3dy5pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPk1vcmUgaW5mb3JtYXRpb24uLi48L2E+PC9wPgo8L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg==","length":1615,"alteration":"none","edited":false,"parent_id":null,"created_at":1755348935578},"alteration":"none","edited":false,"parent_id":null,"created_at":1755348935446}, {"id":2,"host":"www.example.com","method":"GET","path":"/favicon.ico","length":502,"port":443,"raw":"R0VUIC9mYXZpY29uLmljbyBIVFRQLzEuMQ0KSG9zdDogd3d3LmV4YW1wbGUuY29tDQpVc2VyLUFnZW50OiBNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0OyBydjoxNDEuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC8xNDEuMA0KQWNjZXB0OiBpbWFnZS9hdmlmLGltYWdlL3dlYnAsaW1hZ2UvcG5nLGltYWdlL3N2Zyt4bWwsaW1hZ2UvKjtxPTAuOCwqLyo7cT0wLjUNCkFjY2VwdC1MYW5ndWFnZTogZW4tVVMsZW47cT0wLjUNCkFjY2VwdC1FbmNvZGluZzogZ3ppcCwgZGVmbGF0ZSwgYnIsIHpzdGQNCkROVDogMQ0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KUmVmZXJlcjogaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vDQpTZWMtRmV0Y2gtRGVzdDogaW1hZ2UNClNlYy1GZXRjaC1Nb2RlOiBuby1jb3JzDQpTZWMtRmV0Y2gtU2l0ZTogc2FtZS1vcmlnaW4NClByaW9yaXR5OiB1PTYNClByYWdtYTogbm8tY2FjaGUNCkNhY2hlLUNvbnRyb2w6IG5vLWNhY2hlDQoNCg==","is_tls":true,"query":"","file_extension":".ico","source":"intercept","response":{"id":1490,"status_code":404,"raw":"SFRUUC8xLjEgNDA0IE5vdCBGb3VuZA0KQWNjZXB0LVJhbmdlczogYnl0ZXMNCkNvbnRlbnQtVHlwZTogdGV4dC9odG1sDQpFVGFnOiAiODQyMzhkZmM4MDkyZTVkOWMwZGFjOGVmOTMzNzFhMDc6MTczNjc5OTA4MC4xMjExMzQiDQpMYXN0LU1vZGlmaWVkOiBNb24sIDEzIEphbiAyMDI1IDIwOjExOjIwIEdNVA0KU2VydmVyOiBBa2FtYWlOZXRTdG9yYWdlDQpDb250ZW50LUxlbmd0aDogMTI1Ng0KRXhwaXJlczogU2F0LCAxNiBBdWcgMjAyNSAxMjo1NTozNSBHTVQNCkNhY2hlLUNvbnRyb2w6IG1heC1hZ2U9MCwgbm8tY2FjaGUsIG5vLXN0b3JlDQpQcmFnbWE6IG5vLWNhY2hlDQpEYXRlOiBTYXQsIDE2IEF1ZyAyMDI1IDEyOjU1OjM1IEdNVA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KDQo8IWRvY3R5cGUgaHRtbD4KPGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPkV4YW1wbGUgRG9tYWluPC90aXRsZT4KCiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4KICAgIDxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiAvPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPgogICAgPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KICAgIGJvZHkgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjI7CiAgICAgICAgbWFyZ2luOiAwOwogICAgICAgIHBhZGRpbmc6IDA7CiAgICAgICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCAiT3BlbiBTYW5zIiwgIkhlbHZldGljYSBOZXVlIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsKICAgICAgICAKICAgIH0KICAgIGRpdiB7CiAgICAgICAgd2lkdGg6IDYwMHB4OwogICAgICAgIG1hcmdpbjogNWVtIGF1dG87CiAgICAgICAgcGFkZGluZzogMmVtOwogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZGZkZmY7CiAgICAgICAgYm9yZGVyLXJhZGl1czogMC41ZW07CiAgICAgICAgYm94LXNoYWRvdzogMnB4IDNweCA3cHggMnB4IHJnYmEoMCwwLDAsMC4wMik7CiAgICB9CiAgICBhOmxpbmssIGE6dmlzaXRlZCB7CiAgICAgICAgY29sb3I6ICMzODQ4OGY7CiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQogICAgQG1lZGlhIChtYXgtd2lkdGg6IDcwMHB4KSB7CiAgICAgICAgZGl2IHsKICAgICAgICAgICAgbWFyZ2luOiAwIGF1dG87CiAgICAgICAgICAgIHdpZHRoOiBhdXRvOwogICAgICAgIH0KICAgIH0KICAgIDwvc3R5bGU+ICAgIAo8L2hlYWQ+Cgo8Ym9keT4KPGRpdj4KICAgIDxoMT5FeGFtcGxlIERvbWFpbjwvaDE+CiAgICA8cD5UaGlzIGRvbWFpbiBpcyBmb3IgdXNlIGluIGlsbHVzdHJhdGl2ZSBleGFtcGxlcyBpbiBkb2N1bWVudHMuIFlvdSBtYXkgdXNlIHRoaXMKICAgIGRvbWFpbiBpbiBsaXRlcmF0dXJlIHdpdGhvdXQgcHJpb3IgY29vcmRpbmF0aW9uIG9yIGFza2luZyBmb3IgcGVybWlzc2lvbi48L3A+CiAgICA8cD48YSBocmVmPSJodHRwczovL3d3dy5pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPk1vcmUgaW5mb3JtYXRpb24uLi48L2E+PC9wPgo8L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg==","length":1648,"alteration":"none","edited":false,"parent_id":null,"created_at":1755348935754},"alteration":"none","edited":false,"parent_id":null,"created_at":1755348935616}, {"id":3,"host":"www.example.com","method":"GET","path":"/path","length":461,"port":443,"raw":"R0VUIC9wYXRoIEhUVFAvMS4xDQpIb3N0OiB3d3cuZXhhbXBsZS5jb20NClVzZXItQWdlbnQ6IE1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQ7IHJ2OjE0MS4wKSBHZWNrby8yMDEwMDEwMSBGaXJlZm94LzE0MS4wDQpBY2NlcHQ6IHRleHQvaHRtbCxhcHBsaWNhdGlvbi94aHRtbCt4bWwsYXBwbGljYXRpb24veG1sO3E9MC45LCovKjtxPTAuOA0KQWNjZXB0LUxhbmd1YWdlOiBlbi1VUyxlbjtxPTAuNQ0KQWNjZXB0LUVuY29kaW5nOiBnemlwLCBkZWZsYXRlLCBiciwgenN0ZA0KRE5UOiAxDQpDb25uZWN0aW9uOiBrZWVwLWFsaXZlDQpVcGdyYWRlLUluc2VjdXJlLVJlcXVlc3RzOiAxDQpTZWMtRmV0Y2gtRGVzdDogZG9jdW1lbnQNClNlYy1GZXRjaC1Nb2RlOiBuYXZpZ2F0ZQ0KU2VjLUZldGNoLVNpdGU6IG5vbmUNClNlYy1GZXRjaC1Vc2VyOiA/MQ0KUHJpb3JpdHk6IHU9MCwgaQ0KDQo=","is_tls":true,"query":"","file_extension":null,"source":"intercept","response":{"id":1491,"status_code":404,"raw":"SFRUUC8xLjEgNDA0IE5vdCBGb3VuZA0KQWNjZXB0LVJhbmdlczogYnl0ZXMNCkNvbnRlbnQtVHlwZTogdGV4dC9odG1sDQpFVGFnOiAiODQyMzhkZmM4MDkyZTVkOWMwZGFjOGVmOTMzNzFhMDc6MTczNjc5OTA4MC4xMjExMzQiDQpMYXN0LU1vZGlmaWVkOiBNb24sIDEzIEphbiAyMDI1IDIwOjExOjIwIEdNVA0KU2VydmVyOiBBa2FtYWlOZXRTdG9yYWdlDQpDb250ZW50LUxlbmd0aDogMTI1Ng0KRXhwaXJlczogU2F0LCAxNiBBdWcgMjAyNSAxMjo1NTozOCBHTVQNCkNhY2hlLUNvbnRyb2w6IG1heC1hZ2U9MCwgbm8tY2FjaGUsIG5vLXN0b3JlDQpQcmFnbWE6IG5vLWNhY2hlDQpEYXRlOiBTYXQsIDE2IEF1ZyAyMDI1IDEyOjU1OjM4IEdNVA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KDQo8IWRvY3R5cGUgaHRtbD4KPGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPkV4YW1wbGUgRG9tYWluPC90aXRsZT4KCiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4KICAgIDxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiAvPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPgogICAgPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KICAgIGJvZHkgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjI7CiAgICAgICAgbWFyZ2luOiAwOwogICAgICAgIHBhZGRpbmc6IDA7CiAgICAgICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCAiT3BlbiBTYW5zIiwgIkhlbHZldGljYSBOZXVlIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsKICAgICAgICAKICAgIH0KICAgIGRpdiB7CiAgICAgICAgd2lkdGg6IDYwMHB4OwogICAgICAgIG1hcmdpbjogNWVtIGF1dG87CiAgICAgICAgcGFkZGluZzogMmVtOwogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZGZkZmY7CiAgICAgICAgYm9yZGVyLXJhZGl1czogMC41ZW07CiAgICAgICAgYm94LXNoYWRvdzogMnB4IDNweCA3cHggMnB4IHJnYmEoMCwwLDAsMC4wMik7CiAgICB9CiAgICBhOmxpbmssIGE6dmlzaXRlZCB7CiAgICAgICAgY29sb3I6ICMzODQ4OGY7CiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQogICAgQG1lZGlhIChtYXgtd2lkdGg6IDcwMHB4KSB7CiAgICAgICAgZGl2IHsKICAgICAgICAgICAgbWFyZ2luOiAwIGF1dG87CiAgICAgICAgICAgIHdpZHRoOiBhdXRvOwogICAgICAgIH0KICAgIH0KICAgIDwvc3R5bGU+ICAgIAo8L2hlYWQ+Cgo8Ym9keT4KPGRpdj4KICAgIDxoMT5FeGFtcGxlIERvbWFpbjwvaDE+CiAgICA8cD5UaGlzIGRvbWFpbiBpcyBmb3IgdXNlIGluIGlsbHVzdHJhdGl2ZSBleGFtcGxlcyBpbiBkb2N1bWVudHMuIFlvdSBtYXkgdXNlIHRoaXMKICAgIGRvbWFpbiBpbiBsaXRlcmF0dXJlIHdpdGhvdXQgcHJpb3IgY29vcmRpbmF0aW9uIG9yIGFza2luZyBmb3IgcGVybWlzc2lvbi48L3A+CiAgICA8cD48YSBocmVmPSJodHRwczovL3d3dy5pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPk1vcmUgaW5mb3JtYXRpb24uLi48L2E+PC9wPgo8L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg==","length":1648,"alteration":"none","edited":false,"parent_id":null,"created_at":1755348939013},"alteration":"none","edited":false,"parent_id":null,"created_at":1755348938708} ] ``` ## CSV Format ```csv id,host,method,path,length,port,raw,is_tls,query,file_extension,source,alteration,edited,parent_id,created_at,response_id,response_status_code,response_raw,response_length,response_alteration,response_edited,response_parent_id,response_created_at 1,www.example.com,GET,/,500,443,R0VUIC8gSFRUUC8xLjENCkhvc3Q6IHd3dy5leGFtcGxlLmNvbQ0KVXNlci1BZ2VudDogTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NDsgcnY6MTQxLjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMTQxLjANCkFjY2VwdDogdGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksKi8qO3E9MC44DQpBY2NlcHQtTGFuZ3VhZ2U6IGVuLVVTLGVuO3E9MC41DQpBY2NlcHQtRW5jb2Rpbmc6IGd6aXAsIGRlZmxhdGUsIGJyLCB6c3RkDQpETlQ6IDENCkNvbm5lY3Rpb246IGtlZXAtYWxpdmUNClVwZ3JhZGUtSW5zZWN1cmUtUmVxdWVzdHM6IDENClNlYy1GZXRjaC1EZXN0OiBkb2N1bWVudA0KU2VjLUZldGNoLU1vZGU6IG5hdmlnYXRlDQpTZWMtRmV0Y2gtU2l0ZTogbm9uZQ0KU2VjLUZldGNoLVVzZXI6ID8xDQpQcmlvcml0eTogdT0wLCBpDQpQcmFnbWE6IG5vLWNhY2hlDQpDYWNoZS1Db250cm9sOiBuby1jYWNoZQ0KDQo=,true,,,intercept,none,false,,1755348935446,1489,200,SFRUUC8xLjEgMjAwIE9LDQpBY2NlcHQtUmFuZ2VzOiBieXRlcw0KQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwNCkVUYWc6ICI4NDIzOGRmYzgwOTJlNWQ5YzBkYWM4ZWY5MzM3MWEwNzoxNzM2Nzk5MDgwLjEyMTEzNCINCkxhc3QtTW9kaWZpZWQ6IE1vbiwgMTMgSmFuIDIwMjUgMjA6MTE6MjAgR01UDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkNvbnRlbnQtTGVuZ3RoOiAxMjU2DQpDYWNoZS1Db250cm9sOiBtYXgtYWdlPTk0OA0KRGF0ZTogU2F0LCAxNiBBdWcgMjAyNSAxMjo1NTozNSBHTVQNCkFsdC1TdmM6IGgzPSI6NDQzIjsgbWE9OTM2MDAsaDMtMjk9Ijo0NDMiOyBtYT05MzYwMA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KDQo8IWRvY3R5cGUgaHRtbD4KPGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPkV4YW1wbGUgRG9tYWluPC90aXRsZT4KCiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4KICAgIDxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiAvPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPgogICAgPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KICAgIGJvZHkgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjI7CiAgICAgICAgbWFyZ2luOiAwOwogICAgICAgIHBhZGRpbmc6IDA7CiAgICAgICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCAiT3BlbiBTYW5zIiwgIkhlbHZldGljYSBOZXVlIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsKICAgICAgICAKICAgIH0KICAgIGRpdiB7CiAgICAgICAgd2lkdGg6IDYwMHB4OwogICAgICAgIG1hcmdpbjogNWVtIGF1dG87CiAgICAgICAgcGFkZGluZzogMmVtOwogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZGZkZmY7CiAgICAgICAgYm9yZGVyLXJhZGl1czogMC41ZW07CiAgICAgICAgYm94LXNoYWRvdzogMnB4IDNweCA3cHggMnB4IHJnYmEoMCwwLDAsMC4wMik7CiAgICB9CiAgICBhOmxpbmssIGE6dmlzaXRlZCB7CiAgICAgICAgY29sb3I6ICMzODQ4OGY7CiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQogICAgQG1lZGlhIChtYXgtd2lkdGg6IDcwMHB4KSB7CiAgICAgICAgZGl2IHsKICAgICAgICAgICAgbWFyZ2luOiAwIGF1dG87CiAgICAgICAgICAgIHdpZHRoOiBhdXRvOwogICAgICAgIH0KICAgIH0KICAgIDwvc3R5bGU+ICAgIAo8L2hlYWQ+Cgo8Ym9keT4KPGRpdj4KICAgIDxoMT5FeGFtcGxlIERvbWFpbjwvaDE+CiAgICA8cD5UaGlzIGRvbWFpbiBpcyBmb3IgdXNlIGluIGlsbHVzdHJhdGl2ZSBleGFtcGxlcyBpbiBkb2N1bWVudHMuIFlvdSBtYXkgdXNlIHRoaXMKICAgIGRvbWFpbiBpbiBsaXRlcmF0dXJlIHdpdGhvdXQgcHJpb3IgY29vcmRpbmF0aW9uIG9yIGFza2luZyBmb3IgcGVybWlzc2lvbi48L3A+CiAgICA8cD48YSBocmVmPSJodHRwczovL3d3dy5pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPk1vcmUgaW5mb3JtYXRpb24uLi48L2E+PC9wPgo8L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg==,1615,none,false,,1755348935578 2,www.example.com,GET,/favicon.ico,502,443,R0VUIC9mYXZpY29uLmljbyBIVFRQLzEuMQ0KSG9zdDogd3d3LmV4YW1wbGUuY29tDQpVc2VyLUFnZW50OiBNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0OyBydjoxNDEuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC8xNDEuMA0KQWNjZXB0OiBpbWFnZS9hdmlmLGltYWdlL3dlYnAsaW1hZ2UvcG5nLGltYWdlL3N2Zyt4bWwsaW1hZ2UvKjtxPTAuOCwqLyo7cT0wLjUNCkFjY2VwdC1MYW5ndWFnZTogZW4tVVMsZW47cT0wLjUNCkFjY2VwdC1FbmNvZGluZzogZ3ppcCwgZGVmbGF0ZSwgYnIsIHpzdGQNCkROVDogMQ0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KUmVmZXJlcjogaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vDQpTZWMtRmV0Y2gtRGVzdDogaW1hZ2UNClNlYy1GZXRjaC1Nb2RlOiBuby1jb3JzDQpTZWMtRmV0Y2gtU2l0ZTogc2FtZS1vcmlnaW4NClByaW9yaXR5OiB1PTYNClByYWdtYTogbm8tY2FjaGUNCkNhY2hlLUNvbnRyb2w6IG5vLWNhY2hlDQoNCg==,true,,.ico,intercept,none,false,,1755348935616,1490,404,SFRUUC8xLjEgNDA0IE5vdCBGb3VuZA0KQWNjZXB0LVJhbmdlczogYnl0ZXMNCkNvbnRlbnQtVHlwZTogdGV4dC9odG1sDQpFVGFnOiAiODQyMzhkZmM4MDkyZTVkOWMwZGFjOGVmOTMzNzFhMDc6MTczNjc5OTA4MC4xMjExMzQiDQpMYXN0LU1vZGlmaWVkOiBNb24sIDEzIEphbiAyMDI1IDIwOjExOjIwIEdNVA0KU2VydmVyOiBBa2FtYWlOZXRTdG9yYWdlDQpDb250ZW50LUxlbmd0aDogMTI1Ng0KRXhwaXJlczogU2F0LCAxNiBBdWcgMjAyNSAxMjo1NTozNSBHTVQNCkNhY2hlLUNvbnRyb2w6IG1heC1hZ2U9MCwgbm8tY2FjaGUsIG5vLXN0b3JlDQpQcmFnbWE6IG5vLWNhY2hlDQpEYXRlOiBTYXQsIDE2IEF1ZyAyMDI1IDEyOjU1OjM1IEdNVA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KDQo8IWRvY3R5cGUgaHRtbD4KPGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPkV4YW1wbGUgRG9tYWluPC90aXRsZT4KCiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4KICAgIDxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiAvPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPgogICAgPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KICAgIGJvZHkgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjI7CiAgICAgICAgbWFyZ2luOiAwOwogICAgICAgIHBhZGRpbmc6IDA7CiAgICAgICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCAiT3BlbiBTYW5zIiwgIkhlbHZldGljYSBOZXVlIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsKICAgICAgICAKICAgIH0KICAgIGRpdiB7CiAgICAgICAgd2lkdGg6IDYwMHB4OwogICAgICAgIG1hcmdpbjogNWVtIGF1dG87CiAgICAgICAgcGFkZGluZzogMmVtOwogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZGZkZmY7CiAgICAgICAgYm9yZGVyLXJhZGl1czogMC41ZW07CiAgICAgICAgYm94LXNoYWRvdzogMnB4IDNweCA3cHggMnB4IHJnYmEoMCwwLDAsMC4wMik7CiAgICB9CiAgICBhOmxpbmssIGE6dmlzaXRlZCB7CiAgICAgICAgY29sb3I6ICMzODQ4OGY7CiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQogICAgQG1lZGlhIChtYXgtd2lkdGg6IDcwMHB4KSB7CiAgICAgICAgZGl2IHsKICAgICAgICAgICAgbWFyZ2luOiAwIGF1dG87CiAgICAgICAgICAgIHdpZHRoOiBhdXRvOwogICAgICAgIH0KICAgIH0KICAgIDwvc3R5bGU+ICAgIAo8L2hlYWQ+Cgo8Ym9keT4KPGRpdj4KICAgIDxoMT5FeGFtcGxlIERvbWFpbjwvaDE+CiAgICA8cD5UaGlzIGRvbWFpbiBpcyBmb3IgdXNlIGluIGlsbHVzdHJhdGl2ZSBleGFtcGxlcyBpbiBkb2N1bWVudHMuIFlvdSBtYXkgdXNlIHRoaXMKICAgIGRvbWFpbiBpbiBsaXRlcmF0dXJlIHdpdGhvdXQgcHJpb3IgY29vcmRpbmF0aW9uIG9yIGFza2luZyBmb3IgcGVybWlzc2lvbi48L3A+CiAgICA8cD48YSBocmVmPSJodHRwczovL3d3dy5pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPk1vcmUgaW5mb3JtYXRpb24uLi48L2E+PC9wPgo8L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg==,1648,none,false,,1755348935754 3,www.example.com,GET,/path,461,443,R0VUIC9wYXRoIEhUVFAvMS4xDQpIb3N0OiB3d3cuZXhhbXBsZS5jb20NClVzZXItQWdlbnQ6IE1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQ7IHJ2OjE0MS4wKSBHZWNrby8yMDEwMDEwMSBGaXJlZm94LzE0MS4wDQpBY2NlcHQ6IHRleHQvaHRtbCxhcHBsaWNhdGlvbi94aHRtbCt4bWwsYXBwbGljYXRpb24veG1sO3E9MC45LCovKjtxPTAuOA0KQWNjZXB0LUxhbmd1YWdlOiBlbi1VUyxlbjtxPTAuNQ0KQWNjZXB0LUVuY29kaW5nOiBnemlwLCBkZWZsYXRlLCBiciwgenN0ZA0KRE5UOiAxDQpDb25uZWN0aW9uOiBrZWVwLWFsaXZlDQpVcGdyYWRlLUluc2VjdXJlLVJlcXVlc3RzOiAxDQpTZWMtRmV0Y2gtRGVzdDogZG9jdW1lbnQNClNlYy1GZXRjaC1Nb2RlOiBuYXZpZ2F0ZQ0KU2VjLUZldGNoLVNpdGU6IG5vbmUNClNlYy1GZXRjaC1Vc2VyOiA/MQ0KUHJpb3JpdHk6IHU9MCwgaQ0KDQo=,true,,,intercept,none,false,,1755348938708,1491,404,SFRUUC8xLjEgNDA0IE5vdCBGb3VuZA0KQWNjZXB0LVJhbmdlczogYnl0ZXMNCkNvbnRlbnQtVHlwZTogdGV4dC9odG1sDQpFVGFnOiAiODQyMzhkZmM4MDkyZTVkOWMwZGFjOGVmOTMzNzFhMDc6MTczNjc5OTA4MC4xMjExMzQiDQpMYXN0LU1vZGlmaWVkOiBNb24sIDEzIEphbiAyMDI1IDIwOjExOjIwIEdNVA0KU2VydmVyOiBBa2FtYWlOZXRTdG9yYWdlDQpDb250ZW50LUxlbmd0aDogMTI1Ng0KRXhwaXJlczogU2F0LCAxNiBBdWcgMjAyNSAxMjo1NTozOCBHTVQNCkNhY2hlLUNvbnRyb2w6IG1heC1hZ2U9MCwgbm8tY2FjaGUsIG5vLXN0b3JlDQpQcmFnbWE6IG5vLWNhY2hlDQpEYXRlOiBTYXQsIDE2IEF1ZyAyMDI1IDEyOjU1OjM4IEdNVA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KDQo8IWRvY3R5cGUgaHRtbD4KPGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPkV4YW1wbGUgRG9tYWluPC90aXRsZT4KCiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCIgLz4KICAgIDxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiAvPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPgogICAgPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KICAgIGJvZHkgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjI7CiAgICAgICAgbWFyZ2luOiAwOwogICAgICAgIHBhZGRpbmc6IDA7CiAgICAgICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIHN5c3RlbS11aSwgQmxpbmtNYWNTeXN0ZW1Gb250LCAiU2Vnb2UgVUkiLCAiT3BlbiBTYW5zIiwgIkhlbHZldGljYSBOZXVlIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsKICAgICAgICAKICAgIH0KICAgIGRpdiB7CiAgICAgICAgd2lkdGg6IDYwMHB4OwogICAgICAgIG1hcmdpbjogNWVtIGF1dG87CiAgICAgICAgcGFkZGluZzogMmVtOwogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZGZkZmY7CiAgICAgICAgYm9yZGVyLXJhZGl1czogMC41ZW07CiAgICAgICAgYm94LXNoYWRvdzogMnB4IDNweCA3cHggMnB4IHJnYmEoMCwwLDAsMC4wMik7CiAgICB9CiAgICBhOmxpbmssIGE6dmlzaXRlZCB7CiAgICAgICAgY29sb3I6ICMzODQ4OGY7CiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQogICAgQG1lZGlhIChtYXgtd2lkdGg6IDcwMHB4KSB7CiAgICAgICAgZGl2IHsKICAgICAgICAgICAgbWFyZ2luOiAwIGF1dG87CiAgICAgICAgICAgIHdpZHRoOiBhdXRvOwogICAgICAgIH0KICAgIH0KICAgIDwvc3R5bGU+ICAgIAo8L2hlYWQ+Cgo8Ym9keT4KPGRpdj4KICAgIDxoMT5FeGFtcGxlIERvbWFpbjwvaDE+CiAgICA8cD5UaGlzIGRvbWFpbiBpcyBmb3IgdXNlIGluIGlsbHVzdHJhdGl2ZSBleGFtcGxlcyBpbiBkb2N1bWVudHMuIFlvdSBtYXkgdXNlIHRoaXMKICAgIGRvbWFpbiBpbiBsaXRlcmF0dXJlIHdpdGhvdXQgcHJpb3IgY29vcmRpbmF0aW9uIG9yIGFza2luZyBmb3IgcGVybWlzc2lvbi48L3A+CiAgICA8cD48YSBocmVmPSJodHRwczovL3d3dy5pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPk1vcmUgaW5mb3JtYXRpb24uLi48L2E+PC9wPgo8L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg==,1648,none,false,,1755348939013 ``` --- --- url: /app/quickstart/exports.md description: >- A step-by-step guide to exporting data from Caido for use with other security tools or client presentations. --- # Exports The `Exports` interface allows you to export data from Caido that can then be used by other tools or presented to clients. ::: tip HOW-TO GUIDE * [Exporting Request Data](/app/guides/exports_requests.md) ::: --- --- url: /app/tutorials/instance_internet.md description: >- Learn how to set up an instance of Caido that is available online via a domain. --- # Exposing an Instance to the Internet In this tutorial, you will learn how to expose a Caido instance to the internet. ::: danger If [Guest Mode](/app/guides/guest_mode.md) is enabled, the Caido instance will be publicly accessible without authentication. For security and confidentiality, ensure to disable Guest Mode before exposing an instance to the internet. ::: ::: warning NOTE Ensure to replace `user` with your username, `example.com` with your domain, `user@example.com` with your email address, and account for any currently running processes by changing the ports. ::: ## Nginx Configuration 1. To logically separate the internet-exposed Caido instance from your existing setup, create a new subdomain by adding a A record for `caido.example.com` for the IP address of your server. 2. SSH into your server. 3. Create a new `sites-available` file and use the `proxy_pass` directive to route traffic to Caido: `sudo nano /etc/nginx/sites-available/caido.example.com` ```txt server { server_name caido.example.com; location / { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } listen 80; listen [::]:80; } ``` 4. Make the site available, test the configuration, and reload the web server: ```bash sudo ln -s /etc/nginx/sites-available/caido.example.com /etc/nginx/sites-enabled/ ``` ```bash sudo nginx -t ``` ```bash sudo systemctl reload nginx ``` 5. Obtain a SSL/TLS certificate: ```bash sudo certbot --nginx -d caido.example.com ``` 6. Launch the Caido CLI: ```bash caido-cli --ui-listen 127.0.0.1:8081 --proxy-listen 127.0.0.1:8082 --ui-domain caido.example.com --debug --no-renderer-sandbox --no-open ``` ## Docker The following Docker compose file runs two services: the Caido CLI and [Traefik](https://doc.traefik.io/traefik/). ::: warning NOTE If Nginx/Apache is running, kill it with: `sudo systemctl stop nginx`/`sudo systemctl stop apache` ::: 1. SSH into your server. 2. Install [Docker](https://docs.docker.com/engine/install/) with the Docker Compose plugin. 3. Create a `docker-compose.yml` file with the following content: ```txt services: caido: image: caido/caido:latest container_name: caido ports: - "127.0.0.1:8082:8082" # Proxy port volumes: - /home/user/caido/data/:/home/caido/.local/share/caido command: > caido-cli --no-renderer-sandbox --debug --no-open --ui-listen 0.0.0.0:8081 --ui-domain example.com --proxy-listen 0.0.0.0:8082 #--allow-guests restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.caido.rule=Host(`example.com`)" - "traefik.http.routers.caido.entrypoints=websecure" - "traefik.http.routers.caido.tls.certresolver=letsencrypt" - "traefik.http.services.caido.loadbalancer.server.port=8081" traefik: image: traefik:latest container_name: traefik restart: unless-stopped ports: - "80:80" - "443:443" command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" # Redirect HTTP → HTTPS - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" # Let's Encrypt - HTTP challenge (works with standard ports 80/443) - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true" - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - "--certificatesresolvers.letsencrypt.acme.email=user@example.com" - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt ``` 3. Create a data storage location for Caido: ```bash mkdir -p /home/user/caido/data ``` 4. Since the container runs as `uid=996(caido) gid=996(caido) groups=996(caido)`, set ownership of the host directory to match: ```bash sudo chown -R 996:996 /home/user/caido/data ``` 5. Make the directory writable: ```bash sudo chmod 755 /home/user/caido/data ``` 6. Then, run the container to launch Caido and navigate to the `--ui-domain`: ```bash docker compose up ``` ## Accessing Caido Once Caido is running, access the instance at the configured domain and authenticate into your account. --- --- url: /burp-suite/extensibility/overview.md description: Map Burp Suite Pro extensibility features to Caido plugins and workflows. --- # Extensibility This section maps **Burp Suite Pro** extensibility features — extensions, Bambdas, and custom scan checks — to Caido. ## How to use this section 1. **Search by Burp name** — Look for the extension or pattern you used in Burp (for example, `Param Miner`, `Bambdas`, or `custom scan checks`). 2. **Pick the right page** — Use **Extensions** for named BApps, **Bambdas** for Burp scripts, or **Custom Scan Checks** for BChecks and custom scanner rules. 3. **Read the mapping** — Entries are grouped under **Available**, **Indirectly Available**, and **Not Available**. Each entry explains the Caido equivalent, how it differs from Burp, and links under **Resources**. ::: info Workflows and custom checks Many Burp Bambdas, custom scan checks, and extensions can be rebuilt with [Workflows](/app/concepts/workflows_intro.md) or [Scanner custom checks](https://github.com/caido-community/scanner#check-definition). ::: ## Pages * **[Extensions](/burp-suite/extensibility/extensions)** — BApp Store extensions and popular community plugin equivalents. * **[Bambdas](/burp-suite/extensibility/bambdas)** — Burp's in-app JavaScript snippets. * **[Custom Scan Checks](/burp-suite/extensibility/custom-scan-checks)** — User-defined passive and active scan rules. For built-in Burp tools like Proxy and Repeater, see [Core](/burp-suite/core/overview). --- --- url: /burp-suite/extensibility/extensions.md description: Map Burp Suite Pro BApp Store extensions to Caido plugins. --- # Extensions (BApp Store) Burp Suite Pro BApp Store extensions and popular community plugin equivalents in Caido. ## Available ### Extensions (BApp Store) Burp provides an extension marketplace for installing third-party and official BApps. Caido uses a native **Community Store** for extensions listed in the [caido/store](https://github.com/caido/store) catalog, plus manual installation from GitHub. Plugins are the primary extensibility model in Caido, equivalent to Burp's BApp Store but with a different distribution and API. #### Resources * [Plugins](/app/quickstart/plugins.md) * [Installing Plugins](/app/guides/plugins_installing.md) * [Managing Plugins](/app/guides/plugins_managing.md) * [Caido plugin store catalog](https://github.com/caido/store) (GitHub) ### Param Miner Param Miner discovers hidden parameters, headers, and cache-busting inputs. Caido offers the **ParamFinder** community plugin. Caido does not include hidden-parameter discovery natively; this capability comes from a plugin modeled after Burp's Param Miner. #### Resources * [ParamFinder](https://github.com/caido-community/ParamFinder) (GitHub) ### JWT Editor JWT Editor decodes, edits, and resigns JSON Web Tokens inside Burp. Caido offers the **JWT Analyzer** community plugin for JWT decoding, editing, and analysis within Caido. JWT handling is plugin-based rather than a built-in editor. This also covers Burp's older **JSON Web Tokens** BApp, which provided the same decode-and-manipulate workflow before JWT Editor. #### Resources * [JWT Analyzer](https://github.com/caido-community/JWT-Analyzer) (GitHub) * [Decode JWT Tutorial](/app/tutorials/decode_jwt.md) ### JS Miner JS Miner mines JavaScript files for endpoints, secrets, and interesting strings. Caido offers the **Data Grep** and **JS Analyzer** community plugins to extract patterns and analyze JavaScript in captured traffic. Together they cover much of JS Miner's endpoint and secret discovery through passive analysis. #### Resources * [Data Grep](https://github.com/caido-community/data-grep) (GitHub) * [JS Analyzer](https://github.com/caido-community/JS-Analyzer) (GitHub) ### JS Link Finder JS Link Finder passively scans JavaScript files for endpoint links and URLs. Caido offers the **JS Analyzer** community plugin as a direct replacement for JS Link Finder's passive endpoint discovery in JavaScript. #### Resources * [JS Analyzer](https://github.com/caido-community/JS-Analyzer) (GitHub) ### Content Type Converter Content Type Converter converts request and response bodies between content types. Caido offers the **Convert Tools** community plugin for content-type conversion. Caido's native **Convert Workflows** also handle many encoding transformations. #### Resources * [Convert Tools](https://github.com/caido-community/convert-tools) (GitHub) * [Convert Workflows](/app/concepts/workflows_intro.md#convert-workflows) ### 403 Bypasser 403 Bypasser attempts path and header mutations to bypass 403 Forbidden responses. Caido offers the **403Bypasser** community plugin for automated 403 bypass attempts. This is a dedicated plugin rather than a native feature. #### Resources * [403Bypasser](https://github.com/caido-community/Caido403Bypasser) (GitHub) ### InQL InQL provides GraphQL introspection, query building, and analysis inside Burp. Caido offers the **GraphQL Analyzer** community plugin for GraphQL testing in Caido. GraphQL-specific analysis is plugin-provided rather than built in. #### Resources * [GraphQL Analyzer](https://github.com/caido-community/GraphQL-Analyzer) (GitHub) ### Autorize Autorize tests access controls by replaying requests with different session tokens. Caido offers the **Autorize** community plugin for automated authorization testing. **Authswap** can complement it by switching between authentication contexts during manual testing. #### Resources * [Autorize](https://github.com/caido-community/autorize) (GitHub) * [Autorize Tutorial](/app/tutorials/autorize.md) * [Authswap](https://github.com/caido-community/authswap) (GitHub) ### Auth Analyzer Auth Analyzer compares responses across multiple authorization contexts to find access control flaws. Caido offers the **Authify** community plugin for multi-context authorization comparison and analysis. #### Resources * [Authify](https://github.com/saltify7/Authify) (GitHub) ### Request Minimizer Request Minimizer strips unnecessary headers and parameters to find minimal viable requests. Caido offers the **Squash** community plugin to minimize requests. Request minimization is plugin-based rather than a native Burp-style tool. #### Resources * [Squash](https://github.com/evanconnelly/squash) (GitHub) ### CSP Auditor CSP Auditor analyzes Content-Security-Policy headers for weaknesses. Caido offers the **CSP Auditor** community plugin for CSP analysis. CSP-specific auditing is provided by a plugin rather than a native tool. #### Resources * [CSP Auditor](https://github.com/caido-community/csp-auditor) (GitHub) ### AuthMatrix AuthMatrix tests authorization across roles with a matrix of requests and sessions. Caido offers the **AuthMatrix** community plugin for role-based authorization matrix testing. It provides a dedicated UI for cross-role comparison similar to Burp's AuthMatrix extension. #### Resources * [AuthMatrix](https://github.com/caido-community/authmatrix) (GitHub) ### Notes Notes lets you attach notes and annotations to requests inside Burp. Caido offers the **Notes++** community plugin for request annotations. Caido's native **Findings** can track issues, but rich per-request notes are plugin-provided. #### Resources * [Notes++](https://github.com/caido-community/NotesPlusPlus) (GitHub) * [Findings](/app/quickstart/findings.md) ### YesWeBurp YesWeBurp shares Burp requests with teammates through YesWeHack tooling. Caido offers the **YesWeCaido** community plugin for YesWeHack-compatible request sharing. This is a direct port of the collaboration workflow for Caido. #### Resources * [YesWeCaido](https://github.com/yeswehack/yeswecaido) (GitHub) ### Burp Share Requests Burp Share Requests enables collaborative request sharing between Burp users. Caido offers the **Drop** community plugin to share requests with teammates. Collaborative sharing is plugin-based rather than a native Caido feature. #### Resources * [Drop](https://github.com/caido-community/drop) (GitHub) * [Drop Tutorial](/app/tutorials/drop.md) ### Retire.js Retire.js integrates with the Retire.js vulnerability database to flag outdated JavaScript libraries in proxied traffic. Caido offers the **RetireJS Scanner** community plugin, which performs Retire.js-style checks against captured requests and responses. Library version detection is plugin-provided rather than built into Caido's scanner. #### Resources * [RetireJS Scanner](https://github.com/bensh/caido-retirejs) (GitHub) ## Indirectly Available ### Error Message Checks Error Message Checks passively detects verbose server error messages that may leak stack traces or internal details. Caido lets you flag error patterns through the **Scanner** plugin's custom checks or **Passive Workflows**. There is no dedicated passive check pack matching Burp's Error Message Checks BApp. #### Resources * [Scanner: Custom Checks](https://github.com/caido-community/scanner#check-definition) (GitHub) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) ### Reshaper Reshaper triggers actions and reshapes HTTP request and response traffic using configurable rules. Caido offers **Match & Replace** and **Passive Workflows** for rule-based traffic modification and actions. Reshaper's rule engine maps to Caido's workflow and match-and-replace model rather than a single reshaping extension. #### Resources * [Match & Replace](/app/quickstart/match_replace.md) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) ### ExifTool Scanner ExifTool Scanner reads metadata from uploaded or proxied files (JPEG, PNG, PDF, DOC, and more) using ExifTool. Caido has no dedicated ExifTool scanner BApp equivalent. You can extract file metadata with the **Panes** plugin by defining a pane that runs **ExifTool** as a shell command on request or response bodies, or automate similar checks with a **Passive Workflow**. ExifTool must be installed on your system and available in your shell `PATH`. #### Resources * [Panes](https://github.com/caido-community/panes) (GitHub) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) ### MCP Server Burp's MCP Server extension integrates Burp Suite with AI clients through the Model Context Protocol (MCP). Caido offers the **Vibe Hacking** community plugin for MCP-powered agent tools inside Caido, and the community **Caido MCP Server** for connecting external AI clients to a Caido instance. These are separate projects with different scope than PortSwigger's Burp MCP Server. #### Resources * [Vibe Hacking](https://github.com/vvvvvvvvvvel/VibeHacking) (GitHub) * [Caido MCP Server](https://github.com/c0tton-fluff/caido-mcp-server) (GitHub) * [Using a Caido MCP Server](/app/tutorials/mcp.md) ### Active Scan++ Active Scan++ adds active scan checks beyond Burp Scanner's defaults. Caido lets you implement additional checks through the **Scanner** plugin's custom check definitions, and install scan-focused plugins such as **Mass Assignment Radar** or **RetireJS Scanner** for extra coverage. Active Scan++'s extra checks map to custom scanner rules and community plugins rather than a single BApp. #### Resources * [Scanner: Custom Checks](https://github.com/caido-community/scanner#check-definition) (GitHub) * [Mass Assignment Radar](https://github.com/sp1r1tt/Mass-Assignment-Radar) (GitHub) * [RetireJS Scanner](https://github.com/bensh/caido-retirejs) (GitHub) ### Logger++ Logger++ provides enhanced logging with custom fields and filtering beyond Burp Logger. Caido offers native **Search** for traffic querying, the **Data Grep** plugin to extract fields from traffic, or the **Cerebrum** plugin for enhanced logging with custom fields. Logger++'s advanced logging maps to Search plus optional plugins. #### Resources * [Search](/app/quickstart/search.md) * [Search Filtering](/app/guides/search_filtering.md) * [Data Grep](https://github.com/caido-community/data-grep) (GitHub) * [Cerebrum](https://github.com/DewSecOff/Caido-Plugin-Cerebrum) (GitHub) ### Hackvertor Hackvertor transforms data with tag-based encoding, decoding, and encryption pipelines. Caido offers native **Convert Workflows** for tag-based transformations, plus the **Convert Tools** and **HackerUtils** community plugins for encoding pipelines and manual-test utilities. Hackvertor's pipeline model is similar to Caido's workflow-driven conversion, though with different syntax. #### Resources * [Convert Workflows](/app/concepts/workflows_intro.md#convert-workflows) * [Workflows](/app/quickstart/workflows.md) * [Convert Tools](https://github.com/caido-community/convert-tools) (GitHub) * [HackerUtils](https://github.com/caido-community/hackerutils) (GitHub) ### Bypass WAF Bypass WAF applies passive and active techniques to evade web application firewalls during testing. Caido offers **Passive Workflows** to transform traffic, native **Automate** for payload tuning, and WAF-focused plugins such as **403Bypasser**, **Host Header Injector**, **Nomad-ip**, and **SLCyber Tools** (Surf). Caido has no single WAF-bypass BApp; the workflow is distributed across native features and plugins. #### Resources * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [Automate](/app/quickstart/automate.md) * [403Bypasser](https://github.com/caido-community/Caido403Bypasser) (GitHub) * [Host Header Injector](https://github.com/oksuzkayra/host-header-injector) (GitHub) * [Nomad-ip](https://github.com/caido-community/nomad-ip) (GitHub) * [SLCyber Tools](https://github.com/caido-community/slcyber-tools) (GitHub) ### Reflected Parameters Reflected Parameters highlights parameters reflected in responses for XSS and injection testing. Caido offers **Passive Workflows** to flag reflected parameters in proxied traffic. Reflection detection is workflow-driven rather than a dedicated extension tab. #### Resources * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [Workflows](/app/quickstart/workflows.md) ### Sensitive Discoverer Sensitive Discoverer finds sensitive data patterns in HTTP traffic. Caido offers **Passive Workflows** to match sensitive data patterns in traffic automatically, and the **Data Grep** plugin to extract and surface patterns from requests and responses. Custom workflow rules and grep rules replace Burp's Sensitive Discoverer checks. #### Resources * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [Workflows](/app/quickstart/workflows.md) * [Data Grep](https://github.com/caido-community/data-grep) (GitHub) ### Additional Scanner Checks Additional Scanner Checks provides community passive checks that extend Burp Scanner coverage. Caido lets you add checks through the **Scanner** plugin's custom check API and **Passive Workflows**. Extended scanner coverage in Caido is defined by you rather than installed as a BApp. #### Resources * [Scanner: Custom Checks](https://github.com/caido-community/scanner#check-definition) (GitHub) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) ### CORS / Additional CORS Checks CORS checks detect cross-origin misconfigurations and related issues. Caido lets you implement CORS checks through the **Scanner** plugin's custom checks or **Passive Workflows**. Caido does not ship built-in CORS scanning; Caido lets you define checks to match your methodology. #### Resources * [Scanner: Custom Checks](https://github.com/caido-community/scanner#check-definition) (GitHub) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) ### Add Custom Header Add Custom Header adds or modifies headers on requests passing through the proxy. Caido lets you build a native **workflow** to add headers to proxied traffic, use **Match & Replace** for simpler header injection, or install the **Template** plugin for reusable match-and-replace rule templates. The **Host Header Injector** plugin automates Host-header payload variations. #### Resources * [Add a Header Tutorial](/app/tutorials/add_header.md) * [Match & Replace](/app/quickstart/match_replace.md) * [Template](https://github.com/MDGDSS/caido-template) (GitHub) * [Host Header Injector](https://github.com/oksuzkayra/host-header-injector) (GitHub) ### AWS Signer AWS Signer signs AWS API requests with SigV4 credentials inside Burp. The separate **AWS Sigv4** BApp provides the same SigV4 signing capability. Caido supports AWS signing through the **Resign AWS Requests** workflow tutorial pattern to sign AWS requests in Caido. AWS signing is implemented as a workflow rather than a standalone BApp. #### Resources * [Resign AWS Requests Tutorial](/app/tutorials/aws_signature.md) * [Workflows](/app/quickstart/workflows.md) ## Not Available The following BApps from the Burp plugin catalog have no Community Store plugin and no reliable Caido equivalent today. Workarounds, where they exist, are noted but do not provide comparable coverage. ### SSL Scanner SSL Scanner checks TLS/SSL configuration and vulnerabilities using techniques from testssl.sh and a2sv. Caido has no SSL/TLS scanning plugin in the Community Store. You can chain external tools such as testssl.sh or sslscan manually; the community **Dispatch** plugin (GitHub only, not in the store) can pipe requests to CLI scanners if installed separately. ### CSRF Scanner CSRF Scanner passively scans proxied traffic for CSRF vulnerabilities. Caido's **CSRF PoC Generator** builds proof-of-concept HTML from requests but does not perform passive CSRF scanning. Custom **Scanner** checks could approximate some checks but are not a drop-in replacement. ### Collaborator Everywhere Collaborator Everywhere injects Burp Collaborator payloads into headers and parameters on in-scope traffic to surface SSRF, blind RCE, and other out-of-band issues. Caido has no extension that auto-injects OAST payloads across in-scope traffic like Collaborator Everywhere. A similar workflow could be assembled from a **Passive Workflow**, **QuickSSRF**, and an environment variable for the interaction domain, but that integration is not built or shipped as a single equivalent. #### Resources * [QuickSSRF](https://github.com/caido-community/quickssrf) (GitHub) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [Collaborator](/burp-suite/core/tools.md#collaborator) ### Backslash Powered Scanner Backslash Powered Scanner finds unknown classes of injection vulnerabilities using backslash-based fuzzing and response diffing. Caido has no port of Backslash Powered Scanner's backslash fuzzing or response-diffing algorithm. Custom **Scanner** checks and **Mass Assignment Radar** do not provide equivalent coverage. ### Shadow Repeater Shadow Repeater automatically mutates Repeater requests with AI, diffs responses, and sends interesting results to Organizer. Caido has no AI-powered shadow Repeater equivalent. **Automate** covers structured fuzzing but not automatic Repeater-side mutation and anomaly detection. ### Software Vulnerability Scanner Software Vulnerability Scanner uses the Vulners.com audit API to identify vulnerable software versions in HTTP traffic. Caido has no Vulners.com integration or broad software inventory scanning. **RetireJS Scanner** covers outdated JavaScript libraries only and is not a replacement for this BApp. ### Turbo Intruder Turbo Intruder sends large numbers of HTTP requests with Python-scripted attack logic for high-speed or complex fuzzing beyond Burp Intruder. Caido has no equivalent for Turbo Intruder's Python-driven attacks or extreme request throughput. Native **Automate** maps to Burp Intruder, not Turbo Intruder. ### HTTP Request Smuggler HTTP Request Smuggler detects and exploits HTTP request smuggling (CL.TE, TE.CL, and related desync attacks). Caido has no dedicated request-smuggling scanner or exploitation assistant. Smuggling tests generally require crafting raw requests in **Replay**; external proxies such as WafRift can be chained as an upstream if needed. ### HTTPoxy Scanner HTTPoxy Scanner detects the HTTPoxy vulnerability where proxy headers are mishandled by backends. Caido has no built-in HTTPoxy scan check or dedicated plugin. Custom **Scanner** checks or **Passive Workflows** could flag related patterns but are not a drop-in replacement. ### PDF Metadata PDF Metadata adds a passive scanner check for sensitive metadata in PDF responses. Caido has no PDF metadata scanner check. **Data Grep** can match patterns in responses but does not parse PDF structure or extract document metadata like ExifTool-based checks. ### ReportLM ReportLM uses BurpAI to generate custom reports from Burp Scanner issues. Caido offers AI assistants such as **Shift** and **Chatio**, but nothing that turns Caido findings into formatted engagement reports the way ReportLM does for Burp issues. ### CO2 CO2 bundles utilities including a SQL Mapper, user generator, and JavaScript prettifier inside Burp. Caido has no CO2-style SQL mapping or user-generation toolkit. **HackerUtils** and **Automate** cover some manual-testing utilities but not CO2's integrated feature set. ### Proxy Enriched Sequence Diagrams Exporter Proxy Enriched Sequence Diagrams Exporter converts Burp proxy traffic into interactive sequence diagrams. Caido has no traffic-to-diagram export extension. You can review flows in **HTTP History** and **Sitemap**, but not generate sequence diagrams from captured traffic. ### Nucleus Burp Extension Nucleus Burp Extension pushes Burp Suite scan results to the Nucleus vulnerability management platform. Caido has no Nucleus platform integration. This BApp is tied to a specific third-party SaaS workflow. ### OAUTH Scan OAUTH Scan provides automated security checks for applications implementing OAuth 2.0 and OpenID Connect. Caido has no dedicated OAuth/OIDC scanning extension. OAuth-related testing is manual or methodology-specific via custom **Scanner** checks. ### Kerberos Authentication Kerberos Authentication adds Kerberos support for authenticating requests through Burp. Caido's **NTLM Authentication** plugin handles NTLM only. Kerberos authentication is not supported by a Caido plugin today. #### Resources * [NTLM Authentication](https://github.com/caido-community/ntlm) (GitHub) (NTLM only) ### Freddy, Deserialization Bug Finder Freddy detects and helps exploit Java and .NET deserialization vulnerabilities in HTTP traffic. Caido has no deserialization-focused scanner or exploitation extension. Custom **Scanner** checks could flag obvious patterns but do not match Freddy's framework-specific coverage. ### Autowasp Autowasp maps Burp issues to the OWASP Web Security Testing Guide (WSTG) for structured web security testing workflows. Caido's **Findings** track issues in a project but do not map them to WSTG test cases or provide Autowasp's checklist-driven workflow. --- --- url: /faq.md description: >- Frequently asked questions about Caido pricing, installation, data collection, support, and troubleshooting. --- # FAQ ## Is Caido free? Caido has a free `Basic` plan. We also offer an `Individual` plan which includes additional advanced features. By purchasing the `Individual` plan, you will be supporting the development and maintenance of the tool. Additionally, we offer a `Team` plan for organizations that need premium support and/or custom feature implementation. ::: info You can check our [website](https://www.caido.io) to stay informed about the new features that will be added in the future. ::: ## Is Caido open source? Caido is not currently open source, but we have a rich ecosystem of [open source extensions](https://www.caido.io/plugins). We also employ standard open formats whenever possible. ## On how many devices can I install Caido? At this time, Caido can be installed on an unlimited number of devices. You are welcome to install Caido on as many devices as you like. ## What data do you collect? When you register for Caido, we collect your name and email address, as well as information about your user agent. When you use Caido, we collect interaction data between your instances and our cloud services. This includes the IP address of the instance and API call actions/timestamps. We do not collect any data stored on your instances nor interactions within the Caido application. ## Where can I ask for support and/or feature requests? You can ask for support and submit feature requests through our public Discord or Github repository. Both are great places to share feedback and help improve Caido. ## How do I gain access to the dedicated Discord support channels? Caido Individual and Team level subscriptions come with prioritized customer support. To access these channels, you must first [link your Discord account](/app/guides/discord.md). ## What is the difference between Caido CLI and Caido Desktop? The Caido CLI is self-contained binary that launches the Caido proxy (also called instance). You can use it on remote servers or locally and access the instance using your browser. The Caido Desktop acts a connection manager to your instances and can also launch the Caido proxy in the background. It uses webviews to access the instance instead of the browser. ## I've encountered an error, what do I do? Depending on the error, you can try the following: * Check out the Troubleshooting guides. * Join the [Discord](https://links.caido.io/www-discord). * Raise an issue on [Github](https://github.com/caido/caido) if it's a bug. --- --- url: /app/quickstart/files.md description: >- A step-by-step guide to Caido's Files interface for uploading and managing files within your security testing instance. --- # Files Within the `Files` interface, you can upload files to make them available to your Caido instance. ::: tip HOW-TO GUIDE * [Uploading Files](/app/guides/files_uploading.md) ::: --- --- url: /app/guides/http_history_filtering.md description: >- A step-by-step guide to filtering and organizing traffic table rows in Caido's HTTP History interface using column options and advanced filtering. --- # Filtering Traffic Table Rows ::: tip To view traffic generated by Caido features, view the traffic table in the [Search](/app/guides/search_filtering.md) interface. ::: To include or exclude traffic table columns, **click** on the button in the lower right-hand corner. ::: warning NOTE Certain columns support [sorting traffic table rows](/app/guides/sorting.md), while others do not. For example, the `Path & Query` column does not support sorting but the individual `Path` and `Query` columns do. ::: Additional filtering options are accessible by **clicking** the `Advanced` button, located above the traffic table. Actively applied advanced options are listed below the table. ::: tip View the [Writing HTTPQL Queries](/app/guides/filters_httpql.md) guide to learn how to filter traffic based on certain traits. ::: --- --- url: /app/guides/search_filtering.md description: >- A step-by-step guide to filtering traffic table rows in Caido's Search interface using column options, advanced filters, and HTTPQL expressions. --- # Filtering Traffic Table Rows ::: info In addition to the proxied traffic displayed in the HTTP History traffic table, the traffic table in the Search interface also includes traffic generated by Caido features. ::: To include or exclude traffic table columns, **click** on the button in the lower right-hand corner. Additional filtering options are accessible by **clicking** the `Advanced` button, located above the traffic table. Actively applied advanced options are listed below the table. ::: tip View the [HTTPQL reference](/app/reference/httpql.md) to learn how to filter traffic based on certain traits. ::: --- --- url: /app/quickstart/filters.md description: >- A step-by-step guide to Caido's Filters feature for including or excluding specific requests and responses from traffic analysis. --- # Filters The `Filters` interface gives you the ability to define which requests or responses should be included or excluded from Caido traffic tables and operations, based on specific elements. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Writing HTTPQL Queries](/app/guides/filters_httpql.md) * [Defining a Filter](/app/guides/filters_defining.md) * [Applying a Filter](/app/guides/filters_applying.md) ::: --- --- url: /app/quickstart/findings.md description: >- A step-by-step guide to Caido's Findings interface for viewing security discoveries and anomalous requests detected during testing. --- # Findings The `Findings` interface displays discoveries made by Caido processes or ones you’ve added manually, providing you with a repository of anomalous requests that warrant attention. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDE * [Creating Findings](/app/guides/workflows_findings.md) ::: --- --- url: /app/guides/assistant_csrf.md description: >- A step-by-step guide to using Caido's AI Assistant to generate Cross-Site Request Forgery (CSRF) proof-of-concept attacks from HTTP requests. --- # Generating CSRF PoCs ::: warning Submitted data is sent to a third-party (OpenAI) and can be stored for up to 30 days. Due to this, **anonymize sensitive data** when using the Assistant. Sensitive data may be unintentionally submitted when using the Assistant context menu options. Before using any context menu option, manually review all content to ensure no sensitive data is included. For more information, review: * [OpenAI's Privacy Policy](https://openai.com/policies/privacy-policy) * [Caido's Privacy Policy](https://www.caido.io/privacy) ::: To prompt the Assistant to generate Cross-Site Request Forgery (CSRF) attack proof-of-concepts, **right-click** within a request pane to open the context menu, hover your mouse cursor over Assistant, and select `Generate CSRF PoC`. Or, submit a prompt directly in the `Send a message` input field along with the request: ```txt Create a CSRF PoC in HTML that will automatically submit the form for the following request: POST /change/email HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br, zstd DNT: 1 Connection: keep-alive Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Priority: u=0, i Pragma: no-cache Cache-Control: no-cache Cookie: session_id=123ABC321XYZ Content-Type: application/x-www-form-urlencoded Content-Length: 23 email=attacker@caido.io ``` --- --- url: /app/concepts/graphql.md description: >- Understand the core concepts behind Caido's GraphQL API for client/server communication, authentication, playground access, and schema exploration. --- # GraphQL As you interact with the Caido GUI (*client component*), a variety of [GraphQL](https://graphql.org/) API queries, mutations, and subscriptions are generated and sent to the Caido CLI (*server component*). These operations are responsible for fetching data, performing actions, and updating the interface with the latest data. ## GraphQL Playground The [GraphQL API schema](https://github.com/caido/schemas/blob/main/schemas/proxy/schema.graphql) is available via a Playground IDE. To access it, navigate to or **click** on the account button in the top-right corner of the Caido user-interface and select GraphQL Playground. ::: tip A visual representation of the schema can be viewed at . ::: ::: warning NOTE Caido's GraphQL API is intentionally public to assist with the development of third-party tools. However, stability is not guaranteed as each release is likely to include changes to the schema. ::: ### Authentication For the majority of operations, since they execute in the context of your user session/instance, authentication is required. If your token is not already included in the `Headers` tab of the GraphQL Playgound interface, to obtain it: 1. Authenticate into your account. 2. Open the developer tools in the Caido GUI with `CTRL`+`SHIFT`+`I`. 3. Enter the following into the Console tab terminal: ```javascript JSON.parse(localStorage.CAIDO_AUTHENTICATION).accessToken; ``` 4. The access token can then be set in the `Headers` tab: ```json { "Authorization": "Bearer " } ``` ::: warning NOTE The access token expires after a period of 7 days. If your project requires consistent authentication, utilize the [OAuth](/app/concepts/instance_authentication) `startAuthenticationFlow` mutation and `createdAuthenticationToken` subscription. ::: ## Example: Using Replay To gain a better understanding of how Caido operates, the following GraphQL operations are involved in creating a new Replay session and sending the request. ### CreateReplaySession The `CreateReplaySession` mutation creates a new request editor in the Replay interface. ```graphql mutation CreateReplaySession($input: CreateReplaySessionInput!) { createReplaySession(input: $input) { session { id name activeEntry { id } entries(first: 10) { edges { node { id } } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } collection { id } } } } ``` #### Variables Typically, **clicking** on the `+ New Session` button generates an empty request as no fields are specified in the `input` object. However, the connection and request can be included directly. ```json { "input": { "requestSource": { "raw": { "connectionInfo": { "host": "example.com", "port": 80, "isTLS": false, "SNI": "example.com" }, "raw": "R0VUIC8gSFRUUC8xLjENCkhvc3Q6IGV4YW1wbGUuY29tDQpDb25uZWN0aW9uOiBjbG9zZQ0KDQo=" } } } } ``` #### Response Data ```json { "data": { "createReplaySession": { "session": { "id": "1", "name": "1", "activeEntry": { "id": "1" }, "entries": { "edges": [ { "node": { "id": "1" } } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "eyJpZCI6IjEiLCJvcmRlcl92YWx1ZSI6bnVsbH0=", "endCursor": "eyJpZCI6IjEiLCJvcmRlcl92YWx1ZSI6bnVsbH0=" } }, "collection": { "id": "1" } } } } } ``` The corresponding request and response pair are: ```http POST /graphql HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Content-Length: 746 sec-ch-ua-platform: "Windows" Authorization: Bearer User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Caido/0.54.1 Chrome/138.0.7204.251 Electron/37.8.0 Safari/537.36 accept: application/json, multipart/mixed sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138" content-type: application/json sec-ch-ua-mobile: ?0 Origin: http://127.0.0.1:8080 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: http://127.0.0.1:8080/graphql/ Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-US {"query":"mutation CreateReplaySession($input: CreateReplaySessionInput!) {\n createReplaySession(input: $input) {\n session {\n id\n name\n activeEntry {\n id\n }\n entries(first: 10) {\n edges {\n node {\n id\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n collection {\n id\n }\n }\n }\n}","variables":{"input":{"requestSource":{"raw":{"connectionInfo":{"host":"example.com","port":80,"isTLS":false,"SNI":"example.com"},"raw":"R0VUIC8gSFRUUC8xLjENCkhvc3Q6IGV4YW1wbGUuY29tDQpDb25uZWN0aW9uOiBjbG9zZQ0KDQo="}}}},"operationName":"CreateReplaySession"} ``` ```http HTTP/1.1 200 OK content-length: 326 connection: close vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers content-type: application/json access-control-allow-origin: http://127.0.0.1:8080 date: Mon, 12 Jan 2026 16:52:13 GMT {"data":{"createReplaySession":{"session":{"id":"1","name":"1","activeEntry":{"id":"1"},"entries":{"edges":[{"node":{"id":"1"}}],"pageInfo":{"hasNextPage":false,"hasPreviousPage":false,"startCursor":"eyJpZCI6IjMiLCJvcmRlcl92YWx1ZSI6bnVsbH0=","endCursor":"eyJpZCI6IjMiLCJvcmRlcl92YWx1ZSI6bnVsbH0="}},"collection":{"id":"1"}}}}} ``` ### StartReplayTask **Clicking** on the `Send` button generates a `StartReplayTask` mutation. ```graphql mutation StartReplayTask($sessionId: ID!, $input: StartReplayTaskInput!) { startReplayTask(sessionId: $sessionId, input: $input) { error { __typename } task { id createdAt replayEntry { id } } } } ``` #### Variables ```json { "sessionId": "1", "input": { "connection": { "host": "example.com", "port": 80, "isTLS": false, "SNI": "example.com" }, "raw": "R0VUIC8gSFRUUC8xLjENCkhvc3Q6IGV4YW1wbGUuY29tDQpDb25uZWN0aW9uOiBjbG9zZQ0KDQo=", "settings": { "connectionClose": true, "updateContentLength": true, "placeholders": [] } } } ``` #### Data ```json { "data": { "startReplayTask": { "error": null, "task": { "id": "8", "createdAt": "2026-01-12T18:50:28.4289894Z", "replayEntry": { "id": "2" } } } } } ``` The corresponding request and response pair are: ```http POST /graphql HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Content-Length: 3976 sec-ch-ua-platform: "Windows" authorization: Bearer r/iu/AlQOL/SINNOS6yK1b5/ZmzueaAbbEQ99su9aLTAkSlQS0zj4Rtfc7MRSVwNgM140ZiU9rcMSgKxcySFKQ==.eBF2nuQt5k74iNS4IA1SunHWQIKdPX+IvTq/zaBltkk= User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 accept: application/graphql-response+json, application/graphql+json, application/json, text/event-stream, multipart/mixed sec-ch-ua: "Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24" content-type: application/json sec-ch-ua-mobile: ?0 Origin: http://127.0.0.1:8080 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: http://127.0.0.1:8080/ Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 {"operationName":"startReplayTask","query":"mutation startReplayTask($sessionId: ID!, $input: StartReplayTaskInput!) {\n startReplayTask(sessionId: $sessionId, input: $input) {\n task {\n ...replayTaskMeta\n }\n error {\n ... on TaskInProgressUserError {\n ...taskInProgressUserErrorFull\n }\n ... on PermissionDeniedUserError {\n ...permissionDeniedUserErrorFull\n }\n ... on CloudUserError {\n ...cloudUserErrorFull\n }\n ... on OtherUserError {\n ...otherUserErrorFull\n }\n }\n }\n}\nfragment taskMeta on Task {\n __typename\n id\n createdAt\n}\nfragment connectionInfoFull on ConnectionInfo {\n __typename\n host\n port\n isTLS\n SNI\n}\nfragment requestMetadataFull on RequestMetadata {\n __typename\n id\n color\n}\nfragment responseMeta on Response {\n __typename\n id\n statusCode\n roundtripTime\n length\n createdAt\n alteration\n edited\n}\nfragment requestMeta on Request {\n __typename\n id\n host\n port\n path\n query\n method\n edited\n isTls\n sni\n length\n alteration\n metadata {\n ...requestMetadataFull\n }\n fileExtension\n source\n createdAt\n response {\n ...responseMeta\n }\n stream {\n id\n }\n}\nfragment replayEntryMeta on ReplayEntry {\n __typename\n id\n error\n createdAt\n connection {\n ...connectionInfoFull\n }\n session {\n id\n }\n request {\n ...requestMeta\n }\n}\nfragment rangeFull on Range {\n start\n end\n}\nfragment replayPrefixPreprocessorFull on ReplayPrefixPreprocessor {\n __typename\n value\n}\nfragment replaySuffixPreprocessorFull on ReplaySuffixPreprocessor {\n __typename\n value\n}\nfragment replayUrlEncodePreprocessorFull on ReplayUrlEncodePreprocessor {\n __typename\n charset\n nonAscii\n}\nfragment replayWorkflowPreprocessorFull on ReplayWorkflowPreprocessor {\n __typename\n id\n}\nfragment replayEnvironmentPreprocessorFull on ReplayEnvironmentPreprocessor {\n __typename\n variableName\n}\nfragment replayPreprocessorFull on ReplayPreprocessor {\n __typename\n options {\n ... on ReplayPrefixPreprocessor {\n ...replayPrefixPreprocessorFull\n }\n ... on ReplaySuffixPreprocessor {\n ...replaySuffixPreprocessorFull\n }\n ... on ReplayUrlEncodePreprocessor {\n ...replayUrlEncodePreprocessorFull\n }\n ... on ReplayWorkflowPreprocessor {\n ...replayWorkflowPreprocessorFull\n }\n ... on ReplayEnvironmentPreprocessor {\n ...replayEnvironmentPreprocessorFull\n }\n }\n}\nfragment replayPlaceholderFull on ReplayPlaceholder {\n __typename\n inputRange {\n ...rangeFull\n }\n outputRange {\n ...rangeFull\n }\n preprocessors {\n ...replayPreprocessorFull\n }\n}\nfragment requestFullFields on Request {\n ...requestMeta\n raw\n edits {\n ...requestMeta\n }\n}\nfragment requestFull on Request {\n ...requestFullFields\n}\nfragment replayEntryFull on ReplayEntry {\n ...replayEntryMeta\n raw\n settings {\n placeholders {\n ...replayPlaceholderFull\n }\n }\n request {\n ...requestFull\n }\n}\nfragment userErrorFull on UserError {\n __typename\n code\n}\nfragment replayTaskMeta on ReplayTask {\n ...taskMeta\n replayEntry {\n ...replayEntryFull\n }\n}\nfragment taskInProgressUserErrorFull on TaskInProgressUserError {\n ...userErrorFull\n taskId\n}\nfragment permissionDeniedUserErrorFull on PermissionDeniedUserError {\n ...userErrorFull\n permissionDeniedReason: reason\n}\nfragment cloudUserErrorFull on CloudUserError {\n ...userErrorFull\n cloudReason: reason\n}\nfragment otherUserErrorFull on OtherUserError {\n ...userErrorFull\n}","variables":{"input":{"connection":{"SNI":"example.com","host":"example.com","isTLS":false,"port":80},"raw":"R0VUIC8gSFRUUC8xLjENCkhvc3Q6IGV4YW1wbGUuY29tDQpDb25uZWN0aW9uOiBjbG9zZQ0KDQo=","settings":{"connectionClose":true,"placeholders":[],"updateContentLength":true}},"sessionId":"1"}} ``` ```http HTTP/1.1 200 OK content-length: 483 connection: close vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers content-type: application/json access-control-allow-origin: http://127.0.0.1:8080 date: Tue, 13 Jan 2026 16:15:03 GMT {"data":{"startReplayTask":{"task":{"__typename":"ReplayTask","id":"2","createdAt":"2026-01-13T16:15:03.7537873Z","replayEntry":{"__typename":"ReplayEntry","id":"2","error":null,"createdAt":1768320903752,"connection":{"__typename":"ConnectionInfo","host":"example.com","port":80,"isTLS":false,"SNI":"example.com"},"session":{"id":"1"},"request":null,"raw":"R0VUIC8gSFRUUC8xLjENCkhvc3Q6IGV4YW1wbGUuY29tDQpDb25uZWN0aW9uOiBjbG9zZQ0KDQo=","settings":{"placeholders":[]}}},"error":null}}} ``` A [traffic splitting algorithm](/app/concepts/traffic_splitting.md) recognizes that the request is intended for a destination server. The Caido CLI (*server component*) forwards the request and handles the corresponding response. ```http GET / HTTP/1.1 Host: example.com Connection: close ``` ```http HTTP/1.1 200 OK Date: Mon, 12 Jan 2026 19:03:54 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: close CF-RAY: 9bceeaa5af5c27ec-LAX Last-Modified: Sat, 03 Jan 2026 05:43:21 GMT Allow: GET, HEAD Age: 24 cf-cache-status: HIT Accept-Ranges: bytes Server: cloudflare 200 Example Domain

Example Domain

This domain is for use in documentation examples without needing permission. Avoid use in operations.

Learn more

1 0 ``` ### GetReplayEntry To display the response, the `GetReplayEntry` query is used. ```graphql query GetReplayEntry($id: ID!) { replayEntry(id: $id) { id error request { id response { id statusCode length roundtripTime raw createdAt } } } } ``` #### Variables The `id` changes from `1` to `2` since the sent request is second in the session's history. ```json { "id": "2" } ``` #### Data ```json { "data": { "replayEntry": { "id": "2", "error": null, "request": { "id": "2", "response": { "id": "1", "statusCode": 200, "length": 801, "roundtripTime": 116, "raw": "SFRUUC8xLjEgMjAwIE9LDQpEYXRlOiBNb24sIDEyIEphbiAyMDI2IDE5OjAzOjU0IEdNVA0KQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwNCkNvbm5lY3Rpb246IGNsb3NlDQpDRi1SQVk6IDliY2VlYWE1YWY1YzI3ZWMtTEFYDQpMYXN0LU1vZGlmaWVkOiBTYXQsIDAzIEphbiAyMDI2IDA1OjQzOjIxIEdNVA0KQWxsb3c6IEdFVCwgSEVBRA0KQWdlOiAyNA0KY2YtY2FjaGUtc3RhdHVzOiBISVQNCkFjY2VwdC1SYW5nZXM6IGJ5dGVzDQpTZXJ2ZXI6IGNsb3VkZmxhcmUNCkNvbnRlbnQtTGVuZ3RoOiA1MTMNCg0KPCFkb2N0eXBlIGh0bWw+PGh0bWwgbGFuZz0iZW4iPjxoZWFkPjx0aXRsZT5FeGFtcGxlIERvbWFpbjwvdGl0bGU+PG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIj48c3R5bGU+Ym9keXtiYWNrZ3JvdW5kOiNlZWU7d2lkdGg6NjB2dzttYXJnaW46MTV2aCBhdXRvO2ZvbnQtZmFtaWx5OnN5c3RlbS11aSxzYW5zLXNlcmlmfWgxe2ZvbnQtc2l6ZToxLjVlbX1kaXZ7b3BhY2l0eTowLjh9YTpsaW5rLGE6dmlzaXRlZHtjb2xvcjojMzQ4fTwvc3R5bGU+PGJvZHk+PGRpdj48aDE+RXhhbXBsZSBEb21haW48L2gxPjxwPlRoaXMgZG9tYWluIGlzIGZvciB1c2UgaW4gZG9jdW1lbnRhdGlvbiBleGFtcGxlcyB3aXRob3V0IG5lZWRpbmcgcGVybWlzc2lvbi4gQXZvaWQgdXNlIGluIG9wZXJhdGlvbnMuPHA+PGEgaHJlZj0iaHR0cHM6Ly9pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPkxlYXJuIG1vcmU8L2E+PC9kaXY+PC9ib2R5PjwvaHRtbD4K", "createdAt": 1768244634848 } } } } } ``` The corresponding request and response pair are: ```http POST /graphql HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Content-Length: 315 sec-ch-ua-platform: "Windows" Authorization: Bearer 3w41ccRmsftO0MOiWn7zSfDyEaEkZV0eYzU7MZWeyy/l/74QVbQ7pjOVDFl3ufyONEwH7NpXtRiiroi3F6rRBw==.Z78fF5XYnyFlW4QhqPefauH5q0tEVy4+Btyk0Bh1L0I= User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Caido/0.54.1 Chrome/138.0.7204.251 Electron/37.8.0 Safari/537.36 accept: application/json, multipart/mixed sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138" content-type: application/json sec-ch-ua-mobile: ?0 Origin: http://127.0.0.1:8080 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: http://127.0.0.1:8080/graphql/ Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-US {"query":"query GetReplayEntry($id: ID!) {\n replayEntry(id: $id) {\n id\n error\n request {\n id\n response {\n id\n statusCode\n length\n roundtripTime\n raw\n createdAt\n }\n }\n }\n}","variables":{"id":"2"},"operationName":"GetReplayEntry"} ``` ```http HTTP/1.1 200 OK content-length: 1244 connection: close vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers content-type: application/json access-control-allow-origin: http://127.0.0.1:8080 date: Mon, 12 Jan 2026 19:17:51 GMT {"data":{"replayEntry":{"id":"2","error":null,"request":{"id":"2","response":{"id":"1","statusCode":200,"length":801,"roundtripTime":116,"raw":"SFRUUC8xLjEgMjAwIE9LDQpEYXRlOiBNb24sIDEyIEphbiAyMDI2IDE5OjAzOjU0IEdNVA0KQ29udGVudC1UeXBlOiB0ZXh0L2h0bWwNCkNvbm5lY3Rpb246IGNsb3NlDQpDRi1SQVk6IDliY2VlYWE1YWY1YzI3ZWMtTEFYDQpMYXN0LU1vZGlmaWVkOiBTYXQsIDAzIEphbiAyMDI2IDA1OjQzOjIxIEdNVA0KQWxsb3c6IEdFVCwgSEVBRA0KQWdlOiAyNA0KY2YtY2FjaGUtc3RhdHVzOiBISVQNCkFjY2VwdC1SYW5nZXM6IGJ5dGVzDQpTZXJ2ZXI6IGNsb3VkZmxhcmUNCkNvbnRlbnQtTGVuZ3RoOiA1MTMNCg0KPCFkb2N0eXBlIGh0bWw+PGh0bWwgbGFuZz0iZW4iPjxoZWFkPjx0aXRsZT5FeGFtcGxlIERvbWFpbjwvdGl0bGU+PG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIj48c3R5bGU+Ym9keXtiYWNrZ3JvdW5kOiNlZWU7d2lkdGg6NjB2dzttYXJnaW46MTV2aCBhdXRvO2ZvbnQtZmFtaWx5OnN5c3RlbS11aSxzYW5zLXNlcmlmfWgxe2ZvbnQtc2l6ZToxLjVlbX1kaXZ7b3BhY2l0eTowLjh9YTpsaW5rLGE6dmlzaXRlZHtjb2xvcjojMzQ4fTwvc3R5bGU+PGJvZHk+PGRpdj48aDE+RXhhbXBsZSBEb21haW48L2gxPjxwPlRoaXMgZG9tYWluIGlzIGZvciB1c2UgaW4gZG9jdW1lbnRhdGlvbiBleGFtcGxlcyB3aXRob3V0IG5lZWRpbmcgcGVybWlzc2lvbi4gQXZvaWQgdXNlIGluIG9wZXJhdGlvbnMuPHA+PGEgaHJlZj0iaHR0cHM6Ly9pYW5hLm9yZy9kb21haW5zL2V4YW1wbGUiPkxlYXJuIG1vcmU8L2E+PC9kaXY+PC9ib2R5PjwvaHRtbD4K","createdAt":1768244634848}}}}} ``` --- --- url: /app/guides/guest_mode.md description: >- A step-by-step guide to using Caido in Guest Mode without authentication, including security considerations and feature limitations. --- # Guest Mode Caido can be used without an account by selecting the `Continue as guest` option in the authentication prompt. ::: danger In Guest Mode, anyone can access your instance without authentication. For example, binding to 0.0.0.0 would grant unauthorized access to anyone on the same network, exposing your device to remote code execution. ::: ## Caido CLI By default, Guest Mode is **disabled** for the Caido CLI. To enable Guest Mode with the Caido CLI, launch Caido with the `--allow-guests` command-line option. ```bash caido --allow-guests ``` ## Desktop Application By default, Guest Mode is **enabled** for local instances. To disable Guest Mode within the Caido desktop application, in the launch window, **click** on the button attached to an instance and select `Edit`. Then, **click** on Advanced to expand the drop-down settings menu options and **click** on the `Allow guests` checkbox to remove its fill. **Click** on the `Save` button to update and save the configuration. ## Guest Mode Limitations In contrast to an authenticated session, in Guest Mode: * Projects are not saved. * All user settings are shared across all guests. * Only a single plugin can be installed at a time. ::: info Shared Guest Mode settings are not shared with your account. This includes plugin component configurations. For instance, you will have to manually enable/disable the frontend/backend components. ::: tip [Register an account](https://dashboard.caido.io/signup) and use an authenticated session to gain the ability to save two projects and install up to three plugins. ::: --- --- url: /dashboard/guides.md description: Step-by-step guide to help you perform various operations in the dashboard --- # Guides The Guides sections is there to help you with step-by-step guides to perform administrative operations in the Dashboard. --- --- url: /app/quickstart/http_history.md description: >- A step-by-step guide to Caido's HTTP History interface for viewing and analyzing all proxied HTTP requests and responses. --- # HTTP History The `HTTP History` interface provides a table that contains all of the HTTP requests and their associated responses that have been proxied through Caido. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Filtering Traffic Table Rows](/app/guides/http_history_filtering.md) * [Viewing Modifications](/app/guides/http_history_modifications.md) ::: --- --- url: /app/reference/httpql.md description: >- Find detailed reference information on HTTPQL query language used in Caido for filtering requests and responses with namespaces, fields, and operators. --- # HTTPQL HTTPQL is the query language used in Caido that gives you the ability to filter traffic. The constructing primitives of an HTTPQL query statement, in order of position, are the: 1. [Namespace](#namespaces) 2. [Field](#fields) 3. [Operator](#operators) 4. [Value](#values) ::: tip The development of fields is ongoing. To request a field, [submit a templated issue.](https://github.com/caido/caido/issues/new?template=feature.md\&title=New%20HttpQL%20field:) ::: ## Namespaces ::: info Namespaces are project-specific. ::: | Namespace | Description | |-----------|-------------| | `req` | All proxied HTTP requests. | | `resp` | All proxied HTTP responses. | | `preset` | Filter presets. | | `row` | A request's numerical identifier in the traffic tables. | | `source` | The Caido feature source (only available in the Search interface). | ::: warning NOTE The `preset` and `source` namespaces do not have any fields available and instead take direct values. ::: ## Fields ### req | Available Fields | Description | Value Type | |------------------|-------------|------------| | `created_at` | The date and time the request was sent. | Date/Time: [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) (`2024-06-24T17:03:48+00:00`) / [ISO 8601](https://datatracker.ietf.org/doc/html/rfc3339#appendix-A) (`2024-06-24T17:03:48+0000`) / [RFC2822](https://datatracker.ietf.org/doc/html/rfc2822) (`Mon, 24 Jun 2024 17:03:48 +0000`) / [RFC7231](https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.2) (`Mon, 24 Jun 2024 17:03:48 GMT`) / [ISO9075](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_get-format) (`2024-06-24T17:03:48Z`) | | `ext` | The extension of the requested file. | String/Byte | | `host` | The value of the request's `Host` header. | String/Byte | | `len` | The request size in bytes (includes request line, headers, and body data). | Integer | | `method` | The HTTP method used for the request. | String/Byte | | `path` | The URL path (includes files). | String/Byte | | `port` | The port of the target server. | Integer | | `query` | The URL query string (excludes the leading `?`). | String/Byte | | `raw` | The full raw data of the request (includes request line, headers, and body data). | String/Byte | | `tls` | If the connection used TLS/SSL encryption. | Boolean (`true`/`false`) | ### resp | Available Fields | Description | Value Type | |------------------|-------------|------------| | `code` | The status code of the reponse. | Integer | | `len` | The response size in bytes (includes response line, headers, and body data). | Integer | | `raw` | The full raw data of the response (includes response line, headers, and body data). | String/Byte | | `roundtrip` | The total request/response cycle time (in milliseconds). | Integer | ### row | Available Field | Description | Value Type | |------------------|-------------------|------------| | `id` | The numerical identifier of a request's traffic table row. | Integer | ## Operators | Operator | Description | Value Type | Additional Details | |----------|-------------|------------|-------------------| | `eq` | Equal to the supplied value. | String/Byte, Integer | Case sensitive. Requires leading `.` character for `ext` field. | | `gt` | Greater than the supplied value. | Date/Time, Integer | | | `gte` | Greater than or equal to the supplied value. | Integer | | | `lt` | Less than the supplied value. | Date/Time, Integer | | | `lte` | Less than or equal to the supplied value. | Integer | | | `ne` | Not equal to the supplied value. | String/Byte, Integer | Case sensitive. Requires leading `.` character for `ext` field. | | `cont` | Contains the supplied value. | String/Byte | Case insensitive. | | `like` | The [SQLite LIKE Operator](https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators). | String/Byte | Case sensitive for Unicode characters beyond the ASCII range. | | `ncont` | Does not contain the supplied value. | String/Byte | Case insensitive. | | `nlike` | The [SQLite NOT LIKE Operator](https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators). | String/Byte | Case sensitive for Unicode characters beyond the ASCII range. | | `regex` | Matches to the regular expression. | String/Byte | Rust-flavored syntax. | | `nregex` | Does not match to the regular expression. | String/Byte | Rust-flavored syntax. | ::: tip In SQLite - the `%` character matches zero or more characters (*`%.js` matches `.map.js`*) and the `_` character matches one character (*`v_lue` matches `vAlue`*). Visit and select **Rust** syntax to test regular expressions. ::: ::: warning NOTE Not all regex features are currently supported by Caido (*such as look-ahead expressions*) as they are not included in the regex library of Rust. ::: ## Values ### preset | Available Values | Example | |------------------|---------| | A filter preset's alias. | `preset:"no-images"` | | A filter preset's name. | `preset:"No Images"` | ### source | Available Values | Additional Details | Example | |------------------|--------------------|---------| | `automate`, `intercept`, `plugin`, `replay`, `workflow` | Requires lowercase. Autocomplete is not supported. | `source:"plugin"` | ::: warning NOTE The `source` namespace is only available in the Search interface. If no results are returned, ensure the inclusion of the source is enabled in the [Advanced options](/app/guides/search_filtering.md) menu. ::: ::: tip Entering a string (*such as `"my value"`*) into the HTTPQL input field will search across both requests and responses. The supplied string is replaced at runtime by: ```sql (req.raw.cont:"my value" OR resp.raw.cont:"my value") ``` ::: ## Combining Statements Query statements can be combined together using logical operators and logical grouping. ### Logical Operators | Operator | Description | |----------|-------------| | AND | Both the left and right clauses must be true. | | OR | Either the left or right clause must be true. | ::: info Operators are case insensitive. Both have the **same priority**. ::: ### Logical Grouping Caido supports the priority of operations: `AND` has a higher priority than `OR`. * ` AND OR ` is equivalent to `(( AND ) OR )`. * ` OR AND ` is equivalent to `( OR ( AND ))`. * ` AND AND ` is equivalent to `(( AND ) AND )`. ::: tip While parentheses are optional, we recommend using them to make your logical grouping clear. ::: ## Comments Caido supports both single-line and multi-line comments in HTTPQL queries. ::: tip Comments can be used to write descriptions or temporarily disable certain query statements. ::: *** --- --- url: /app/guides/ca_certificate_importing.md description: >- A step-by-step guide to importing Caido's CA certificate for proxying HTTPS traffic. --- # Importing Caido's CA Certificate To [proxy HTTPS traffic](/app/concepts/web_traffic.md) with Caido, it is necessary to import and trust the CA Certificate of Caido in your browser. To download the certificate, **click** on the account button in the top-right corner of the Caido user-interface, select `CA Certificate`, and **click** on the Download CA Certificate button. Once the certificate has been downloaded, continue with the import instructions for your browser: ## Chrome 1. Launch the Chrome browser, enter `chrome://certificate-manager/` in the address bar, and select `Installed by you`. 2) Then, **click** on the Trusted Certificates `Import` button and select the `ca.crt` file you previously downloaded. 3. Continue with either the [Using FoxyProxy](/app/guides/foxyproxy.md#chrome) or [Using ZeroOmega](/app/guides/zeroomega.md#chrome) guides for Chrome. ## Firefox 1. Launch the Firefox browser, enter `about:preferences` in the address bar, and search for `View Certificates`. 2) **Click** on the `View Certificates...` button to open the Certificate Manager window. 3) Select the `Authorities` tab, **click** on the `Import...` button, and select the `ca.crt` file you previously downloaded. 4) In the Downloading Certificate window, select `Trust this CA to identify websites.` and **click** `OK`. 5. **Click** `OK` to close the Certificate Manager window. 6. Continue with either the [Using the Caido Extension](/app/guides/caido_extension.md), [Using FoxyProxy](/app/guides/foxyproxy.md#firefox) or [Using ZeroOmega](/app/guides/zeroomega.md#firefox) guides for Firefox. --- --- url: /app/troubleshooting/in_app.md description: >- Troubleshooting common Caido in-app errors including match and replace rules not working, responses not loading, permission issues, and missing user-interface sections. --- # In-app Issues ## Proxying Doesn't Work If you are unable to proxy traffic, tamper rules may be the cause. Disable any Match & Replace rules, network configuration settings, and ensure your [proxy settings are configured correctly](/app/troubleshooting/startup.md#resolution-1). ## Match & Replace Rule Not Working If a Match & Replace rule is not working or is not being applied, the formatting may be incorrect. Ensure you are viewing and working with the [raw](/app/guides/request_response_modes.md) representation of data. ## No Responses to Automate Requests If Automate requests are not receiving responses, unexpected input/output errors may be the cause. Select the `Settings` tab of the Automate interface and set the value of `Max retries` to `1`+. ## Can't Preview Responses This error may occur when Caido is running as root. ```text Rendering error: LaunchIo(Custom { kind: UnexpectedEof, error: "unexpected end of stream" }, BrowserStderr("[0101/110718.156035:ERROR:zygote_host_impl_linux.cc(90)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.\n")) ``` If you encounter this error message after attempting to preview a response, do not run Caido as the root user or launch Caido without the `--no-renderer-sandbox` command-line option. ## Looping Requests If a steady stream of requests are being sent to `api.caido.io` and/or `gstatic.com`, network configuration settings may be the cause. Disable your VPN and check your browser, upstream, SOCKS, and invisible proxy settings. ## Unable to Access Individual/Team Tier Subscription Features This error may occur when the cached state of your account has not been updated. If you are unable access premium subscription features, refresh your account state by reauthenticating to your Caido instance. ## "You don't have the required permissions for this action." This error may occur when you have exceeded the installation limits of workflows, plugins, or filters for your account type. If you encounter this error message after attempting to install an extension, remove extensions that are unused or less important to your current work, and then retry the installation. ## The GraphQL Playground Doesn't Work This error may occur when unauthenticated requests are being sent to the GraphQL server. If you are unable to make GraphQL API calls, access the GraphQL Playground in your browser by navigating to , **click** on the `Headers` tab, and add an `Authorization` header. ```json { "Authorization": "Bearer ACCESS_TOKEN_HERE" } ``` To acquire your token, open the browser's DevTools interface, select the `Application` tab, and copy the value of the `accessToken` in the `CAIDO_AUTHENTICATION` object within local storage. ## A Section of the User Interface is Missing If you are unable to view a section of the user-interface, it may have been minimized. Ensure the section pane wasn't [resized](/app/guides/ui.md#resizing-panes) inadvertently. ## Shell Node Timeouts This error may occur when workflows include a shell node. ```text "Error in $shell node: Failed to execute shell: Timeout" ``` By default, the initialization script sources from `bashrc` or `zshrc`, which may contain slow operations or hanging commands. Clear the `init` script field in the shell node configuration, or replace it with a minimal script that doesn't source shell configuration files. --- --- url: /app/guides.md description: >- A step-by-step guide to installing Caido on Windows, Linux, and macOS operating systems. --- # Installation Learn how to download and install Caido based on your operating system: * [Caido for Windows](/app/quickstart/windows.md) * [Caido for Linux](/app/quickstart/linux.md) * [Caido for macOS](/app/quickstart/mac.md) --- --- url: /app/troubleshooting/installation.md description: Commonly encountered Caido installation issues. --- # Installation Issues ## "The SUID sandbox helper binary was found, but is not configured correctly." This error may occur due to [AppArmor](https://apparmor.net/), the Linux application security system. Each time Caido is launched, it loads in the `tmp` directory as a virtual file system before execution. Due to this, there is no hook to add an AppArmor profile, which defines the permissions granted in the context of the operating system. ```text [142547:0410/141348.635410:FATAL:setuid_sandbox_host.cc(163)] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now. You need to make sure that /tmp/.mount_caido-PMiQot/chrome-sandbox is owned by root and has mode 4755. ``` If you encounter this error message after installing the [AppImage](/app/quickstart/linux#appimage) Caido package, either: ::: warning NOTE Ensure to replace `/path/to/caido-desktop-vX.XX.X-linux-.AppImage` with the correct path, versioning, and architecture of the AppImage package. ::: ### Create an AppArmor Profile for Caido (Preferred Method): To create an AppArmor profile for Caido, create a `appimage.caido` file with the following content in the `/etc/apparmor.d/` directory. ```bash sudo nano /etc/apparmor.d/appimage.caido ``` ```text abi , include profile appimage.caido /path/to/caido-desktop-vX.XX.X-linux-.AppImage flags=(unconfined) { userns, include if exists } ``` Once the file is written, save it, and then read/load the profile. ```bash apparmor_parser -r /etc/apparmor.d/appimage.caido ``` ### Run Caido without a Sandbox To disable the AppArmor sandbox security restrictions, launch Caido with the `--no-sandbox` command-line option. ```bash /path/to/caido-desktop-vX.XX.X-linux-.AppImage --no-sandbox ``` To apply this to every launch, create a `.desktop` extension file with the following content in either the `~/.local/share/applications/` directory (*for the current user account*) or the `/usr/share/applications/` directory (*for all user accounts*). ::: warning NOTE Ensure to replace `/path/to/caido-icon.png` with the correct path and file name of the image you want to use for Caido's desktop application icon. ::: ```ini [Desktop Entry] Version=1.0 Name=Caido Comment=Caido - A platform for secure vulnerability management Exec=/path/to/caido-desktop-vX.XX.X-linux-.AppImage --no-sandbox Icon=/path/to/caido-icon.png Terminal=false Type=Application Categories=Security;Utility;Networking; StartupNotify=true ``` Once the file is written, save it, and then refresh the desktop application icon cache. ```bash sudo update-icon-caches /usr/share/icons/* ``` ::: tip TIPS Caido's default desktop application icon is available at . ::: ### Disable AppArmor (Not Recommended) To disable AppArmor globally, use the `sysctl` utility to allow unprivileged users to create user namespaces. ```bash sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 ``` --- --- url: /app/quickstart/linux.md description: >- A step-by-step guide to installing Caido on Linux using .deb packages, AppImage, or AUR for different architectures. --- # Installing Caido on Linux For Linux users, the Caido desktop application is available for both `x86_64` and `AArch64` architectures and any distribution. ::: tip Caido comes preinstalled on [Parrot Security](/app/guides/parrot_os.md) and [Athena OS](/app/guides/athena_os.md). ::: ## Debian Distributions 1. To download the Caido desktop application for Debian-based Linux distributions, visit [www.caido.io/download](https://www.caido.io/download) and **click** on the `Linux (x86_64)` or `Linux (Aarch64)` button, depending on your architecture. ::: tip To discover which download is suitable for your device, enter the following terminal command: ```bash uname -m ``` ::: 2. Once the installation package has been downloaded, navigate to its directory, and install Caido with the `dpkg` package manager. ```bash sudo dpkg -i caido-desktop-vX.XX.X-linux-aarch64.deb ``` 3. Once Caido has been installed, launch Caido, and [continue to the setup instructions](/app/quickstart/setup.md). ```bash ./caido ``` ## AppImage 1. To download the Caido desktop application for any Linux distribution, visit the latest releases page on [Github](https://github.com/caido/caido/releases/latest), and download the `.AppImage` package appropriate for your architecture. ::: tip To discover which download is suitable for your device, enter the following terminal command: ```bash uname -m ``` ::: 2. Once the installation package has been downloaded, navigate to its directory, and make it executable with `chmod +x`. ```bash chmod +x caido-desktop-vX.XX.X-linux-.AppImage ``` 3. Rename the package to `caido` for convenience. ```bash mv caido-desktop-vX.XX.X-linux-.AppImage caido ``` 4. Once Caido has been installed, launch Caido, and [continue to the setup instructions](/app/quickstart/setup.md). ```bash caido ``` ::: warning TROUBLESHOOTING If Caido is not launching and you are getting a FATAL error message, view the [Installation Issues](/app/troubleshooting/installation.md) troubleshooting guide for possible fixes. ::: ## Arch User Repository ::: danger Using an unofficial repository to install Caido may expose you to potential security risks. The installation is managed by third-party maintainers, not the official Caido team, which means it may not be as regularly updated or audited. ::: 1. To download the Caido desktop application for Arch Linux and Arch-based distributions, first ensure you have the required dependencies installed. ```bash sudo pacman -S --needed git base-devel fuse2 ``` 2. Then, clone the package from the repository. ```bash git clone https://aur.archlinux.org/caido-desktop.git ``` 3. Once the package has been downloaded, navigate to its directory. ```bash cd caido-desktop ``` 4. Next, check for and install any missing dependencies, build the package from the source code, and install it with the `makepkg` tool. ```bash makepkg -si ``` 5. Ensure the package is executable with `chmod +x`. ```bash chmod +x caido-desktop-vX.XX.X-linux-.AppImage ``` 6. Rename the package to `caido` for convenience. ```bash mv caido-desktop-vX.XX.X-linux-.AppImage caido ``` 7. Once Caido has been installed, launch Caido, and [continue to the setup instructions](/app/quickstart/setup.md). ```bash ./caido ``` ::: warning TROUBLESHOOTING If Caido is not launching and you are getting a FATAL error message, view the [Installation Issues](/app/troubleshooting/installation.md) troubleshooting guide for possible fixes. ::: --- --- url: /app/quickstart/mac.md description: >- A step-by-step guide to installing Caido on macOS using .dmg files or Homebrew for Intel and Apple Silicon Macs. --- # Installing Caido on macOS For macOS users, Caido provides a desktop application for both the Intel-based `x86_64` and Apple Silicon `M1/M2/M3, AArch64` architectures. ## Disk Image (.dmg) A `.dmg` file is a macOS disk image used to distribute applications. It's the most common and user-friendly way to install apps on Mac. 1. To download the Caido desktop application for macOS, visit [www.caido.io/download](https://www.caido.io/download) and **click** on the `Mac Intel Chip` or `Mac Apple Chip` button, depending on your architecture. ::: tip [Learn which download is suitable for your device.](https://support.apple.com/en-us/116943) ::: 2. Once the download is complete, run the installation package and **click**, **hold**, and **drag** the Caido icon into the `Applications` folder. 3) Open the `Applications` folder, launch Caido, and [continue to the setup instructions](/app/quickstart/setup.md). ## Homebrew (Unofficial) ::: danger Using an unofficial Homebrew tap to install Caido may expose you to potential security risks. The installation is managed by third-party maintainers, not the official Caido team, which means it may not be as regularly updated or audited. ::: [Homebrew](https://brew.sh/) is a popular package manager that simplifies the installation and management of software. It allows users to easily install, update, and manage software packages from the command-line. ::: tip To download and install Homebrew, enter the following terminal command: ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` Once Homebrew is installed, add it to your PATH environment variable to make it available globally. ```bash echo >> /Users//.zprofile ``` ```bash echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users//.zprofile ``` ```bash eval "$(/opt/homebrew/bin/brew shellenv)" ``` ::: 1. To download and install the Caido desktop application on your macOS device with the Homebrew package manager, run `brew install` with the `--cask` command-line option. ```bash brew install --cask caido ``` 2. Open the `Applications` folder, launch Caido, and [continue to the setup instructions](/app/quickstart/setup.md). --- --- url: /app/quickstart/windows.md description: >- A step-by-step guide to downloading and installing Caido desktop application on Windows operating systems. --- # Installing Caido on Windows 1. To download the Caido desktop application for Windows, visit [www.caido.io/download](https://www.caido.io/download) and **click** on the `Windows (x86_64)` button. 2) Once the download is complete, run the `.exe` and follow the on-screen instructions. 3) After installation, launch Caido, and [continue to the setup instructions](/app/quickstart/setup.md). --- --- url: /app/guides/plugins_installing.md description: >- A step-by-step guide to installing plugins in Caido from the Community Store or local package files, including security considerations and risk acknowledgment. --- # Installing Plugins ::: warning Plugins available in the Community Store run third-party code, which could potentially pose security risks. Before you can access the Community Store, you must **click** on the *"I understand the risks associated with third-party plugins."* checkbox to acknowlege and accept the risk. ::: ::: tip [Learn how to create your own Caido plugins!](https://developer.caido.io/) ::: To install a plugin, either: * **Click** on the Install Package button and select a plugin `plugin_package.zip` file. * Or **click** on the `+ Install` button associated with a plugin available in the Community Store. --- --- url: /app/concepts/instance.md description: >- Understand the core concepts behind Caido instances - the client/server architecture, local vs remote instances --- # Instance An **instance** of Caido is effectively a directory on disk that contains the settings, projects, secrets, plugins, etc. that are created by Caido at runtime. This abstraction allows you to manage multiple, separate instances of Caido on a single device. ## Local vs Remote ### Local Instances A local instance runs on the same computer as you. Effectively, we will manage the [Caido CLI](./cli_vs_desktop.md) for you in the background. Additional local instances can be created using either the standalone Caido CLI or desktop application by [changing the data storage location](/app/guides/data_location.md). ### Remote Instances A remote instance runs on another computer that you can access over the network. Additional instances can also be created for remote installations of the Caido CLI via the launch window of the desktop application. ## Client/server When you start a Caido instance, you effectively start a server on a given port. You can use either the Caido Desktop application or a browser to access that instance. This is why we refer Caido has being built using a client/server architecture. --- --- url: /app/quickstart/intercept.md description: >- A step-by-step guide to Caido's Intercept feature for real-time traffic inspection, modification, and control during security testing. --- # Intercept The `Intercept` interface gives you direct control over proxied traffic, granting you the ability to inspect, modify, forward, and drop both requests and responses as they are sent between a client and a server. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDE * [Intercepting Traffic](/app/guides/intercept_traffic.md) ::: --- --- url: /app/guides/intercept_traffic.md description: >- A step-by-step guide to intercepting, modifying, and controlling HTTP/HTTPS traffic in Caido including forwarding, dropping, and editing capabilities. --- # Intercepting Traffic To begin intercepting proxied traffic, **click** on the Forwarding button to toggle it to Queuing. *** ::: tip If no subsequent traffic is intercepted, ensure the proxy settings of your client are properly configured and enabled. ::: To give you control over what traffic is intercepted, Caido provides buttons for HTTP requests, HTTP responses, and Websocket messages. To intercept traffic of a specific type, **click** on its associated button to toggle it to the state. When interception is enabled, Caido will list all of the awaiting traffic in a queue table. Select any queued HTTP request, HTTP response, or Websocket message from its associated table to view its contents. Once traffic has been intercepted, there are various actions that can be taken against it. ## Modifying Intercepted Traffic To make modifications to an intercepted HTTP request, HTTP response, or Websocket message, **click** inside its associated pane. ::: tip **Click** on the undo button to restore traffic to its original state. ::: ## Forwarding Intercepted Traffic **Clicking** on the `Forward` button will send the traffic to its target recipient. ::: info Any forwarded traffic that was modified from its original state will be marked as `Edited` within the `State` column of traffic tables. Both states can be viewed for comparison. ::: ## Dropping Intercepted Traffic **Clicking** on the `Drop` button will stop the traffic from being sent to its target recipient. ## Sending Traffic to Other Interfaces To send intercepted traffic to other interfaces, **right-click** within a traffic pane to open the context menu, and select a `Send to...` or `Plugins` option. ::: tip With a request pane focused, you can quickly send the request to Replay with the default keyboard shortcut `CTRL` + `R` or to Automate with `CTRL` + `M`. ::: ## Disabling Interception To resume passive forwarding for a specific traffic type, **click** on its associated button to toggle it to the state. To resume passive forwarding for all traffic, **click** on the Queuing button to revert back to the Forwarding state. --- --- url: /app/reference/workflow_interpolation.md description: >- Find detailed reference information on Caido Interpolation within workflow nodes allowing rich and dynamic reporting. --- # Interpolation Interpolation enables dynamic content generation within workflow nodes by embedding [JavaScript](#javascript-engine) expressions in text. Those expressions can take the following shapes: * [Inline](#inline-evaluation) * [Code Blocks](#tagged-code-blocks) ## Inline Evaluation Inline interpolation uses `<% %>` delimiters to execute JavaScript expressions and output results in-place within text. For example: ```md # Found <% issue_count %> issues ``` ::: warning NOTE The example above assumes a `issue_count` variable was previously declared. ::: ### Escaping Use `\<% %>` to display literal interpolation syntax without execution (shows as `<% %>`). ### Comments | Syntax | Description | |--------|-------------| | `<% value // comment %>` | Line comments - `%>` closes the interpolation block. | | `<% /* comment with %> */ value %>` | Block comments allow including `%>` in comments. | ## Tagged Code Blocks Markdown-style code blocks with the `exec` tag are evaluated by the JavaScript engine. For example: ````md ```exec const issue_count = 5; println("# Found " + issue_count + " issues"); ``` ```` ### Output Functions | Function | Description | |----------|-------------| | `print(...values)` | Outputs values without newline. | | `println(...values)` | Outputs values with newline. | ::: warning NOTE Only explicitly printed content appears in final output. The `exec` code block itself is not visible. ::: ::: tip As [all fields share the same context](#shared-context), pre-compute complex values in `exec` blocks without print statements, then reference variables in simple `<% variable %>` interpolations for improved readability. ::: ## Javascript Engine Interpolation uses [Caido's JavaScript runtime environment](/app/concepts/workflows_js.md). Refer to the [runtime documentaion](https://developer.caido.io/concepts/runtime.html) for detailed technical specifications. ### Accessing Previous Nodes All previous node outputs within a workflow are accessible using their [alias](/app/concepts/workflows_nodes.html#aliases), allowing interpolation to use values from earlier nodes in the workflow chain. ### Shared Context All interpolable fields within a workflow node share the same execution context which entails the following: * **Execution Order**: Interpolations execute sequentially in the order they appear within the node, allowing building upon previous computations. * **Shared Context**: All interpolations in a single node share the same JavaScript environment, meaning variables, functions, and state are accessible across all expressions within that node. --- --- url: /app/tutorials/android_introduction.md description: Learn how to proxy HTTP/HTTPS traffic generated by Android devices. --- # Introduction In this series, you will learn how to proxy HTTP/HTTPS traffic generated by Android devices. At a high-level, this process involves: * Establishing a connection between the device and your computer running Caido. * Configuring Wi-Fi proxy settings. * Port forwarding device traffic to Caido. However, the exact steps to accomplish this differs between physical/virtual devices and specific applications. As is the case with other clients, in order to proxy encrypted HTTPS traffic, Caido's CA certificate must be added as a trusted credential. Android devices store certificates in two separate partitions: 1. **System**: Stores pre-installed Root and Intermediary CA certificates. 2. **User**: Stores certificates added by users. Certain applications will trust user certificates, while others only trust system certificates. Additionally, some applications implement security measures directly in the application code to prevent communication with unintended servers. If an application is protected in such a manner, modifications to the application package must be made in order to proxy traffic. The tutorials in this series provide step-by-step instructions across physical and virtual device setups to account for these scenarios. ::: danger WARNING For physical devices, adding a certificate to the system partition requires the device to be rooted and is beyond the scope of this series. If you choose to attempt to root your physical device/add Caido's CA certificate to the system partition - Caido is not liable for any malfunctions, failures, damages, loss/theft of data, or other technical issues that may occur. Proceed at your own risk. ::: --- --- url: /app/guides/invisible_proxying.md description: >- A step-by-step guide to enabling invisible proxying in Caido CLI and Desktop application to capture traffic from non-proxy aware applications. --- # Invisible Proxying ::: tip View the [Invisible Proxying for Non-Proxy Aware Thick Clients](/app/tutorials/invisible_proxy.md) tutorial for a detailed walk-through on configuring invisible proxying. ::: ::: warning NOTE If you enable invisible proxying on a remote instance, you must ensure the **same address and port** is used. This includes any SSH port forwarding you may use. Otherwise, Caido will not be able to [split the traffic](/app/concepts/traffic_splitting) correctly and will not work. ::: ## Caido CLI By default, invisible proxying is **disabled** for the Caido CLI. To enable invisible proxying with the Caido CLI, launch Caido with the `--invisible` command-line option. ```bash caido --invisible ``` ## Desktop Application By default, invisible proxying is **enabled** for local instances. To disable invisible proxying within the Caido desktop application, in the launch window, **click** on the button attached to an instance and select `Edit`. Then, **click** on Advanced to expand the drop-down settings menu options and **click** on the `Enable invisible proxying` checkbox to remove its fill. **Click** on the `Save` button to update and save the configuration. --- --- url: /app/tutorials/invisible_proxy.md description: >- Learn how to set up invisible proxying in Caido, both manually and automatically with Proxifier, to capture traffic from thick client applications that don't support proxy configuration. --- # Invisible Proxying for Non-Proxy Aware Thick Clients In this tutorial you will be guided through the process of configuring clients that cannot be configured to utilize a HTTP proxy server via native settings, in order to view, intercept, and modify their traffic with Caido. ::: tip View the [Proxifier](/app/tutorials/invisible_proxy.md#proxifier) section to learn how to automate invisible proxying. ::: ## Thick Clients “Thick clients” refer to clients that lack native HTTP proxy server support. These clients perform the majority of their processes independently but occasionally communicate: * With a database server (*two-tier architecture*). * With an external backend server that communicates with a database server (*three-tier architecture*). While web applications that run inside a browser can be configured to use a proxy via the connection settings or an extension like [FoxyProxy](https://getfoxyproxy.org/), non-proxy aware thick clients ignore system proxy settings and do not have proxy setting options themselves. So, in order to pass the HTTP traffic that these thick clients generate through Caido, you will need to set up “invisible proxying”. ## Invisible Proxying In invisible proxying, Caido acts as the destination server that the thick client application is expecting to communicate with directly. ::: warning NOTE In this tutorial we will demonstrate setting up invisible proxying using a simple Node.js script that will act as a thick client communicating with `http://www.example.com/`. To follow along, ensure you have Node.js installed and create a file named `thick-client.js` with the following content: ```js const url = process.argv[2]; if (!url) { console.error("Usage: node fetch-test.js "); process.exit(1); } // Disable SSL verification (FOR TESTING ONLY). process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; fetch(url) .then((res) => res.text()) .then((body) => { console.log("Response:"); console.log(body); }) .catch((err) => { console.error("Fetch error:", err); }); ``` ::: ### DNS Resolution In order for Caido to capture the traffic, the domain name of a destination server needs to resolve to Caido’s listening address. ::: tip TIPS * To discover the domain/domains the thick client is communicating with, use a network traffic inspection tool like [Wireshark](https://www.wireshark.org/) and filter traffic by the DNS protocol. * To discover the IP address of a domain name, run the terminal command: ```bash nslookup www.example.com ``` ::: This can be done by adding `127.0.0.1 www.example.com` as an entry to either: * The `C:\Windows\System32\drivers\etc\hosts` file in Windows. * The `/etc/hosts` file in Linux and macOS. ### Port Binding / Forwarding The thick client will expect the destination server to be running on either port 80 (*for HTTP*) or 443 (*for HTTPS*). However, ports below 1024 are considered privileged ports which only bind to services running with root/administrative privileges. ::: danger Running Caido with root/administrative privileges is **NOT** recommended. Doing so **will** create issues later on since any resource created by Caido will be owned by the root/administrator user. **DO NOT DO THIS.** ::: Instead, you must either: * **Preferred Method**: Use port forwarding to redirect traffic intended for ports 80 and 443 to Caido's listening port. * Use alternative port binding methods available to certain operating systems. *** #### Windows On Windows, you can use the `netsh` (*Network Shell*) command-line utility to setup port forwarding. Open Command Prompt as Administrator and run: ```cmd netsh interface portproxy add v4tov4 listenport=80 listenaddress=127.0.0.1 connectport=8080 connectaddress=127.0.0.1 ``` ```cmd netsh interface portproxy add v4tov4 listenport=443 listenaddress=127.0.0.1 connectport=8080 connectaddress=127.0.0.1 ``` ::: tip TIPS View any active rules with: ```cmd netsh interface portproxy show all ``` Remove the rules with: ```cmd netsh interface portproxy delete v4tov4 listenport=80 listenaddress=127.0.0.1 ``` ```cmd netsh interface portproxy delete v4tov4 listenport=443 listenaddress=127.0.0.1 ``` ::: *** #### macOS On macOS, you can use the `pfctl` (*Packet Filter*) command-line utility to setup port forwarding by writing a redirection rule in a `pf.conf` file. Open the `/etc/pf.conf` file and add: ```bash rdr pass on lo0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080 rdr pass on lo0 inet proto tcp from any to any port 443 -> 127.0.0.1 port 8080 ``` Reload the rules with: ```bash sudo pfctl -f pf.conf ``` Ensure Packet Filter is enabled with: ```bash sudo pfctl -e ``` ::: info As Packet Filter hijacks port 8080, Caido's user interface will no longer load on that port. Currently, the only workaround to this is to use the CLI parameter `--ui-listen 8081` to bind another port for the UI. ::: ::: warning Alternatively, to bind ports 80 and 443 on macOS without using root permissions or port fowarding, you can instead configure Caido to listen on all interfaces (`0.0.0.0`). However, we do **NOT** recommend doing this in untrusted networks since this allows **ANY** computer on the same network as you to proxy through your computer. ::: *** #### Linux On Linux, you can use the `iptables` command-line utility to setup port forwarding. Open a terminal and run: ```bash sudo iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-port 8080 ``` ```bash sudo iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 443 -j REDIRECT --to-port 8080 ``` ::: tip TIPS View any active rules with: ```bash sudo iptables -t nat -L OUTPUT -n -v --line-numbers ``` Remove the rules with: ```bash sudo iptables -t nat -F OUTPUT ``` Alternatively, on Linux, you can grant the Caido CLI permission to bind to ports 80 and 443 with: ```bash sudo setcap 'cap_net_bind_service=+ep' ./path/to/caido-cli ``` Ensure you grant permission to the CLI, **NOT** the desktop application. Usually, the binary will be found under `resources/bin/caido-cli` in your installation directory. ::: *** ### Enable Invisible Proxying To enable invisible proxying: 1. In the launch window, **click** on the button attached to an instance and select `Edit`. 2) Then, **click** on Advanced to expand the drop-down settings menu options and **click** on the `Enable invisible proxying` checkbox. 3. **Click** on the `Save` button to update and save the configuration. ### DNS Rewrite The target domain will now resolve to Caido. However, Caido will also resolve the domain to itself, since DNS queries will check the `hosts` file before being sent to a resolver. In order for Caido to pass the request along to the actual destination server, you must create a [DNS Rewrite](/app/guides/dns_rewrites.md) rule to preserve the original IP address of the target domain. To create a rule: 1. **Click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `Network` tab. 2) Scroll down and **click** on the `+ Add Rewrite` button. 3) **Click** on the `Use static IP` checkbox and type in the IP address in the `Redirect to static IP` input field. 4) Add `www.example.com` to the `Included Hosts` list and **click** on the `+ Create` button to save the rule. ::: tip Glob syntax (\*) is supported to account for varying subdomains and top-level domains/extended top-level domains. ::: ### Testing To test the configuration, navigate to the directory in which the `thick-client.js` file is saved to and enter: ```bash node thick-client.js http://www.example.com/ ``` And: ```bash node thick-client.js https://www.example.com/ ``` Each time the script is executed, a new request will be proxied through Caido. ::: tip You may need to flush the DNS cache. ```cmd ipconfig /flushdns ``` ::: ## Proxifier Instead of manually configuring invisible proxying, [Proxifier](https://www.proxifier.com/) is an application that automatically proxies traffic generated by thick clients. By creating a proxy profile for Caido's listening address and rules for which applications should be proxied, you can route traffic through Caido. 1. Download and install Proxifier by visiting . 2. Accept any prompts/adjust your device settings to grant Proxifier permission. 3. **Click** on `Proxies` in the top navigation bar and select `Add...`. 4) Enter Caido's listening address and port in the related fields, select `HTTPS` as the protocol, and enable the `Appear as Web Browser` checkbox. 5) **Click** on the `Advanced...` button and enable the `Use target hostname in proxy request if available` checkbox. 6. **Click** on the `Save` button to save the configuration. 7. Next, **click** on `Rules` in the top navigation bar and select `Add...`. 8. Provide a name for the rule, the name of the application you want to proxy, and the hosts that you want to proxy. 9. **Click** on the `Action` dropdown menu and select the proxy profile you created previously. 10) **Click** on the `Save` button to save the configuration. ::: tip Rules can be managed by **clicking** on the `Action` dropdown menu from the `Rules` tab interface. ::: --- --- url: /app/tutorials/ios_configuration.md description: >- Learn how to configure iOS devices to proxy HTTP/HTTPS traffic through Caido including proxy settings and certificate installation. --- # iOS Setup and Configuration In this tutorial, we will cover how to setup and configure an iOS device in order to proxy HTTP/HTTPS traffic generated by iOS applications. ::: danger WARNING Caido is not liable for any malfunctions, failures, damages, loss/theft of data, or other technical issues that may occur with your device as a result of following this tutorial. Proceed at your own risk. ::: ::: info * Be aware that the exact names and locations of setting options may vary between devices. * Ensure to pay attention to any prompts on the device itself while proceeding through these steps. * For convenience, add all installed tools to your system's `PATH` envrionment variable to make them globally accessible. Ensure to restart your terminal afterwards so the changes take effect. ::: ## Configuring Caido To capture traffic from your Apple devices on your Wi-Fi network, you will need to edit the default settings of Caido. 1. In the launch window, **click** the vertical ellipsis button of your desired instance and select `Edit`. 2. Select `All interfaces (0.0.0.0)` and **click** the `Save` button in the bottom right corner. 3) Now, launch Caido. ## Configuring the Proxy Settings 1. On your iOS device, navigate to `Settings` and select `Wi-Fi`. 2. Ensure your device is on the same network as your computer. 3. Select the network SSID and scroll down to select the `Configure Proxy` option, then select the `Manual` option. 4. In the `Server` field, enter the IP address of your computer running Caido (*run the terminal command `ipconfig` in Windows or `ifconfig` in macOS/Linux to discover your computer's IP address*). Then enter the listening port of Caido in the `Port` field. Once the values have been added, **click** `Save` in the upper left corner. 5) In the Safari browser, visit `http://:8080/ca.crt` (*replace `` with the IP address of your computer*) to download Caido's CA certificate. Select `Allow` in the prompt. In the `Choose a Device` prompt, select the device you are currently using. **Click** `Close` in the `Profile Downloaded` notification. 6) Return to your device's `Settings`, **click** on the `Profile Downloaded` option, and then **click** `Install`. On the warning screen, **click** `Install` again and `Install` yet again at the bottom. Then select `Done`. 7) **Click** the `< Back` button in the upper left corner to return to the `General Settings` screen. Next, select the `About` option. At the bottom of this screen will be the `Certificate Trust Settings` option, select this and then enable Caido to be a trusted root certificate. In the warning prompt, select `Continue`. ::: tip To test if the certificate was successfully installed for Wi-Fi, launch the device's browser and navigate to a website. You should see the traffic in Caido's HTTP History table. Next, open an application and view if the traffic it is generating is being proxied. This will vary depending on the security techniques used by the developers. ::: ::: info Applications may have security measures that will prevent them from working properly and allowing [Caido to proxy the HTTPS traffic](/app/concepts/web_traffic.md) they generate. If the application is still not working properly and traffic is still not being proxied, you will need to take additional steps to bypass these measures. Due to Apple's robust security, the easiest way to do so is to obtain a device running an operating system version that has a jailbreak available. ::: --- --- url: /app/concepts/workflows_js.md description: >- Understand the core concepts behind using JavaScript in Caido workflows including QuickJS engine, TypeScript, JSDoc, and SDK integration. --- # JavaScript in Caido *Below includes in-depth foundational information, to skip to usage of JavaScript in workflow nodes - navigate to the [JavaScript node functions](#javascript-node-functions) section.* ## Why JavaScript? Caido's decision to implement JavaScript as opposed to another programming language was arrived at based on multiple factors. With JavaScript, context switching between the frontend and backend is minimal. JavaScript is a versatile language and easy to learn. Also, JavaScript is a familiar language to those that are using Caido as it is present in every engagement. ## QuickJS Caido uses the [QuickJS Engine](https://github.com/bellard/quickjs) to handle any JavaScript code it receives. Without implementing an engine - Caido would not be able to utilize JavaScript for creating workflows. Caido leverages the QuickJS Engine to: 1. Identify that the received input is JavaScript code. 2. Parse and interpret the code. 3. Run the code - performing the actions and computations within it. ::: warning NOTE As QuickJS is a lightweight, embeddable JavaScript engine - it **does not** have built-in support for TypeScript or all modules you would find in the browser or in Node.js. ::: ## Typing JavaScript is a [dynamically typed language](https://developer.mozilla.org/en-US/docs/Glossary/Dynamic_typing), meaning that entities do not have a fixed data type and can hold values of any data type. The data type is determined at runtime based on the assigned values. However, specific data types for entities may be required for code to run properly. In order to achieve this, Caido utilizes [JSDoc](#jsdoc) in the workflow coding environment and external [TypeScript](#typescript). JSDoc comments in JavaScript inform you as to what data type an entity expects. TypeScript is used to explicitly assign data types to entities - a process known as [type annotation](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#functions). TypeScript then verifies that the correct data type is supplied in a process known as **[static type-checking](https://www.typescriptlang.org/docs/handbook/2/basic-types.html#static-type-checking)**. Static type-checking is a preemptive measure to make sure you supplied the correct parameter types that Caido’s backend requires in order for the proper execution of the `run` function. ::: info The data types that workflows use are: bytes, strings, Boolean values, integers, request objects and response objects. ::: ### JSDoc [JSDoc comments](https://jsdoc.app/about-getting-started) start with `/**` and end with `*/`. Within these comment blocks, you can use various tags and annotations to provide specific information about the code element being documented. ::: info Some commonly used JSDoc tags include: * @param: Describes the parameters accepted by a function, including their names, types, and descriptions. * @returns: Describes the return value of a function, including its type and description. * @type: Specifies the data type of a variable or property. ::: Below is the default `run` function used by the JavaScript Convert node: ::: tip Convert Type Function ```js /** * @param {Bytes} input * @param {SDK} sdk * @returns {MaybePromise}` */ export function run(input, sdk) { let parsed = sdk.asString(array) sdk.console.log(parsed); return parsed; }; ``` The value inside the `{}` is the type. ::: Using the comments as reference, you can view the declaration file to determine which methods are available to be called upon. ::: warning NOTE JSDoc comments for function parameters do not directly assign types to the parameters themselves. Meaning they will not enforce or assign types during runtime. However they are used in Caido to provide autocompletion and inform you on the expected type. ::: ### TypeScript [TypeScript](https://www.typescriptlang.org/) is referred to as **superset** of JavaScript. A superset builds upon a programming language, adding additional capabilities. TypeScript can be used when building workflows outside of Caido - such as when using the workflow Starter Kit. ::: tip Example: ```ts function addNumbers(a: number, b: number): number { return a + b; }; const result = addNumbers(2, "Hello world!"); ``` In this example: * The `addNumbers` function takes two parameters (`a` and `b`). * Both `a` and `b` have a type annotation of `number` (applied using the syntax `entity: type`) - they each must have a value that is either an integer or float. * The return value is of type `number` (applied using the syntax `: return data type`). * Parameter `b` in the function call stored in the `result` variable has a string type value of `"Hello world!"` which is invalid. * With static type-checking, you will receive the following error **before** the function is even ran: `Argument of type 'string' is not assignable to parameter of type 'number'.` ::: With TypeScript, you can **also** create custom data types. This is accomplished by defining the custom data types in what is known as a [declaration file](https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html) (*TypeScript declaration files have the `.d.ts` extension*). Within a declaration file, you will find declared [type aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases) and [classes](https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#classes) (*among other entities*). ::: info The `export declare` syntax in TypeScript is used to provide type definitions or declarations for external entities. ::: #### Type Aliases When you declare a type alias, you are able to define the type/s that an entity should have. ::: tip Example: The custom type alias definition in a TypeScript declaration file named `types.d.ts` is as follows: ```ts export declare type Account = { username: string; age: number; isVerified?: boolean; }; ``` The external object entity in a TypeScript file named `script.ts` is as follows: ```ts const account: Account = { username: 'ninjeeter', age: 35 }; ``` In this example: * The type alias of `Account` defines that the `username` property should be of type `string`, the `age` property should be of type `number` and the `isVerified` property is optional (denoted by the `?`), but if it is present, should be of type `boolean`. * The object in the external file `script.ts` has the `Account` type alias (applied using the syntax `entity: Alias`). * The `account` object passes static type-checking since the property values are all valid types. ::: #### Classes When you declare a custom class type, you are able to define an object's: * `Constructor`: A special method used to create an `instance` of the class. An instance is simply a new object that inherits the properties and methods that are included in that class. The constructor's parameter/s, used to initialize the object and its property/properties or set its initial state, can be type annotated. * `Properties`: The characteristics of the object class, of which you can add type annotation. * `Methods`: The functions that perform actions/calculations using the object's properties and other logic. You can add [type annotation to the function parameter/s](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#parameter-type-annotations) as well as the [return value](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#return-type-annotations). ::: tip Example: The custom class type definition in a TypeScript declaration file named `types.d.ts` is as follows: ```ts export declare class WelcomeMessage { constructor(username: string); greet(userId: number): void; }; ``` The method function code in an external TypeScript file named `greetFunction.ts` is as follows: ```ts export function greet(userId: number): void { console.log(`Welcome User ${userId}!`); } ``` The usage of the object entity in an external TypeScript file named `script.ts` is as follows: ```ts import {greet} from './greetFunction.ts'; const obj: WelcomeMessage = new WelcomeMessage("ninjeeter"); obj.greet(123); ``` In this example: In the `types.d.ts` file: * The custom class type definition of `WelcomeMessage` defines that the `username` parameter of the constructor method should be of type `string`. * The `userId` parameter should be of type `number`. This parameter is used as an argument of the `greet()` method that is included in the object class. *** In the `greetFunction.ts` file: * The `greet()` method function code defines that the return value is `void` (applied using the syntax `: return data type`), since no value is returned but rather printed to the console using `console.log`. *** In the `script.ts` file: * The `greet()` function is imported from the `greetFunction.ts` file. * The object has the `WelcomeMessage` type (applied using the syntax `entity: type`). * The constructor method is called and the static type-checking passes since a valid `string` type value is supplied. A new object of the `WelcomeMessage` class is created. * The `greet()` method is called on the `obj` variable that stores the instance. The parameter value of `123` satisfies the `number` type requirement. * The following message is printed to the console: `Welcome User 123!` ::: ::: info The constructor parameter used to create the instance will become a property. In the above example, if you used `console.log(obj.username)`, the output would be as follows: ```text "ninjeeter" ``` ::: ## SDK [View the developer documentation for more information.](https://developer.caido.io/reference/sdks/workflow/) For simplicity, in Caido when referring to the SDK - we are speaking of the methods that allow a JavaScript program ran in a JavaScript node to interact with the rest of Caido backend. These methods are the ones included within the SDK object: ```ts export declare type SDK = { console: Console; findings: FindingsSDK; requests: RequestsSDK; asString(array: Bytes): string; }; ``` ::: info The SDK object inherits all the methods of `Console`, `FindingsSDK` and `RequestsSDK`. ::: This SDK object is the second parameter of the `run` function used by the JavaScript node in workflows. ::: tip Convert Type JavaScript Node Function ```js export function run(input, sdk) { let parsed = sdk.asString(array) sdk.console.log(parsed); return parsed; }; ``` ::: ::: tip Passive & Active Type JavaScript Node Function ```js export async function run({ request, response }, sdk) { if (request) { let host = request.getHost(); sdk.console.log(host); } } ``` ::: ## JavaScript Node Functions When a JavaScript node is executed inside a workflow, one of two functions is ran - depending on the [workflow type](/app/concepts/workflows_intro.md). ### Convert Type JavaScript Node Function ```js /** * @param {BytesInput} input * @param {SDK} sdk * @returns {MaybePromise} */ export function run(input, sdk) { let parsed = sdk.asString(input); sdk.console.log(parsed); return parsed; } ``` ::: tip Function Breakdown & Declaration Associations The JSDoc comment uses type tags to note what types are assigned to the function parameters: ```javascript /** * @param {BytesInput} input * @param {SDK} sdk * @returns {MaybePromise} */ ``` The `input` parameter type is of type `BytesInput`. The `sdk` parameter is of the object type `SDK`. The associated declarations are: ```ts export declare type BytesInput = Array; export declare type SDK = { console: Console; findings: FindingsSDK; requests: RequestsSDK; asString(array: Bytes): string; }; ``` The return value is of type `MaybePromise`. This type allows the handling of both synchronous and asynchronous functions. The value between the angle brackets `<>` is a placeholder for another type. `Data` is the type used which itself has a type of `Bytes` which can be of data types `string`, `Array`, or `Uint8Array`. The associated declarations are: ```ts export declare type MaybePromise = T | Promise; export declare type Data = Bytes; export declare type Bytes = string | Array | Uint8Array; ``` The `run` function is available to be imported in external scripts. The function takes two parameters: `input` and `sdk`. The variable `parsed` stores `sdk.asString(input)` to convert bytes into a string. The `SDK` object assigned to `sdk` then uses the `console.log` method that it inherited from the `Console` object. This method is called on the `parsed` variable. The value of `parsed` will be printed to the backend logs. The associated declaration is: ```ts export declare type Console = { debug(message: any): void; log(message: any): void; warn(message: any): void; error(message: any): void; }; ``` Finally, `return parsed` returns the string converted data. ::: ### Passive & Active Type JavaScript Node Function ```js /** * @param {HttpInput} input * @param {SDK} sdk * @returns {MaybePromise} */ export async function run({ request, response }, sdk) { if (request) { let host = request.getHost(); sdk.console.log(host); } } ``` ::: tip Function Breakdown & Declaration Associations The JSDoc comment uses type tags to note what types are assigned to the function parameters: ```javascript /** * @param {HttpInput} input * @param {SDK} sdk * @returns {MaybePromise} */ ``` The `input` parameter type is of the object type `HttpInput` which itself contains a `request` object and `response` object pair (*if they exist*). The `sdk` parameter is of the object type `SDK`. The associated declarations are: ```ts export declare type HttpInput = { request: Request | undefined; response: Response | undefined; }; export declare type Request = { getId(): ID; getHost(): string; getPort(): number; getTls(): boolean; getMethod(): string; getPath(): string; getQuery(): string; getHeaders(): Record>; getHeader(name: string): Array | undefined; getBody(): Body | undefined; toSpec(): RequestSpec; toSpecRaw(): RequestSpecRaw; }; export declare type Response = { getId(): ID; getCode(): number; getHeaders(): Record>; getHeader(name: string): Array | undefined; getBody(): Body | undefined; }; export declare type BytesInput = Array; export declare type SDK = { console: Console; findings: FindingsSDK; requests: RequestsSDK; asString(array: Bytes): string; }; ``` The return value is of union type `MaybePromise` due to the function being asynchronous. This type allows the handling of both synchronous and asynchronous functions. The value between the angle brackets `<>` separated by the `|` holds two types - `Data` OR `undefined`. `Data` type has a type of `Bytes` which can be of data types `string`, `Array`, or `Uint8Array`. A resolved promise is returned as `Data`. OR the return value can be `undefined` if the promise is rejected. The associated declarations are: ```ts export declare type MaybePromise = T | Promise; export declare type Data = Bytes; export declare type Bytes = string | Array | Uint8Array; ``` The `run` function is available to be imported in external scripts. The function takes two parameters: `input` and `sdk`. If the `request` exists (*evaluates to true*) - the `getHost()` method is called on it. This is stored in the `host` variable. The `SDK` object assigned to `sdk` then uses the `console.log` method that it inherited from the `Console` object. This method is called on the `host` variable. The associated declaration is: ```ts export declare type Console = { debug(message: any): void; log(message: any): void; warn(message: any): void; error(message: any): void; }; ``` Finally, the value of `host` will be printed to the backend logs. ::: ## Example ### X-Forwarded-For Passive Workflow This workflow will check the if the status code of responses to requests are either **401** or **403**. If so, a new request will be sent with the `X-Forwarded-For: 127.0.0.1` header. If the status code of the response to this newly issued request is 200 - a new finding will be created, alerting you of the bypass. The associated request/response pair to the bypass will be displayed rather than the original request/response pair in the finding. ```js /** * @param {HttpInput} input * @param {SDK} sdk * @returns {MaybePromise} */ export async function run({ request, response }, sdk) { let reqID = request.getId(); let respCode = response.getCode(); sdk.console.log(`401/403 BYPASS WORKFLOW - Request ${reqID} received a code of: ${respCode}`); if (respCode === 401 || respCode === 403) { const spec = request.toSpec(); spec.setHeader("X-Forwarded-For", "127.0.0.1"); let bypass = await sdk.requests.send(spec); if (bypass.response.getCode() === 200) { let finding = { title: "401/403 Bypass", description: `SUCCESS! Auth bypass via X-Forwarded-For header for ${bypass.request.getMethod()} ${bypass.request.getPath()} to ${bypass.request.getHost()}.`, reporter: "X-Forwarded-For Passive Workflow", request: bypass.request }; await sdk.findings.create(finding); } } } ``` ::: tip Function Breakdown * The asynchronous `run` function is created and is available to be imported in other scripts. * The first parameter of the function is a `request` object and `response` object pair. The second parameter of the function is the `SDK` object - used to interact with Caido's backend. The return value is a `promise` - a resolved promise is returned as `Data` OR the return value can be `undefined` if the promise is rejected. * A message is printed in the logs that references the request `ID` of the currently handled request. * If the response status code is either 401 or 403 - then the associated request is converted into a mutable state using the `toSpec()` method and stored in the `spec` variable. * The `setHeader()` method is called on the mutable request - adding `X-Forwarded-For: 127.0.0.1` as a header. * The request is sent using the `sdk.requests.send()` method. The response to this request is awaited and stored in the `bypass` variable. * The `getCode()` method is called on this new response. If the status code is 200 - a Finding object is created and stored in the `finding` variable. * The `sdk.findings.create()` method is called. * This call will await the completion of the creation process of the `finding` object and then creates a new Finding with it in the Caido interface. ::: --- --- url: /app/guides/discord.md description: >- A step-by-step guide to linking your Caido account to Discord and accessing customer support channels for Individual and Team tier subscribers. --- # Joining Caido's Discord Server To link your Caido account to your Discord account, visit and click the `Sign in with Discord` button. ## Customer Support Users with active Individual tier subscriptions will be granted the `Customer` role and gain access to prioritized support channels in Caido's Discord server. All Team tier subscriptions include a dedicated, private support channel. To request a channel, email . --- --- url: /dashboard/guides/licensing.md description: >- Learn how to configure payment methods and billing information in the Caido Dashboard. --- # Licensing In order for team members to access workspace instances, each member must claim a "seat" of your Team or Enterprise tier subscription. ## Billing To upgrade your account subscription, click on the Upgrade button in the `Active Plan` section of the `Home` tab interface. ::: info Caido uses [Paddle](https://www.paddle.com/) for payment processing. ::: Team tier accounts include a maximum of 50 seats. To select the number of seats for your team, click on the arrow buttons to increase or decrease the total seat count at checkout. ::: warning NOTE If your organization needs additional seats, purchase orders, security questionnaires, custom terms, or custom integrations [contact sales](https://app.formbricks.com/s/cm8m73pnu0000jm03mw4wzejl) to obtain an Enterprise tier account. ::: ## Assigning Seats Once an account holds an active Team or Enterprise tier subscription, seats can be assigned to members with an Active status by **clicking** the `Use seat` checkbox of a team member's row in the `Users` page. --- --- url: /app/guides/listening_ports.md description: >- A step-by-step guide to configuring Caido to listen on multiple ports for UI and proxy traffic using CLI options and traffic splitting bypass. --- # Listening on Multiple Ports To listen for traffic on additional ports launch the Caido CLI with the `--ui-listen ` and multiple `--proxy-listen ` command-line options. ::: info Specifying different listening ports for the user-interface GraphQL API calls and traffic bypasses Caido's default [traffic splitting algorithm](/app/concepts/traffic_splitting.md). ::: ::: warning Please note that if you change the listening address to something other than 127.0.0.1, Caido will be accessible from any device on the network, so it is important to consider the security implications of doing so. ::: For example, to listen for traffic on two ports, enter: ```bash caido-cli --ui-listen 127.0.0.1:8080 --proxy-listen 127.0.0.1:8081 --proxy-listen 127.0.0.1:8082 ``` The user-interface will launch in a browser window at `127.0.0.1:8080`. You can then configure proxy settings to listen for traffic on `127.0.0.1:8081` and `127.0.0.1:8082`. *** *** *** --- --- url: /app/troubleshooting/authentication.md description: >- Troubleshooting authentication issues in Caido including instance access problems and login URL generation failures. --- # Login Issues ## "You do not have access to this instance. Go to dashboard." - "Login URL generation failed: invalid authentication token." - "The instance is no longer valid." These errors may occur when you are trying to access an instance of a different account or the instance has been deleted from the [Dashboard](https://dashboard.caido.io). *** If you encounter one of these error messages after attempting to login, either: ### Use the Other Account To gain access to the instance, login to the account that created the instance. ### Reset the Instance Credentials To reset the instance credentials with the Caido CLI, launch Caido with the `--reset-credentials` command-line option. ```bash caido --reset-credentials ``` To reset the instance credentials within the Caido desktop application, in the launch window, **click** on the button attached to an instance and select `Edit`. Then, **click** on Advanced to expand the drop-down settings menu options and **click** on the `Reset credentials` checkbox. **Click** on the `Save` button to update and save the configuration. ::: warning NOTE Once you have authenticated to the instance, ensure to remove the `--reset-credentials` option or checkbox, otherwise your instance credentials will be reset on every launch. ::: ### Delete the Data Storage Directory Although it is not recommended, deleting the [data storage directory](/app/reference/data_storage.md) reset the installation. ## "Date mismatch: make sure your device's date and time settings are correct." This error may occur due to your computer time being out of synchronization with the Coordinated Universal Time (UTC). For authentication, Caido only allows up to 5 minutes of deviation. If you encounter this error after attempting to login, manually adjust the time utilized by your operating system. ### Windows To synchronize the time on Windows, **right-click** on the clock, select Adjust date and time, and **click** on the `Sync now` button. ### macOS To synchronize the time on macOS, use the `sntp` utility with the `-S` command-line option. ```bash sudo sntp -S pool.ntp.org ``` ::: tip Check the time synchronization status with the same command. ::: ### Linux To synchronize the time on Linux, install the `ntp` package. Once the installation is complete, the service will start automatically. ```bash sudo apt-get install ntp ``` ::: tip Check the time synchronization status with `sudo systemctl status ntp`. --- --- url: /app/guides/elements.md description: >- A step-by-step guide to managing UI elements in Caido including context menu options, buttons, and interface controls for workspace management. --- # Managing Elements As you use Caido, the user-interface will populate with elements that reflect your activity. The majority of these elements come with various controls, available as buttons or menu options, that are designed to give you fine-grained control over your workspace. ## Context Menu Options **Right-clicking** on certain elements in the Caido user-interface will open a context menu with various actions and options to select from. ::: tip [View a comprehensive list of all context menu options and their functionality.](/app/reference/context_menu.md) ::: ## Buttons As Caido is designed with ease-of-use in mind, all buttons are intuitive or labeled. If a button is not visibly labeled, hover your mouse cursor over it to reveal its label. --- --- url: /app/guides/scopes_managing.md description: >- A step-by-step guide to managing scope presets in Caido including adding targets, duplicating presets, and deleting scope configurations. --- # Managing Scopes Once a scope preset is created, there are various actions that can be taken against it. ## Adding to Target Lists To add targets to an existing scope preset, you can either: * Select the scope preset from the Scopes interface, manually type targets into either the `In Scope` or `Out of Scope` lists, and apply the updates by **clicking** the Save button. * Or you can add a request's target domain to the scope preset by **right-clicking** on a request pane, hovering your mouse cursor over `Add in Scope` or `Add out of Scope`, and selecting the scope preset by its name. A message will appear notifying you that the operation was successful. *** ## Duplicating a Scope Preset To create a copy of a scope preset, **click** on the Duplicate button. ## Deleting a Scope Preset To permanently delete a scope preset, **click** on the `Delete` button. --- --- url: /app/quickstart/match_replace.md description: >- A step-by-step guide to Caido's Match & Replace feature for automatically modifying requests and responses with custom rules. --- # Match & Replace The `Match & Replace` interface gives you the ability to create rules that will automatically add, remove, or replace specific values within requests and responses as they are passed through Caido. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Selecting a Traffic Source](/app/guides/match_replace_sources.md) * [Adding a Header](/app/guides/match_replace_header.md) * [Using Capturing Groups](/app/guides/match_replace_capturing.md) * [Encoding Body Data](/app/guides/match_replace_encoding.md) * [Testing Rules](/app/guides/match_replace_testing.md) ::: --- --- url: /app/reference/match_replace.md description: >- Find detailed reference information on Caido's Match & Replace feature including request/response sections, actions, matchers, and replacers. --- # Match & Replace ::: tip If you're having an issue with your Match & Replace rule not taking affect, make sure you're looking at the un-prettified version of the request/response body by pressing the `{}` button within any request/response pane to ensure your spacing is correct. ::: ## Request Sections | Section | Target | |---------|-------------| | Request Path | The path of a request. | | Request Method | The HTTP method of a request. | | Request Query | The query of a request. | | Request First Line | The first line of a request. | | Request Header | The header or headers of a request. | | Request Body | The body data of a request. | ## Response Sections | Section | Target | |---------|-------------| | Response First Line | The first line of a response. | | Response Status Code | The HTTP status code of a response. | | Response Header | The header or headers of a response. | | Response Body | The body data of a response. | ## Request Query Section Actions | Action | Description | |--------|-------------| | Update Raw | Makes modifications to the query as a whole. | | Update Param | Matches against a query parameter key name and modifies its value. | | Add Param | Appends an additional query parameter. | | Remove Param | Removes a query parameter by key name. | ## Request Header/Response Header Section Actions | Action | Description | |--------|-------------| | Update Raw | Makes modifications to the headers as a whole. | | Update Value | Matches against a header's key name and modifies its value. | | Add | Inserts a new header key-value pair. | | Remove | Removes a header by key name. | ## Matcher | Matcher | Description | |---------|-------------| | Full | Matches against the entire section will be replaced. If there are multiple section items, such as when dealing with headers, all instances will be replaced. | | Regex | Matches against Rust flavor regular expressions. | | String | Matches against string values. | ::: warning NOTE Caido does not currently support look-around and backreference regular expressions. ::: ::: tip To test your regular expressions, visit [regex101.com](https://regex101.com/). ::: ## Replacer | Replacer | Description | |----------|-------------| | Term | Replaces the match with a string value. | | Workflow | Applies a workflow to the match. | --- --- url: /app/tutorials/md5_hash.md description: >- Learn how to create a convert workflow that generates MD5 hash digests from input data with various encoding options. --- # MD5 Hash Input Workflow In this tutorial, we will create a convert workflow that will MD5 hash input. ## Creating a Convert Workflow To begin, navigate to the Workflows interface, select the `Convert` tab, and **click** the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections Too add nodes to the workflow, **click** on `+ Add Node` button and then the `+ Add` button of a specific node. For this workflow, the overall node layout will be: * The `Convert Start` node outputs `$convert_start.data` that represents the input that will undergo conversion. * The input will be passed to the `MD5 Hash` node. * Once the input has been hashed and encoded by the `MD5 Hash` node, the `$md5_hash.data` will be output, and the workflow will end. ## MD5 Hashing 1. **Click** on the `MD5 Hash` node to access its editor and ensure the `$convert_start.data` is [referenced as input data](/app/guides/workflows_references.md). 2. Then, select an encoding type from the `Encoding (choice)` drop-down menu. Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ## Testing the Workflow To test the workflow, type in the value to be MD5 hashed in the `Input` text area and **click** on the `Run` button. A message will appear notifying you that the workflow executed successfully. ## The Result The MD5 hash digest will appear in the `Output` text area: The full workflow is provided below, ready to be imported. ```json { "description": "Converts a value to an MD5 hash digest.", "edition": 2, "graph": { "edges": [ { "source": { "exec_alias": "exec", "node_id": 0 }, "target": { "exec_alias": "exec", "node_id": 2 } }, { "source": { "exec_alias": "exec", "node_id": 2 }, "target": { "exec_alias": "exec", "node_id": 1 } } ], "nodes": [ { "alias": "convert_start", "definition_id": "caido/convert-start", "display": { "x": -210, "y": 90 }, "id": 0, "inputs": [], "name": "Convert Start", "version": "0.1.0" }, { "alias": "convert_end", "definition_id": "caido/convert-end", "display": { "x": 200, "y": 90 }, "id": 1, "inputs": [ { "alias": "data", "value": { "data": "$md5_hash.data", "kind": "ref" } } ], "name": "Convert End", "version": "0.1.0" }, { "alias": "md5_hash", "definition_id": "caido/md5-hash", "display": { "x": 0, "y": 90 }, "id": 2, "inputs": [ { "alias": "data", "value": { "data": "$convert_start.data", "kind": "ref" } }, { "alias": "encoding", "value": { "data": "HEX", "kind": "string" } } ], "name": "MD5 Hash", "version": "0.1.0" } ] }, "id": "1b185861-258c-48a6-8450-a73d0eae9ad5", "kind": "convert", "name": "MD5 Hash" } ``` --- --- url: /app/tutorials/modifying_apk.md description: >- Learn how to modify Android APK files to bypass certificate pinning and enable HTTPS traffic interception through Caido. --- # Modifying an Android Application: Virtual & Physical Devices ::: warning NOTE This tutorial is a continuation of the previous tutorials. Ensure your environment and virtual/physical device is prepared before continuing. ::: To proceed with this tutorial, you will need to download/install the **SSL Pinning Demo** application. ## SSL Pinning Demo The [SSL Pinning Demo](https://github.com/httptoolkit/android-ssl-pinning-demo) is an Android application developed by [HTTPToolkit](https://httptoolkit.tech/) for security education. It blocks HTTPS traffic from being proxied or intercepted via certificate pinning and a security configuration file. The application provides an array of buttons that issue requests under various secure and insecure configurations. Unpacking and modifying the **Android Package Kit** (APK) file bundle that comprises the application demonstrates how these protective measures can be bypassed. If an application's traffic is still not proxied through Caido or you encounter errors or limited functionality, similar protective measures likely exist in its code or configuration. ::: warning NOTE This tutorial was written using: * SSL Pinning Demo v1.4.1. To download this release visit: We recommend using the same version to ensure the instructions align. ::: ::: info * **This process does NOT require a rooted device.** * Be aware that the exact names and locations of setting options may vary between devices. * Ensure to pay attention to any prompts on the device itself while proceeding through these steps. * For physical devices, ensure the device is connected to the computer running Caido via USB and that both the device and the computer are on the same Wi-Fi network. ::: Once the `SSL Pinning Demo v1.4.1` APK has been downloaded to your computer, to install it on your device: 1. Execute the `adb` tool with `devices` to ensure the device is listed. ```bash adb devices ``` 2. Navigate to the file system location of the APK file. 3. Execute the `adb` tool with the device ID as the value of the `-s` argument and the file system location of the `pinning-demo.apk` as the value of the `install` argument to install the application. ```bash adb -s install pinning-demo.apk ``` ## Extracting an APK Once the `SSL Pinning Demo v1.4.1` application has been installed on your device, to simulate extracting the APK from the installation: 1. Execute the `adb` tool against the device with `shell` to initialize a terminal. ```bash adb -s shell ``` 2. Find the application's `base.apk` package on your device by listing all the file paths of installed packages and filtering the results by the application name. ```bash pm list packages -f | grep -i pinning ``` 3. Copy the absolute file path (*starting from `/data` and ending with `/base.apk`*) and exit the device command-line interface using `CTRL` + `D` or by typing and entering `exit`. 4. Execute the `adb` tool against the device with the file path as the value of the `pull` argument to pull the APK to your computer. ```bash adb -s pull /base.apk> ``` ### Unpacking APKs Once you have an application's APK, to decompile the package into its individual resources: 1. Download and install [Apktool](https://apktool.org/docs/install/) for your operating system. 2. Open a terminal and navigate to the file system location of the APK file. 3. Execute `apktool` with `d` and the output directory (*e.g. `unpacked`*) as the value of the `-o` argument against the APK file (*e.g. `base.apk`*) to unpack the contents to the specified directory. ```bash apktool d -o unpacked base.apk ``` ## Modifying the Network Security Configuration File Application traffic may be blocked from interception/proxying due to the presence of a [Network Security Configuration](https://developer.android.com/privacy-and-security/security-config) file. Introduced in Android 7.0 (*API level 24*), the `network_security_config.xml` file allows developers to customize network security settings for their applications. In some cases, modifying this file and including the `` directive to trust user-supplied certificates may be sufficient enough to configure the application to be Caido compatible. To make the appropriate changes: 1. Open the `/res/xml/network_security_config.xml` file from the unpacked directory in an editor (*or, if it doesn't exist, create it*). 2. Replace/write the content of the file to: ```xml ``` 3. Save the changes to `/res/xml/network_security_config.xml`. 4. Ensure that the main configuration file, `AndroidManifest.xml` references the `network_security_config.xml` file via the `android:networkSecurityConfig="@xml/network_security_config"` attribute in the `` tag (*if you created a new `network_security_config.xml` file, you will have to explicitly add this*). 5. Save any changes to `AndroidManifest.xml`. 6. From the root directory of the unpacked APK, execute `apktool` with `b` and the output filename (*e.g. `modified.apk`*) as the value of the `-o` argument to repack the contents into an APK. ```bash apktool b -o modified.apk ./ ``` 7. Download and install [Java Development Kit (JDK)](https://docs.oracle.com/en/java/javase/23/install/overview-jdk-installation.html) for your operating system and add the `/bin` directory to your system's PATH environment variable. 8. Open a new terminal and navigate to the file system location of the repacked APK file. 9. Execute `keytool` to generate a signing key with a keystore filename as the value of the `-keystore` argument (*e.g. `custom.keystore`*). ```bash keytool -genkey -v -keystore custom.keystore -alias aliasname -keyalg RSA -keysize 2048 -validity 10000 ``` 10. Follow the prompts to configure the key. 11. Add the `build-tools\` directory (*a subdirectory of the file system location stated in the `Android SDK Location` field*) to your system's PATH environment variable. 12. Open a new terminal and navigate to the file system location of the repacked APK file. 13. Execute `zipalign` with `-p 4` against the repacked APK filename (*e.g. `modified.apk`*) and specify a new APK filename for the aligned file (*e.g. `aligned.apk`*). ```bash zipalign -p 4 modified.apk aligned.apk ``` 14. Sign the APK. ```bash apksigner sign --ks custom.keystore aligned.apk ``` 15. Execute the `adb` tool against the device with `uninstall tech.httptoolkit.pinning_demo` to uninstall the existing installation. ```bash adb -s uninstall tech.httptoolkit.pinning_demo ``` 16. Install the modified application on the device. ```bash adb -s install aligned.apk ``` Open the SSL Pinning Demo application on your device. Modifying the `network_security_config.xml` file allows for the following requests (*highlighted in green*): You will now see traffic generated by the application in Caido's **HTTP History** traffic table. As you can see, certain requests still result in an error message and are not proxied through Caido. This is due to certificate pinning within the application code. ## Frida **Frida** is a toolkit that allows you to hook custom scripts into running Android application processes, enabling real-time analysis and modification. This can be used to modify the processes that are checking the SSL/TLS certificates. ::: warning NOTE This tutorial was written using: * **Frida** v16.6.6 * **Frida Tools** v13.6.0 We recommend using the same versions to ensure the instructions align. ::: To bypass the additional certificate pinning protections: 1. Download and install the Frida CLI tools (Frida and Frida Tools): ```bash pip install frida==16.6.6 frida-tools==13.6.0 ``` 2. Add the `/scripts` directory of the package to your system's PATH environment variable. 3. Open a new terminal and navigate to the file system location of the unpacked APK directory. ### Frida Gadget Since certain Frida operations may not work with unrooted devices, you will also need the **Frida Gadget** library. Once the library is injected into the APK, commands can be executed using the CLI tools. ::: warning NOTE This tutorial was written using: * **Frida Gadget** v16.6.6 We recommend using the same versions to ensure the instructions align. ::: To check which download you will need for your device's architecture: 1. Execute the `adb` tool against the device with `shell getprop ro.product.cpu.abi` to get the device's CPU ABI. ```bash adb -s shell getprop ro.product.cpu.abi ``` 2. Download the latest appropriate `frida-gadget-16.6.6-android-.so.xz` package: * For `armeabi-v7a` or `armeabi`: [android-arm.so.xz](https://github.com/frida/frida/releases/download/16.6.6/frida-gadget-16.6.6-android-arm.so.xz) * For `arm64-v8a`: [android-arm64.so.xz](https://github.com/frida/frida/releases/download/16.6.6/frida-gadget-16.6.6-android-arm64.so.xz) * For `x86`: [android-x86.so.xz](https://github.com/frida/frida/releases/download/16.6.6/frida-gadget-16.6.6-android-x86.so.xz) * For `x86_64`: [android-x86\_64.so.xz](https://github.com/frida/frida/releases/download/16.6.6/frida-gadget-16.6.6-android-x86_64.so.xz) Once downloaded, extract the library folder to your working directory and rename the `.so` file to: ```text libfrida-gadget.so ``` ## Bypassing Hardcoded Certificate Pinning To bypass hardcoded certificate pinning protections, you will need to insert the Frida Gadget library into the main activity stated in the `AndroidManifest.xml` configuration file: ::: info In Android development, an "activity" is the term used to refer to a specific page/screen of the application. ::: 1. Open the `AndroidManifest.xml` file of the unpacked APK in a text editor. ```xml ``` 2. Change the value of the `android:extractNativeLibs` attribute from `"false"` to `"true"`. 3. Save the changes to the `AndroidManifest.xml` file. ```xml android:extractNativeLibs="true" ``` 4. Next, search for the `activity` tag for the value of the `android:name` attribute which stores the full name of the package that serves the main activity of the application upon launch. ```xml ``` ::: info The packages can be recognized by their ending syntax of `Activity` (*e.g. `MainActivity`, `SplashActivity`, `WindowActivity`, `LauncherActivity`, etc.*). ::: 5. Recursively search through the unpacked APK for the `MainActivity`'s `.smali` file. 6. Open the `smali/tech/httptoolkit/pinning_demo/MainActivity.smali` file and locate the `.method public constructor ()V` initialization function (*lines 74-81*). ```smali .method public constructor ()V .locals 0 .line 51 invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;->()V return-void .end method ``` 7. Modify this method to include the Frida Gadget script and increment the value of its `.locals` property to account for the change. ```smali .method public constructor ()V .locals 1 const-string v0, "frida-gadget" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V .line 51 invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;->()V return-void .end method ``` 8. Save the changes to `smali/tech/httptoolkit/pinning_demo/MainActivity.smali`. 9. Next, create a `lib` directory in the root of the unpacked APK folder, an architecture specific subdirectory, and move the `libfrida-gadget.so` file into it (*example: `/unpacked/lib/x86/libfrida-gadget.so`*). 10. Execute `apktool` with `b` and the output filename (*e.g. `frida-app.apk`*) as the value of the `-o` argument against the unpacked APK directory to repack the contents. ```bash apktool b -o frida-app.apk ./ ``` *** 11. Align the file (*e.g. `frida-aligned.apk`*). ```bash zipalign -p 4 frida-app.apk frida-aligned.apk ``` *** 12. Sign the APK. ```bash apksigner sign --ks custom.keystore frida-aligned.apk ``` 13. Uninstall the original application from the device. ```bash adb -s uninstall tech.httptoolkit.pinning_demo ``` 14. Install the modified APK. ```bash adb -s install frida-aligned.apk ``` ## Frida CodeShare [Frida Codeshare](https://codeshare.frida.re/browse) is Frida's official repository of scripts for bypassing the protective measures of various HTTP libraries utilized by Android applications. To utilize a script from the repository: 1. Open the SSL Pinning Demo application on your device. The screen will be blank as it is awaiting the script that will hook into the application's initialization. 2. Execute `frida` against the device with `-U gadget` and the script `/` (*e.g. `fdciabdul/frida-multiple-bypass`*) as the value of the `--codeshare` argument. ```bash frida -U gadget --codeshare fdciabdul/frida-multiple-bypass ``` Depending on the script used, you will now be able to make additional requests that previously failed. ::: danger WARNING When sourcing files online, ensure to evaluate the code for any malicious operations before executing it. ::: ::: tip To specify a local script, use the filename as the value of the `-l` argument. ```bash ./frida -U gadget -l ``` ::: --- --- url: /app/guides/match_replace_websocket.md description: >- A step-by-step guide to modifying WebSocket messages in Caido using the Match & Replace feature. --- # Modifying WebSocket Messages To modify an outgoing or incoming WebSocket message, **click** on the `Section` drop-down menu and select either `Request Websocket` or `Response Websocket`. Next, select an option from the `Matcher` drop-down menu to specify what data to modify: * `Full`: The entire message. * `Regex`: Matches a value determined by a regular expression. * `String`: Matches a string value. Then, specify the replacement value in the `Replacer` input field. Select the traffic source/s and click on the `+ Add` button to add the rule to the Default Collection. ::: tip Give rules descriptive names for quick identification of their purpose. ::: To enable the rule, **click** on its associated checkbox. Applied rules will be listed in the `Active Rules` table. To view the modified message, within the [WS History](/app/quickstart/ws_history.md) interface **click** on the `Original` button above a message and select `Tamper`. --- --- url: /app/guides/navigation.md description: >- A step-by-step guide to navigating Caido's user interface including the navigation menu, feature interfaces, and sidebar visibility controls. --- # Navigating Caido On the left-hand side of the Caido user-interface is a navigation menu that contains the different feature interfaces, grouped by category. **Clicking** on a listed feature will present its own page. ## Toggling Navigation Menu Visibility To hide the navigation menu, **click** on the Collapse Sidebar button. To view the navigation menu, **click** on the button. --- --- url: /dashboard/guides/receipts.md description: A guide to viewing and downloading receipts in the Caido Dashboard. --- # Obtaining Receipts Before your subscription is renewed, you will receive an email from **Caido Labs Inc. (via Paddle.com)** notifying you of the upcoming transaction. To obtain receipts of your subscription payments, visit , authenticate with your account, and visit the [Billing](https://dashboard.caido.io/receipts) page. In the **Transactions** table, the **Receipt** column will contain a link to the receipt for the transaction. Receipts can also be obtained from the Paddle customer portal which can be accessed by clicking on either the `Update billing information` or `Cancel subscription` buttons in the [Billing](https://dashboard.caido.io/receipts) page. ::: warning NOTE Close the panel opened in the customer portal to avoid subscription interruptions. ::: ::: info Purchase orders and bank payments are available on the Enterprise tier. ::: --- --- url: /app/tutorials/headless_orchestration.md description: >- Learn how to orchestrate headless Caido instances and automate instance configuration via scripting --- # Orchestrating Caido Headless The goal of this tutorial is to automate headless Caido instances through scripting to ensure they are safely registered and configured without human intervention. This allows many use cases like: * **Red boxes**: Pre-configure isolated instances for triaging/pentest/etc * **CI/CD testing**: Automatically set up instances to run particular tests on-demand * **AI agent interfaces**: Provide human-in-the-loop interfaces to AI agents ## 1. Creating a Registration Key and Launching the Instance To safely deploy Caido instances without human intervention, you'll need to use a [Registration Key](/dashboard/concepts/registration_key). Registration keys automatically claim new instances, ensuring they're secure even when deployed in automated environments. If you are not on a Team plan, you will need to do this registration step manually. ### Creating a Registration Key First, create a registration key in the [Caido Dashboard](https://dashboard.caido.io): 1. Navigate to your Team workspace 2. Go to the Registration Keys section 3. Click `Create Key` 4. Configure the key: * **Description**: `Headless Tutorial` * **Prefix**: `headless` * **Expiration**: Set an expiration date * **Reusable**: Yes For detailed instructions, see our guide on [creating a registration key](/dashboard/guides/create_registration_key). ### Downloading the Caido CLI To download the latest [Caido CLI](/app/concepts/cli_vs_desktop) version automatically, you can use our [release API](/app/reference/download_links). ```bash curl -s https://caido.download/releases/latest ``` You can filter with JQ for your specific platform (here `Linux x86_64`): ```bash curl -s https://caido.download/releases/latest | jq -r '.links[] | select(.os=="linux" and .arch=="x86_64" and .kind=="cli") | .link' ``` ::: info The binary is always packaged in an archive (zip or tar.gz), make sure to unarchive it before the next step! ::: ### Launching the Instance with a Registration Key Once you have a registration key and the binary, launch your Caido instance. You can pass the registration key in two ways: **Option 1: Using the `--registration-key` flag:** ```bash caido --registration-key ckey_xxxxx ``` **Option 2: Using the `CAIDO_REGISTRATION_KEY` environment variable:** ```bash export CAIDO_REGISTRATION_KEY=ckey_xxxxx caido ``` When the instance starts, it will automatically register itself and be automatically claimed by the Team. This ensures the instance is secure. ::: info For more information about the registration process, see our documentation on [instance registration](/app/concepts/instance_registration). ::: ::: warning If you want to expose the instance to the internet, make sure to read our [tutorial](./instance_internet.md) on the subject to do so securely. ::: ## 2. Creating a PAT and Setting Environment Variable To authenticate your scripts with the Caido instance, you'll need a [Personal Access Token (PAT)](/dashboard/concepts/pat). PATs allow headless authentication without requiring browser interaction. ### Creating a PAT 1. Visit the [Caido Dashboard](https://dashboard.caido.io) 2. Navigate to the Developer page **in your Workspace** 3. Click `+ Create Token` 4. Configure the token: * **Name**: `Headless automation` * **Resource Owner**: Select your Team * **Expiration**: Set an expiration date For detailed instructions, see our guide on [creating a PAT](/dashboard/guides/create_pat). ### Setting the Environment Variable Once you have your PAT, set it as an environment variable: ```bash export CAIDO_PAT=caido_xxxxx ``` You can also set the Caido instance URL (if different from the default): ```bash export CAIDO_INSTANCE_URL=http://abc.remote.cai.do:9000 ``` ::: info For more information about authentication, see our documentation on [instance authentication](/app/concepts/instance_authentication). ::: ## 3. Creating the Configuration Script Now we'll create a script that uses the `@caido/sdk-client` to automatically configure your Caido instance. This script will: 1. Create and select a project 2. Create a scope preset 3. Create a filter preset 4. Create an environment with environment variables 5. Upload a hosted file (wordlist) ### Setting Up the Project First, create a new directory for your script and initialize it: ```bash mkdir caido-automation cd caido-automation pnpm init ``` Install the Caido SDK client: ```bash pnpm install @caido/sdk-client ``` ::: info Not all versions of the sdk-client are compatible with the targeted Caido instances. If you see errors, make sure to update your sdk-client version. ::: ### The Configuration Script Create a file named `configure.ts`: ```typescript import { Client } from "@caido/sdk-client"; async function main() { // Get the Caido instance URL from environment or use default const instanceUrl = process.env["CAIDO_INSTANCE_URL"] ?? "http://localhost:8082"; // Get the Personal Access Token from environment const pat = process.env["CAIDO_PAT"]; if (pat === undefined || pat === "") { console.error("❌ Error: CAIDO_PAT environment variable is required"); console.error(" Set it with: export CAIDO_PAT=caido_xxxxx"); process.exit(1); } const client = new Client({ url: instanceUrl, auth: { pat: pat, cache: { file: ".secrets.json", // This caches the access token on disk to speed up other scripts, can be removed }, }, }); await client.connect(); console.log("✅ Connected to Caido instance"); // Verify authentication const viewer = await client.user.viewer(); console.log( `✅ Authenticated as: ${ viewer.kind === "CloudUser" ? viewer.profile.identity.email : viewer.id }`, ); // 1. Create and select a project console.log("\n📁 Creating project..."); const project = await client.project.create({ name: "Automated Pentest Environment", temporary: false, }); console.log(`✅ Created project: ${project.name} (${project.id})`); await client.project.select(project.id); console.log(`✅ Selected project: ${project.name}`); // 2. Create a scope preset console.log("\n🎯 Creating scope preset..."); const scope = await client.scope.create({ name: "Main Scope", allowlist: ["*.example.com", "*.test.example.com"], denylist: ["*.admin.example.com"], }); console.log(`✅ Created scope: ${scope.name} (${scope.id})`); console.log(` In-scope: ${scope.allowlist.join(", ")}`); console.log(` Out-of-scope: ${scope.denylist.join(", ")}`); // 3. Create a filter preset console.log("\n🔍 Creating filter preset..."); const filter = await client.filter.create({ name: "API Requests Only", alias: "api_only", clause: 'req.method.eq:"GET" or req.method.eq:"POST"', }); console.log(`✅ Created filter preset: ${filter.name} (${filter.alias})`); // 4. Create an environment with environment variables console.log("\n🌍 Creating environment..."); const environment = await client.environment.create({ name: "Production Environment", variables: [ { name: "API_BASE_URL", value: "https://api.example.com", kind: "PLAIN", }, { name: "API_KEY", value: "secret-api-key-12345", kind: "SECRET", }, ], }); console.log( `✅ Created environment: ${environment.name} (${environment.id})`, ); console.log( ` Variables: ${environment.variables.map((v) => v.name).join(", ")}`, ); // Add more variables to the environment await environment.addVariable({ name: "SESSION_TOKEN", value: "initial-token-value", kind: "PLAIN", }); console.log(`✅ Added variable: SESSION_TOKEN`); // Select the environment await client.environment.select(environment.id); console.log(`✅ Selected environment: ${environment.name}`); // 5. Upload a hosted file (wordlist) console.log("\n📄 Uploading hosted file..."); // Create a sample wordlist file // In Node.js 18+, File is available globally // For older versions, you can use: import { File } from "node-fetch" or similar const wordlistContent = `admin administrator api backup config database dev login password test user `; // Create a File object from the content // Note: File API is available in Node.js 18+; for older versions, use a polyfill const wordlistFile = new File([wordlistContent], "common-wordlist.txt", { type: "text/plain", }); // Alternatively, read from an existing file (uncomment readFileSync import above): // const fileBuffer = readFileSync("path/to/wordlist.txt"); // const wordlistFile = new File([fileBuffer], "wordlist.txt", { type: "text/plain" }); const hostedFile = await client.hostedFile.upload({ name: "Common Wordlist", file: wordlistFile, }); console.log(`✅ Uploaded hosted file: ${hostedFile.name} (${hostedFile.id})`); console.log(` Size: ${hostedFile.size} bytes`); console.log(` Status: ${hostedFile.status}`); console.log("\n✨ Configuration complete!"); console.log(`\nProject ID: ${project.id}`); console.log(`Scope ID: ${scope.id}`); console.log(`Filter ID: ${filter.id}`); console.log(`Environment ID: ${environment.id}`); console.log(`Hosted File ID: ${hostedFile.id}`); } main().catch((error: unknown) => { console.error("❌ Fatal error:", error); process.exit(1); }); ``` ### Running the Script Make sure your environment variables are set. Add the following start command to your `package.json`: ```json "scripts": { "start": "node configure.ts" } ``` Then simply run: ```bash pnpm start ``` ::: info Modern versions of Node.js can now run TypeScript directly. No compilation step is needed! If you see some errors, make sure your Node.js version is up to date. ::: ### Script Breakdown The script performs the following operations: 1. **Project Creation**: Creates a new project named "Automated Pentest Environment" and selects it as the active project. Projects are containers for all your testing data. 2. **Scope Preset Creation**: Creates a scope preset that defines which targets are in-scope and out-of-scope. For more details, see our guide on [defining a scope](/app/guides/scopes_defining). 3. **Filter Preset Creation**: Creates a filter preset using HTTPQL to filter traffic. For more information, see our guide on [defining a filter](/app/guides/filters_defining) and the [HTTPQL reference](/app/reference/httpql). 4. **Environment Creation**: Creates a custom environment with environment variables. Environment variables can be used in requests and workflows. The script creates both plain and secret variables. For more details, see our guide on [creating environment variables](/app/guides/environment_variables). 5. **Hosted File Upload**: Uploads a wordlist file that can be used in Automate sessions for systematic payload testing. For more information, see our guides on [uploading files](/app/guides/files_uploading) and [using wordlists in Automate](/app/guides/automate_wordlists). ## Next Steps Your instance is now configured, you can start using it directly as an operator or via further scripting. You can also check out our tutorial on [GitHub Actions](./github_action.md). --- --- url: /app/guides/workflows_references.md description: >- A step-by-step guide to passing data between workflow nodes in Caido using references and data aliases for complex automation sequences. --- # Passing Data Between Nodes To use the output of a workflow node as the input of a connected downstream node, **click** on the button in a node's editor and select the data alias from the drop-down menu: ::: tip View the [Workflow Node Data Types](/app/reference/workflow_data_types.md) reference to learn which input and output types are exact matches, compatible, and incompatible with one another. ::: --- --- url: /app/concepts/pat.md description: >- Understand what Personal Access Tokens (PATs) are, how they work in Caido, and when to use them for headless and automated workflows. --- # Personal Access Token A Personal Access Token (PAT) is a long-lived credential that allows you to authenticate with a Caido instance without going through the browser-based consent flow described in [Authentication](./instance_authentication.md). This makes PATs the primary authentication method for headless environments, CI/CD pipelines, and any automated interaction with the [Caido Cloud API](https://developer.caido.io/client-sdk/reference/api.html). All Caido PATs use the `caido_` prefix, making them easy to identify and manage across your systems. ::: info Each PAT is tied to the user who created it and acts with the same level of permissions as that user. ::: ## How It Works When you log into a Caido instance through the browser or desktop application, a Device Authorization flow takes place. You are redirected to the [Dashboard](https://dashboard.caido.io) to manually approve a consent form. A PAT replaces that manual approval step, making the entire authentication process automated. 1. The **Script** sends a login request to the **Caido** instance. 2. The instance initiates a Device Authorization **Flow** with the **Cloud**. 3. The Script presents the **PAT** to the Cloud, which validates it and automatically approves the authorization. 4. The Cloud returns **Tokens** (an access token and a refresh token) to the instance. 5. The instance passes the **Tokens** back to the Script. From this point forward, the session behaves identically to a browser-based login. The access token authenticates subsequent API calls and the refresh token is used to renew it when it expires. ## Resource Ownership A PAT can be created to access resources under your own account or under a specific Team. When you [create a PAT](/dashboard/guides/create_pat) for a Team, it operates within that Team's [Workspace](/dashboard/concepts/workspace) and can access the Team's instances, members, and subscription resources. A PAT created for yourself can only access your personal resources. ::: info Team admins can view PATs created for their Team, but only the creator of a PAT can revoke it. ::: ## Security Considerations * **Always set an expiration date** when [creating a PAT](/dashboard/guides/create_pat). Open-ended tokens increase your risk exposure if they are leaked. * **Treat PATs like passwords.** Store them in environment variables or a secret management system. Never commit them to source code. * **Revoke PATs you no longer need.** You can manage your tokens from the [Developer section](https://dashboard.caido.io/developer) of the Dashboard. --- --- url: /dashboard/concepts/pat.md --- # Personal Access Token Personal Access Tokens (PAT) are used to access the public [API of Caido Cloud](https://developer.caido.io/client-sdk/reference/api.html). For example, they can be used to invite new members to a Team or approve an headless login to a Caido instance. You can easily recognize a Caido PAT as they start with `caido_`. ::: info Each PAT is tied to a user and will act with the same level of permissions as that user. ::: A PAT can either be created to access resources for your own account or a specific Team (the resource owner). ::: info PATs created for a Team will be visible by the admins of that Team, but they won't be able to revoke them. ::: To get started with PAT, [learn how to create one](/dashboard/guides/create_pat). --- --- url: /app/quickstart/plugins.md description: >- A step-by-step guide to Caido's Plugins interface for installing and managing extension packages to customize functionality. --- # Plugins The `Plugins` interface allows you to install and manage plugin packages in Caido. These packages extend Caido's functionality, offering a high degree of customization. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Installing Plugins](/app/guides/plugins_installing.md) * [Enabling/Disabling Plugins](/app/guides/plugins_managing.md) ::: ::: warning STEP-BY-STEP TUTORIALS * [Autorize](/app/tutorials/autorize.md) * [Scanner](/app/tutorials/scanner.md) * [Shift](/app/tutorials/shift.md) ::: --- --- url: /app/guides/automate_preprocessors.md description: >- A step-by-step guide to preprocessing payloads in Caido's Automate feature using workflows, URL encoding, prefixes, suffixes, and custom transformations. --- # Preprocessing Payloads Additional modifications can be made to payload values before they are included in Automate session requests from the `Preprocessors` tab. *** ## Applying a Workflow With `Workflow` selected from the Preprocessor type drop-down menu, you can expand the `Select a workflow` drop-down menu and select a workflow to apply to a payload. Once a workflow has been selected, **click** on the `Add` button to apply the Preprocessor. ## URL Encoding To ensure payloads are interpreted as intended, you can URL-encode their values by selecting `URL Encode` from the Preprocessor type drop-down menu. This option will present a `Charset` input field that specifies which characters will be encoded. To add to this list, **click** inside the input field and type in any additional characters. By default, `Encode non-ASCII characters` is enabled. To disable this feature, **click** on its checkbox to remove its fill. To apply the URL Encode Preprocessor **click** on the `Add` button. ## Adding a Prefix or Suffix By selecting either `Prefix` or `Suffix` from the Preprocessor type drop-down menu, you can add a prefix or a suffix to payload values. Each option will present an input field for typing the attached value. *** ## Ordering Any added Preprocessors are displayed in the `Active preprocessors` list and are applied to payloads in ascending order. To reorder their application, **click** on a Preprocessor from the list and use the and buttons. ::: info If `Close Connection` is disabled in the `Settings` tab, the TCP connection is maintained through the session until it is terminated by the server. ::: --- --- url: /app/guides/preview_responses.md description: >- A step-by-step guide to previewing HTTP responses in Caido using the rendering engine to view content as it would appear in a browser window. --- # Previewing Responses You can preview responses directly within HTTP response panes just as they would appear in your browser window. To make use of this feature, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `Rendering` tab. Then, **click** on the `Install now` button to install the required rendering engine. Once the rendering engine is installed, you can **click** on the `Preview` or page button attached to a response pane to render the view. --- --- url: /burp-suite/core/project-and-configuration.md description: Map Burp Suite Pro project files and configuration to Caido. --- # Project & Configuration Burp Suite Pro project files, session handling, and configuration features and their Caido equivalents. ## Available ### Project Files Burp saves and restores project state including traffic, site map, and configuration. Caido offers native **Workspaces** to manage projects and persist traffic, scope, and configuration within an instance. Caido also exports traffic separately through **Exports** when you need portable data outside the workspace. #### Resources * [Workspace](/app/quickstart/workspace.md) * [Exports](/app/quickstart/exports.md) * [Recovering Projects](/app/guides/projects_recovering.md) * [Project Backups](/app/guides/projects_backups.md) ## Indirectly Available ### Session Handling Rules Burp automatically modifies requests based on session state using macros and rules. Caido has no native session handling rule engine like Burp. Caido supports session and identity switching through **Environment Variables** (store tokens and credentials per context), **Workflows** (inject or refresh values on traffic), and **Match & Replace** rules (swap headers or cookies when rules are enabled). The **Authswap** community plugin adds quick switching between authentication contexts during manual testing. This covers many Burp session workflows but requires explicit setup rather than Burp's integrated macros and rules. #### Resources * [Environment Variables](/app/quickstart/environment.md) * [Workflows](/app/quickstart/workflows.md) * [Match & Replace](/app/quickstart/match_replace.md) * [Refresh Authentication Tutorial](/app/tutorials/refresh_authentication.md) * [Authswap](https://github.com/caido-community/authswap) (GitHub) ### Macros Burp records sequences of requests and replays them to maintain session state. Caido offers **Workflows** as the equivalent for defining sequences of actions—such as sending requests, transforming traffic, or chaining steps based on responses. You build workflows in the editor rather than recording a macro, but they cover the same multi-step automation use cases as Burp macros. #### Resources * [Workflows](/app/quickstart/workflows.md) * [Creating Workflows](/app/guides/workflows_creating.md) * [Refresh Authentication Tutorial](/app/tutorials/refresh_authentication.md) ### Configuration Library Burp exports specific settings as shareable configuration files and saves configuration profiles for reuse across projects. Caido has no unified configuration library like Burp. Instead, many feature pages offer their own export so you can save settings to disk, version-control them, and import them into new projects—workflows, filters, scopes, match-and-replace rules, and environment variables, each from its own interface. Some objects, such as **global workflows**, are available across all projects in an instance by default; switch a workflow to project-specific scope when you want it limited to one workspace. #### Resources * [Workflows](/app/quickstart/workflows.md) * [Creating Workflows](/app/guides/workflows_creating.md) * [Filters](/app/quickstart/filters.md) * [Scopes](/app/quickstart/scopes.md) * [Match & Replace](/app/quickstart/match_replace.md) * [Environment Variables](/app/quickstart/environment.md) * [Workspace](/app/quickstart/workspace.md) --- --- url: /app/guides/assistant_explain.md description: >- A step-by-step guide to using Caido's AI Assistant to explain HTTP requests in natural language and identify potential attack vectors. --- # Prompting the Assistant to Explain Requests ::: warning Submitted data is sent to the LLM's third-party provider (OpenAI) and can be stored for up to 30 days. Due to this, **anonymize sensitive data** when using the Assistant. Sensitive data may be unintentionally submitted when using the Assistant context menu options. Before using any context menu option, manually review all content to ensure no sensitive data is included. For more information, review: * [OpenAI's Privacy Policy](https://openai.com/policies/privacy-policy) * [Caido's Privacy Policy](https://www.caido.io/privacy) ::: To prompt the Assistant to explain a HTTP request in natural language, **right-click** within a request pane to open the context menu, hover your mouse cursor over Assistant, and select `Explain`. Or, submit a prompt directly in the `Send a message` input field along with the request: ```txt Explain the operation being performed by the endpoint in this request: POST /change/email HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br, zstd DNT: 1 Connection: keep-alive Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: none Sec-Fetch-User: ?1 Priority: u=0, i Pragma: no-cache Cache-Control: no-cache Cookie: session_id=123ABC321XYZ Content-Type: application/x-www-form-urlencoded Content-Length: 23 email=attacker@caido.io ``` ::: tip Once the Assistant has the context of a request, you can ask for possible attack vectors. ::: --- --- url: /app/tutorials/android_browser_physical.md description: >- Learn how to configure and add Caido's CA certificate to the user-store of a physical Android device. --- # Proxying Browser Traffic ::: warning NOTE This tutorial is a continuation of [Setup & Configuration](/app/tutorials/android_physical_device.md). Ensure you have completed the previous steps before proceeding. ::: ::: info * Be aware that the exact names and locations of setting options may vary between devices. * Ensure to pay attention to any prompts on the device itself while proceeding through these steps. * Ensure the device is connected to the computer running Caido via USB and that both the device and the computer are on the same Wi-Fi network. ::: To proxy HTTP/HTTPS traffic generated by the Chrome application (*the default mobile browser installed on Android devices*): 1. Navigate to the device's settings and enable [`Developer options`](https://developer.android.com/studio/debug/dev-options#enable) and `USB debugging`. 2) In the **Projects** interface of the Android Studio window, **click** on the More Actions button and select `SDK Manager`. 3. Select `Android SDK` from the **Languages & Frameworks** drop-down menu. 4. Add the `platform-tools` directory (*a subdirectory of the file system location stated in the `Android SDK Location` field*) to your system's PATH environment variable. 5) Connect your Android device to your computer via USB. 6) Open a terminal and execute the `adb` tool with `devices` to ensure the device is listed. ```bash adb devices ``` 7. Execute the `adb` tool with the device ID as the value of the `-s` argument and `reverse tcp:8080 tcp:8080` to forward traffic to Caido. ```bash adb -s reverse tcp:8080 tcp:8080 ``` 8. On the device, navigate to the **Settings** interface and select `Network & internet`. 9. **Click** on the `Wi-Fi` settings. 10. **Click** on the button of your Wi-Fi SSID. 11. **Click** on the button and expand the `Advanced options` drop-down menu. 12. **Click** on the drop-down menu under **Proxy** and select `Manual`. 13. Set the **Proxy hostname** to `127.0.0.1`, the **Proxy port** to `8080`, and **click** `Save`. 14) With Caido running, navigate to `http://127.0.0.1:8080/ca.crt` in your device's browser. 15) **Click** on `Download` to download Caido's CA certificate. 16) **Click** on `Close` in the notification window and navigate to the **Settings** interface. 17) In the Search settings input field, search for and select `Install a certificate`. 18) **Click** on `Install a certificate` and select `CA certificate`. 19) In the security notification screen **click** on `Install anyway` and select Caido's `ca.crt` file. ::: tip To verify the addition of the certificate: 1. On the device, navigate to the **Settings** interface. 2. In the Search settings input field, search for and select `Trusted credentials`. 3. **Click** on `Trusted credentials` and locate `Caido` in the **User** tab certificate list. ::: Once the certificate has been installed, navigate to any domain using either the `http://` or `https://` scheme and view the **HTTP History** traffic table in Caido to inspect the traffic. ::: warning NOTE If traffic is not appearing in the **HTTP History** table in Caido, try: * Disabling `Mobile data` usage. * Disabling any VPN connections. * Setting the Wi-Fi **Proxy hostname** to `10.0.2.2`. ::: --- --- url: /app/tutorials/android_browser_virtual.md description: >- Learn how to configure and add Caido's CA certificate to the user-store of a virtual Android device. --- # Proxying Browser Traffic ::: warning NOTE This tutorial is a continuation of [Setup & Configuration](/app/tutorials/android_virtual_device.md). Ensure you have completed the previous steps before proceeding. ::: To proxy HTTP/HTTPS traffic generated by the Chrome application (*the default mobile browser installed on Android devices*): 1. Launch the device by clicking on the button of its table row. 2. On the device, navigate to the **Settings** interface and select `Network & internet`. 3. **Click** on the `Wi-Fi` settings. 4. **Click** on the button of the `AndroidWifi` SSID. 5. **Click** on the button and expand the `Advanced options` drop-down menu. 6. **Click** on the drop-down menu under **Proxy** and select `Manual`. 7. Set the **Proxy hostname** to `127.0.0.1`, the **Proxy port** to `8080`, and **click** `Save`. 8) In the **Projects** interface of the Android Studio window, **click** on the More Actions button and select `SDK Manager`. 9. Select `Android SDK` from the **Languages & Frameworks** drop-down menu. 10. Add the `platform-tools` directory (*a subdirectory of the file system location stated in the `Android SDK Location` field*) to your system's PATH environment variable. 11) Open a terminal and execute the `adb` tool with `devices` to ensure the device is listed. ```bash adb devices ``` 12. Execute the `adb` tool with the device ID as the value of the `-s` argument and `reverse tcp:8080 tcp:8080` to forward traffic to Caido. ```bash adb -s reverse tcp:8080 tcp:8080 ``` 13. With Caido running, navigate to `http://127.0.0.1:8080/ca.crt` in your device's browser. 14. **Click** on `Download` to download Caido's CA certificate. 15. **Click** on `Close` in the notification window and navigate to the **Settings** interface. 16. In the Search settings input field, search for and select `Install a certificate`. 17. Select `CA certificate`. 18. In the security notification screen **click** on `Install anyway` and select Caido's `ca.crt` file. ::: tip To verify the addition of the certificate: 1. On the device, navigate to the **Settings** interface. 2. In the Search settings input field, search for and select `Trusted credentials`. 3. **Click** on `Trusted credentials` and locate `Caido` in the **User** tab certificate list. ::: Once the certificate has been installed, navigate to any domain using either the `http://` or `https://` scheme and view the **HTTP History** traffic table in Caido to inspect the traffic. ::: warning NOTE If traffic is not appearing in the **HTTP History** table in Caido, try: * Disabling `Mobile data` usage. * Disabling any VPN connections. * Setting the Wi-Fi **Proxy hostname** to `10.0.2.2`. ::: --- --- url: /app/guides/proxy_local.md description: >- A step-by-step guide to proxying local traffic in Caido using FoxyProxy, Chrome, Firefox, and lvh.me domain to bypass localhost bypass rules. --- # Proxying Local Traffic To proxy local traffic, it is necessary to bypass implicit rules that match against localhost addresses using a method mentioned below. ## FoxyProxy **Click** on the FoxyProxy browser extension, select `Options`, type `<-loopback>` to the `Global Exclude` input field, and **click** on the `Save` button to update and save the configuration. ## ZeroOmega **Click** on the ZeroOmega browser extension, select `Options`, select your proxy profile tab, replace the content of the `Bypass List` input field with `<-loopback>`, and **click** on the Apply changes button to update and save the configuration. ::: info In general, the implicit bypass rules can be modified in the proxy settings of different systems/browsers/extensions by supplying `<-loopback>` to the hosts list. This input field is typically accompanied with a title or description that includes terms or keywords such as: `except these addresses`/`no-proxy for`/`exclude`. ::: ## Chrome Launch Chrome via the terminal with the `--proxy-server=` and `--proxy-bypass-list="<-loopback>"` command-line options. ```bash google-chrome --proxy-server=127.0.0.1:8080` --proxy-bypass-list="<-loopback>" ``` ## Firefox Launch Firefox, navigate to `about:config`, set `network.proxy.allow_hijacking_localhost` to `true`, and restart the browser. ## lvh.me Navigate to . This domain name resolves to 127.0.0.1. --- --- url: /app/concepts/web_traffic.md --- # Proxying Web Traffic Caido is a HTTP proxy server that forwards the bidirectional communication between a client and a destination server. HTTP proxy servers operate in a few distinct ways depending on: * If the client is able to be directly configured to utilize a proxy server or not. * If the traffic is in cleartext (*HTTP*) or encrypted (*HTTPS*). ## Proxy-Aware Clients Clients that can be configured to utilize a HTTP proxy server via native settings, are considered to be "proxy-aware". By manually configuring the connection settings (*or by using a browser extension*), we are able to proxy the traffic the browser generates, intended for a web server, through Caido. Other clients, such as command-line tools allow you to specify the listening address of the proxy server via arguments. For example, by using the `-x` command-line argument and Caido's listening address, `curl` will instruct Caido to make a request to `example.com` on it's behalf. ### HTTP ```bash └─$ curl -x 127.0.0.1:8080 http://example.com -v * Trying 127.0.0.1:8080... * Established connection to 127.0.0.1 (127.0.0.1 port 8080) from 127.0.0.1 port 53219 * using HTTP/1.x > GET http://example.com/ HTTP/1.1 > Host: example.com > User-Agent: curl/8.17.0 > Accept: */* > Proxy-Connection: Keep-Alive > * Request completely sent off < HTTP/1.1 200 OK < Date: Sat, 03 Jan 2026 19:44:03 GMT < Content-Type: text/html < Connection: keep-alive < CF-RAY: 9b84fd17ee220ff9-LAX < Last-Modified: Sat, 03 Jan 2026 05:43:21 GMT < Allow: GET, HEAD < Age: 4371 < cf-cache-status: HIT < Accept-Ranges: bytes < Server: cloudflare < Content-Length: 513 < Example Domain

Example Domain

This domain is for use in documentation examples without needing permission. Avoid use in operations.

Learn more

* Connection #0 to host 127.0.0.1:8080 left intact ``` ### HTTPS If a proxy-aware client would like to establish an encrypted connection with the destination server, the client will first send a `CONNECT` method request to the proxy server that states the destination server to create a tunnel with. ```http CONNECT example.com:443 HTTP/1.1 Host: example.com:443 User-Agent: curl/8.17.0 Proxy-Connection: Keep-Alive ``` Once the tunnel is established, traffic will still pass through the proxy server but it will be obfuscated. However, if the client has imported the CA certificate of the proxy server, it is viewed as a trusted entity. This allows the proxy server to establish TCP/TLS connections with both the client and the destination server, holding the derived symmetric keys for both connections so data can be encrypted and decrypted in both directions. To ensure the the domain name of the client’s request matches the domain name in the certificate, Caido dynamically generates certificates for the destination server. ```bash └─$ curl -x 127.0.0.1:8080 https://example.com -v * Trying 127.0.0.1:8080... * CONNECT: no ALPN negotiated * allocate connect buffer * Establish HTTP proxy tunnel to example.com:443 > CONNECT example.com:443 HTTP/1.1 > Host: example.com:443 > User-Agent: curl/8.17.0 > Proxy-Connection: Keep-Alive > < HTTP/1.1 200 OK < * CONNECT phase completed * CONNECT tunnel established, response 200 * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * SSL Trust Anchors: * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: C=CA; ST=CA; O=Caido; CN=Caido Generated Certificate * start date: Dec 27 19:47:46 2025 GMT * expire date: Jan 10 19:47:46 2026 GMT * issuer: C=CA; ST=QC; O=Caido; CN=Caido * Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using ecdsa-with-SHA256 * Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256 * subjectAltName: "example.com" matches cert's "example.com" * SSL certificate verified via OpenSSL. * Established connection to 127.0.0.1 (127.0.0.1 port 8080) from 127.0.0.1 port 53219 * using HTTP/1.x > GET / HTTP/1.1 > Host: example.com > User-Agent: curl/8.17.0 > Accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * Request completely sent off < HTTP/1.1 200 OK < Date: Sat, 03 Jan 2026 19:47:49 GMT < Content-Type: text/html < Connection: keep-alive < CF-RAY: 9b85029889038a80-LAX < last-modified: Sat, 03 Jan 2026 05:43:21 GMT < allow: GET, HEAD < Age: 2128 < cf-cache-status: HIT < Accept-Ranges: bytes < Server: cloudflare < Content-Length: 513 < Example Domain

Example Domain

This domain is for use in documentation examples without needing permission. Avoid use in operations.

Learn more

* Connection #0 to host 127.0.0.1:8080 left intact ``` ## Thick Clients Certain clients (*such as installed desktop applications*), that cannot be configured to utilize a HTTP proxy server via native settings, are referred to as "thick clients" and are considered to be "proxy-unaware" as they expect to communicate with a destination server directly. Due to this, thick clients will not generate `CONNECT` method requests. However, their traffic can still be proxied by configuring local DNS settings and port forwarding so the listening address of the destination server resolves to the listening address of the proxy server. This technique is known as "invisible proxying". ::: tip View the [Invisible Proxying for Non-Proxy Aware Thick Clients](/app/tutorials/invisible_proxy.md) tutorial for a detailed walk-through on configuring invisible proxying. ::: ### HTTP ```bash └─$ curl http://example.com -v * Host example.com:80 was resolved. * IPv6: (none) * IPv4: 127.0.0.1 * Trying 127.0.0.1:80... * Established connection to example.com (127.0.0.1 port 80) from 127.0.0.1 port 53219 * using HTTP/1.x > GET / HTTP/1.1 > Host: example.com > User-Agent: curl/8.17.0 > Accept: */* > * Request completely sent off < HTTP/1.1 200 OK < Date: Sat, 03 Jan 2026 22:07:17 GMT < Content-Type: text/html < Connection: keep-alive < CF-RAY: 9b85cee559350928-LAX < Last-Modified: Sat, 03 Jan 2026 05:43:21 GMT < Allow: GET, HEAD < Age: 4400 < cf-cache-status: HIT < Accept-Ranges: bytes < Server: cloudflare < Content-Length: 513 < Example Domain

Example Domain

This domain is for use in documentation examples without needing permission. Avoid use in operations.

Learn more

* Connection #0 to host example.com:80 left intact ``` ### HTTPS ```bash └─$ curl https://example.com -v * Host example.com:443 was resolved. * IPv6: (none) * IPv4: 127.0.0.1 * Trying 127.0.0.1:443... * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * SSL Trust Anchors: * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: C=CA; ST=CA; O=Caido; CN=Caido Generated Certificate * start date: Dec 27 22:07:37 2025 GMT * expire date: Jan 10 22:07:37 2026 GMT * issuer: C=CA; ST=QC; O=Caido; CN=Caido * Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using ecdsa-with-SHA256 * Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256 * subjectAltName: "example.com" matches cert's "example.com" * SSL certificate verified via OpenSSL. * Established connection to example.com (127.0.0.1 port 443) from 127.0.0.1 port 53219 * using HTTP/1.x > GET / HTTP/1.1 > Host: example.com > User-Agent: curl/8.17.0 > Accept: */* > * Request completely sent off * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): < HTTP/1.1 200 OK < Date: Sat, 03 Jan 2026 22:07:40 GMT < Content-Type: text/html < Connection: keep-alive < CF-RAY: 9b85cf73098bcd33-LAX < last-modified: Sat, 03 Jan 2026 05:43:21 GMT < allow: GET, HEAD < Age: 2131 < cf-cache-status: HIT < Accept-Ranges: bytes < Server: cloudflare < Content-Length: 513 < Example Domain

Example Domain

This domain is for use in documentation examples without needing permission. Avoid use in operations.

Learn more

* Connection #0 to host example.com:443 left intact ``` --- --- url: /app/guides/wsl.md --- # Proxying WSL Traffic To send traffic generated by WSL to the Caido desktop application running on your Windows host, select Export from the [CA Certificate Management](/app/guides/ca_certificate_managing.html#ca-certificate-management) options. Then, [change the listening address](/app/guides/listening_address.html#desktop-application) of the Caido desktop application to `All interfaces (0.0.0.0)`. Once the address is updated, ensure to close both Caido windows. The next time Caido is launched, you may encounter a Windows Security prompt box. **Click** the `Allow` button to allow incoming connections. To configure the firewall rule manually: 1. Open Windows Defender Firewall. 2. **Click** on "Allow an app or feature through Windows Defender Firewall". 3. **Click** on the Change settings button, **click** on the `caido-cli` checkbox to grant permission, and ensure the `Private` and `Public` checkboxes are selected. 4. Then **click** on `OK` to update and save the configuration. ## WSL In WSL, copy the exported CA certificate from Windows: ```bash cp /mnt/c/Users/ninje/Downloads/ca.crt ~/ca.crt ``` Then, install the `ca.crt` file system-wide and update the certificate store with: ```bash sudo cp ~/ca.crt /usr/local/share/ca-certificates/ca.crt && sudo update-ca-certificates ``` To obtain the gateway IP address of your Windows host that Caido is listening on from WSL's perspective, enter: ```bash ip route show | grep -i default | awk '{ print $3}' ``` To test the network access, launch the Caido desktop application and issue a `curl` request with the `-x ` command-line option: ```bash curl -x 172.22.0.1:8080 https://example.com ``` Once the request is sent, you should see it within in the HTTP History traffic table. ## Proxy Configuration To configure your WSL CLI tools to proxy traffic through Caido, set the `http_proxy` and `https_proxy` environment variables to the listening address/port of the desktop application: ```bash export http_proxy="http://172.22.0.1:8080" && export https_proxy="http://172.22.0.1:8080" ``` ::: tip TIPS * To verify the rules exist, use: `echo $http_proxy && echo $https_proxy` * To remove the rules, use: `unset http_proxy && unset https_proxy` * Consider adding these environment variables to your `~/.bashrc` file to make them permanent with: `echo 'export http_proxy="http://172.22.0.1:8080"' >> ~/.bashrc && echo 'export https_proxy="http://172.22.0.1:8080"' >> ~/.bashrc` * To remove both environment variables, use the following command and then close and reopen WSL: `sed -i '/export.*_proxy=/d' ~/.bashrc` ::: --- --- url: /app/guides/projects_recovering.md description: >- A step-by-step guide to recovering read-only projects in Caido when account types revert to Basic, including project deletion and backup restoration methods. --- # Recovering Read-Only Projects If your account type reverts to Basic, only the first three projects will keep read/write permissions. Any additional projects will become read-only. To restore write permissions on a project, either: ::: tip Deleted projects are unrecoverable unless a [backup file was created](/app/guides/projects_backups.md) prior to the account downgrade. ::: * Delete one of the first three by **clicking** on the `...` button associated with a project row and selecting Delete. * Or [create a backup file of the project](/app/guides/projects_backups.md), create a new Caido instance that [stores data outside of the default location](/app/guides/data_location.md), and [import the project backup file](/app/guides/projects_backups.md) to the instance. --- --- url: /app/reference.md description: >- Find detailed reference information on Caido shortcuts, workflow nodes, HTTPQL, and other features. --- # Reference The Reference section provides precise, factual resources to help you use Caido effectively. It’s designed for quick lookups, offering detailed technical information without explanations or tutorials. Whether you’re troubleshooting errors, exploring HTTPQL fields, or working with workflow nodes, this section serves as a reliable source for exact details. Use this section as your go-to resource for detailed technical information about Caido. --- --- url: /app/tutorials/refresh_jwt.md description: >- Learn how to create a workflow that automatically refreshes a JSON Web Token (JWT) when it expires. --- # Refresh a JWT Workflow In this tutorial, you will learn how to create a workflow to refresh a JSON Web Token (JWT) when it expires. Typically, to continue authenticated testing in [Replay](/app/guides/replay_resending.md), session tokens would need to be manually updated in the request headers. However, this process can be automated by: 1. [Creating environment variables](/app/guides/environment_variables.md) to store the tokens. 2. [Creating a workflow](http://localhost:5173/app/guides/workflows_creating.html) (*specifically a [convert workflow](/app/concepts/workflows_intro.md#convert-workflows)*) that will automatically exchange an expired token for a new one. 3. [Using the workflow in Replay](/app/guides/replay_environment_variables.md) to apply the workflow conversion to the request. ## Example Authentication Flow We will use the API to demonstrate the workflow. According to the documentation, any user credentials returned from the `/users` endpoint can be used to authenticate with the `/auth/login` endpoint. By including the `expiresInMins` parameter, we can simulate a short-lived JWT. ```http POST /auth/login HTTP/1.1 Host: dummyjson.com Content-Type: application/json Content-Length: 63 {"username":"emilys","password":"emilyspass","expiresInMins":1} ``` In the response to this request, an `accessToken` and `refreshToken` are returned. Until the `accessToken` expires, it can be used to access sensitive user data from the `/auth/me` endpoint: ```http GET /auth/me HTTP/1.1 Host: dummyjson.com Connection: close Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJlbWlseXMiLCJlbWFpbCI6ImVtaWx5LmpvaG5zb25AeC5kdW1teWpzb24uY29tIiwiZmlyc3ROYW1lIjoiRW1pbHkiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJnZW5kZXIiOiJmZW1hbGUiLCJpbWFnZSI6Imh0dHBzOi8vZHVtbXlqc29uLmNvbS9pY29uL2VtaWx5cy8xMjgiLCJpYXQiOjE3Nzk2NDM0MDEsImV4cCI6MTc3OTY0MzQ2MX0.t-mV4fcqjvQmRu-I2is_iWV7_1MoJ2h8eVmCQMNhlnk ``` Once a minute has passed, a **401 Unauthorized** response is returned instead of user data with a body notifying the `accessToken` has expired: ```http { "message": "Token Expired!" } ``` With the `refreshToken` that was returned in the initial login response, a new valid `accessToken` can be obtained from the response to a POST request to the `/auth/refresh` endpoint: ```http POST /auth/refresh HTTP/1.1 Host: dummyjson.com Content-Type: application/json Content-Length: 397 {"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJlbWlseXMiLCJlbWFpbCI6ImVtaWx5LmpvaG5zb25AeC5kdW1teWpzb24uY29tIiwiZmlyc3ROYW1lIjoiRW1pbHkiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJnZW5kZXIiOiJmZW1hbGUiLCJpbWFnZSI6Imh0dHBzOi8vZHVtbXlqc29uLmNvbS9pY29uL2VtaWx5cy8xMjgiLCJpYXQiOjE3Nzk2NDA4OTIsImV4cCI6MTc4MjIzMjg5Mn0.kmaBxCM5Sq1ybQFZcspzf1HnJBPpZ9maMwOUjxreoYI","expiresInMins":1} ``` ## Creating a Convert Workflow To begin, navigate to the Workflows interface, select the `Convert` tab, and **click** on the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections For this workflow, the overall node layout will be: * The `Convert Start` node outputs `$convert_start.data` that represents the user-selected data that will undergo conversion (*in this case, the `accessToken` JWT that is the value of the `Authorization` header in a request*). * The `Javascript` node executes a script on the `accessToken` and outputs the converted data as `$javascript.data`. * Once the script in the `Javascript` node finishes, the workflow will end. ## Refreshing the JWT 1. **Click** on the `Javascript` node to access its editor. 2. Then, **click** within the coding environment, select all of the existing code, and replace it with the following script: ```js import { Request as FetchRequest, fetch } from "caido:http"; async function saveTokens(sdk, body) { await sdk.env.setVar({ name: "ACCESS_TOKEN", value: body.accessToken, secret: false, global: true, }); await sdk.env.setVar({ name: "REFRESH_TOKEN", value: body.refreshToken, secret: false, global: true, }); } async function login(sdk) { const resp = await fetch( new FetchRequest("https://dummyjson.com/auth/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ username: "emilys", password: "emilyspass", expiresInMins: 1, }), }), ); if (!resp.ok) { sdk.console.error(`Login failed: ${resp.status} ${resp.statusText}`); sdk.console.error(await resp.text()); return null; } const body = await resp.json(); sdk.console.log(`/auth/login: ${resp.status} ${resp.statusText}`); sdk.console.log(JSON.stringify(body)); await saveTokens(sdk, body); return body.accessToken; } async function refresh(sdk, refreshToken) { const resp = await fetch( new FetchRequest("https://dummyjson.com/auth/refresh", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ refreshToken, expiresInMins: 1, }), }), ); if (!resp.ok) { sdk.console.error(`Refresh failed: ${resp.status} ${resp.statusText}`); sdk.console.error(await resp.text()); return null; } const body = await resp.json(); sdk.console.log(`/auth/refresh: ${resp.status} ${resp.statusText}`); sdk.console.log(JSON.stringify(body)); await saveTokens(sdk, body); return body.accessToken; } export async function run({ data, extra }, sdk) { let accessToken = sdk.env.getVar("ACCESS_TOKEN"); if (!accessToken) { const token = await login(sdk); return { data: token ?? sdk.asString(data), extra }; } const meResp = await fetch( new FetchRequest("https://dummyjson.com/auth/me", { method: "GET", headers: { Authorization: `Bearer ${accessToken}`, }, }), ); sdk.console.log(`/auth/me: ${meResp.status} ${meResp.statusText}`); if (meResp.status !== 401) { if (!meResp.ok) { sdk.console.error(await meResp.text()); } return { data: accessToken, extra }; } const refreshToken = sdk.env.getVar("REFRESH_TOKEN"); if (refreshToken) { const token = await refresh(sdk, refreshToken); if (token) { return { data: token, extra }; } } sdk.console.log("Refresh unavailable or failed; logging in again"); const token = await login(sdk); return { data: token ?? accessToken, extra }; } ``` 3. Next, ensure the `$convert_start.data` is [referenced as input data](/app/guides/workflows_references.md). Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ## Script Breakdown To be able to send a fetch request, the `Request` class and the `fetch()` function are imported from the `caido:http` module. ```js import { Request as FetchRequest, fetch } from "caido:http"; ``` The `saveTokens()` function is defined to set environment variables `ACCESS_TOKEN` and `REFRESH_TOKEN` in the global environment. ```js async function saveTokens(sdk, body) { await sdk.env.setVar({ name: "ACCESS_TOKEN", value: body.accessToken, secret: false, global: true, }); await sdk.env.setVar({ name: "REFRESH_TOKEN", value: body.refreshToken, secret: false, global: true, }); } ``` The `login()` function is defined to log in with valid user credentials. If authentication is successful, the `accessToken` and `refreshToken` are saved to the global environment using the `saveTokens()` function. ```js async function login(sdk) { const resp = await fetch( new FetchRequest("https://dummyjson.com/auth/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ username: "emilys", password: "emilyspass", expiresInMins: 1, }), }), ); if (!resp.ok) { sdk.console.error(`Login failed: ${resp.status} ${resp.statusText}`); sdk.console.error(await resp.text()); return null; } const body = await resp.json(); sdk.console.log(`/auth/login: ${resp.status} ${resp.statusText}`); sdk.console.log(JSON.stringify(body)); await saveTokens(sdk, body); return body.accessToken; } ``` The `refresh()` function is defined to refresh the `accessToken` using the `refreshToken` that was saved to the global environment. If the refresh is successful, the `accessToken` is saved to the global environment using the `saveTokens()` function. ```js async function refresh(sdk, refreshToken) { const resp = await fetch( new FetchRequest("https://dummyjson.com/auth/refresh", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ refreshToken, expiresInMins: 1, }), }), ); if (!resp.ok) { sdk.console.error(`Refresh failed: ${resp.status} ${resp.statusText}`); sdk.console.error(await resp.text()); return null; } const body = await resp.json(); sdk.console.log(`/auth/refresh: ${resp.status} ${resp.statusText}`); sdk.console.log(JSON.stringify(body)); await saveTokens(sdk, body); return body.accessToken; } ``` The `run()` function is defined to execute the workflow. If the `accessToken` is not set, the `login()` function is called to log in with valid user credentials. If the `accessToken` is set, the `refresh()` function is called to refresh the `accessToken` using the `refreshToken` that was saved to the global environment. If the refresh is successful, the `accessToken` is saved to the global environment using the `saveTokens()` function. ```js export async function run({ data, extra }, sdk) { let accessToken = sdk.env.getVar("ACCESS_TOKEN"); if (!accessToken) { const token = await login(sdk); return { data: token ?? sdk.asString(data), extra }; } const meResp = await fetch( new FetchRequest("https://dummyjson.com/auth/me", { method: "GET", headers: { Authorization: `Bearer ${accessToken}`, }, }), ); sdk.console.log(`/auth/me: ${meResp.status} ${meResp.statusText}`); if (meResp.status !== 401) { if (!meResp.ok) { sdk.console.error(await meResp.text()); } return { data: accessToken, extra }; } const refreshToken = sdk.env.getVar("REFRESH_TOKEN"); if (refreshToken) { const token = await refresh(sdk, refreshToken); if (token) { return { data: token, extra }; } } sdk.console.log("Refresh unavailable or failed; logging in again"); const token = await login(sdk); return { data: token ?? accessToken, extra }; } ``` ## Testing the Workflow To test the workflow: 1. Send the following request via Replay: ```http POST /auth/login HTTP/1.1 Host: dummyjson.com Content-Type: application/json Content-Length: 63 {"username":"emilys","password":"emilyspass","expiresInMins":1} ``` 2. Copy the value of the `accessToken` from the response. 3. Send the following request via Replay using the `accessToken` you copied in the previous step as the value of the `Authorization` header: ```http GET /auth/me HTTP/1.1 Host: dummyjson.com Connection: close Authorization: Bearer ``` 4. After one minute has passed send the previous request again and notice that a **401 Unauthorized** response is returned. 5. **Click**, **hold**, and **drag** over the `accessToken` value of the `Authorization` header and **click** the `+` button to add it as a placeholder. 6. Then, **click** on the associated edit button of the placeholder to open the `Placeholder Settings` window. 7) **Click** on the `Type` drop-down menu and select `Workflow`. 8) **Click** on the `Workflow` drop-down menu and select the workflow from the list. 9) **Click** on the `Add` button to save the configuration. 10. Close the settings window and send the request. ## The Result The workflow will execute every time the request is sent and automatically refresh the `accessToken` when it expires. The result will be continuous, successful `200 OK` responses with the new `accessToken` in the `Authorization` header. The log messages of the JavaScript node can be viewed in the [frontend logs](/app/troubleshooting/report_bug.md#frontend-logs). If you navigate to the **Environment** interface, you will notice the `ACCESS_TOKEN` and `REFRESH_TOKEN` environment variables that have been set by the workflow. --- --- url: /app/tutorials/refresh_authentication.md description: >- Learn how to create passive workflows that automatically extract and store session cookies or tokens as environment variables for continuous testing. --- # Refresh Authentication Workflow In this tutorial, we will create a passive workflow that will automatically store and update either session cookies or tokens, as environment variables. Then, by using [placeholders in requests for the environment variables](/app/guides/replay_environment_variables.md), you can achieve continuous, uninterrupted testing without manually updating expired sessions. ## setVar() The `setVar()` function sets an environment variable to a given value. It requires the following parameters: * `name`: The name of the environment variable. * `value`: The value of the environment variable. * `secret`: Determines if the environment variable is displayed as plaintext or masked. * `global`: Determines if the envrionment variable is set globally or in the currently selected envrionment. ```js await sdk.env.setVar({ name: "session", value: "123ABC321XYZ", secret: true, global: false }); ``` ::: info If the `name` does not already exist, a new environment variable will be created. If the `name` matches an existing environment variable, its value will be overwritten. ::: ::: tip To set the variable to a specific environment, use the `env` field and supply an existing environment name as its value: ```text env: "Demo Environment" ``` This specification will take precedence over the `global` flag. ::: ## Creating a Passive Workflow To begin, navigate to the Workflows interface, select the `Passive` tab, and **click** the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections For both workflows, the overall node layout will be: * The `On Intercept Response` node outputs `$on_intercept_response.request` and `$on_intercept_response.response` objects which represent proxied requests and their corresponding responses. * The `In Scope` node checks if the value of a request's Host header is included in the in-scope list of a scope preset. If it is not - the workflow will end. * In-scope request and response objects will be passed to the `Javascript` node. * Once a request or response has been processed by the script in the `Javascript` node, the workflow will end. ## Session Cookies Consider a response to a successful credential submission that issues a session cookie via the `Set-Cookie` header: ```http Set-Cookie: session=757365723D636169646F3B726F6C653D75736572; ``` ### Extracting a Session Cookie 1. **Click** on the `In Scope` node to access its editor and ensure the `$on_intercept_response.request` object is [referenced as input data](/app/guides/workflows_references.md). 2) Close the editor window and **click** on the `Javascript` node to access its editor. 3) Then, **click** within the coding environment, select all of the existing code, and replace it with the following script: ```js export async function run({ request, response }, sdk) { if (response) { let cookie = response.getHeader("Set-Cookie"); if (cookie && cookie.length > 0) { await sdk.env.setVar({ name: "session", value: cookie.join("; "), secret: false, global: true }); } } } ``` 4. Reference the `$on_intercept_response.request` and `$on_intercept_response.response` objects as input data. Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ### Script Breakdown First, an asynchronous function is defined that takes a `request` and `response` object pair and the `sdk` object as parameters. The script will execute every time an in-scope response object is passed from the `In Scope` node. ```js export async function run({ request, response }, sdk) { if (response) { ``` Then, using the `.getHeader()` method, the `Set-Cookie` header is extracted and stored in the `cookie` variable. If the header exists, the `.setVar()` method is used to set an environment variable. ```js let cookie = response.getHeader("Set-Cookie"); if (cookie && cookie.length > 0) { await sdk.env.setVar({ name: "session", value: cookie.join("; "), secret: false, global: true }); ``` ### Testing the Workflow To test the workflow: 1. Type in an in-scope domain in the connection URL input field. 2. Then, add a `Set-Cookie: session=;` header to the response. 3) Next, **click** on the `Run` button. A message will appear notifying you that the workflow executed successfully. ### The Result To view the set environment variable, navigate to the `Environment` interface and refresh the `Global` environment by **clicking** on its list row. ## Session Tokens Consider a response to a successful credential submission that issues a session token via an `access_token` JSON parameter: ```http {"access_token":"BQA_QoGKzM2I7sqcQ5cKB0oM4F_1VjwYXyUBdFJZ63nMwbrAejF0hel0dA0Ox9IRH_IT-rbt7F7dBudUOGX-kQExt3ezVuL0OBOOXYPaTVjQ5ZpE_ybkkKNEsyIjzIwOtx_7_xhuXvdaVp0BM_Lq2empsCauwvMujhPNf0HcTG0D-zIfLx9wh465oeGk0qVPM0ypFRxRWjkzM0BVMcRzG07pNk9HT_t3cBhuXt3r57o8XqKUQXlhNhWfMNca9N2v","token_type":"Bearer","expires_in":3600,"scope":"email"} ``` ### Extracting a Session Token 1. **Click** on the `In Scope` node to access its editor and ensure the `$on_intercept_response.request` object is [referenced as input data](/app/guides/workflows_references.md). 2) Close the editor window and **click** on the `Javascript` node to access its editor. 3) Then, **click** within the coding environment, select all of the existing code, and replace it with the following script: ```js export async function run({ request, response }, sdk) { const authFilter = `req.path.cont:"/auth" OR req.path.cont:"/login" OR req.path.cont:"/token" OR req.path.cont:"/oauth" OR req.path.cont:"/refresh"`; if (sdk.requests.matches(authFilter, request, response)) { let body = response.getBody(); if (body) { let json = body.toJson(); let accessToken = json.access_token; if (accessToken) { await sdk.env.setVar({ name: "Bearer", value: accessToken, secret: false, global: true, }); } } } } ``` 4. Reference the `$on_intercept_response.request` and `$on_intercept_response.response` objects as input data. Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ### Script Breakdown First, an asynchronous function is defined that takes a `request` and `response` object pair and the `sdk` object as parameters. ```js export async function run({ request, response }, sdk) { ``` Using `sdk.requests.matches()` the execution of the script is scoped to common authentication endpoints with HTTPQL query statements. The script will execute every time an in-scope request object to one of these endpoints is passed from the `In Scope` node. ```js const authFilter = `req.path.cont:"/auth" OR req.path.cont:"/login" OR req.path.cont:"/token" OR req.path.cont:"/oauth" OR req.path.cont:"/refresh"`; if (sdk.requests.matches(authFilter, request, response)) { ``` Then, using the `.getBody()` method, we extract the response body and if it exists we parse it as JSON using `.toJson()`. If an `access_token` parameter exists, we use the `.setVar()` method to set an environment variable. ```js let body = response.getBody(); if (body) { let json = body.toJson(); let accessToken = json.access_token; if (accessToken) { await sdk.env.setVar({ name: "Bearer", value: accessToken, secret: false, global: true, }); } } } } ``` ### Testing the Workflow To test the workflow: 1. Type in an in-scope domain in the connection URL input field. 2. Edit the request endpoint to be in-scope. 3. Then, add the following body data to the response: ```json {"access_token":"BQA_QoGKzM2I7sqcQ5cKB0oM4F_1VjwYXyUBdFJZ63nMwbrAejF0hel0dA0Ox9IRH_IT-rbt7F7dBudUOGX-kQExt3ezVuL0OBOOXYPaTVjQ5ZpE_ybkkKNEsyIjzIwOtx_7_xhuXvdaVp0BM_Lq2empsCauwvMujhPNf0HcTG0D-zIfLx9wh465oeGk0qVPM0ypFRxRWjkzM0BVMcRzG07pNk9HT_t3cBhuXt3r57o8XqKUQXlhNhWfMNca9N2v","token_type":"Bearer","expires_in":3600,"scope":"email"} ``` 4. Next, **click** on the `Run` button. A message will appear notifying you that the workflow executed successfully. ### The Result To view the set environment variable, navigate to the `Environment` interface and refresh the `Global` environment by **clicking** on its list row. ## Using the Environment Variables Now, with these workflows providing up-to-date session identifiers: 1. Navigate to the Replay interface. 2. Within a request, **click**, **hold**, and **drag** the left mouse button over the value you want to be replaced and **click** the `+` button to add it as a placeholder. 3) Then, **click** on the associated edit button of the placeholder to open the `Placeholder Settings` window. 4) Select `Environment Variable` from the top drop-down menu. 5) Select the environment variable by name from the `Environment Variable` drop-down menu 6) Then, **click** on the `Add` button to save the configuration. The addition will be reflected in the list below. Close the settings window and send the request. ::: tip To verify the addition was successful, you can view the request by navigating to the Search interface. ::: --- --- url: /app/concepts/instance_registration.md --- # Registration When an instance is started for the first time, it will register itself with the [Caido Cloud](./cloud.md) as an [OAuth 2.0 Client](./instance_authentication.md). At this stage the instance is considered "unclaimed", meaning that **anybody** with access to the instance can claim it for themselves or one of their Teams (in a [Workspace](/dashboard/concepts/workspace)). You can **only** log into an instance if it has been claimed. ## Human Claim On initial the login, if it the instance is "unclaimed", you can claim it. This is the same idea if you [reset the credentials](/app/troubleshooting/authentication.html#reset-the-instance-credentials) of your instance. You are prompted to choose a name and a [Workspace](/dashboard/concepts/workspace) in which the instance will live. Claiming an instance in a Team workspace will allow team members to access the instance. The flow usually looks like: ```mermaid sequenceDiagram autonumber Instance->>Cloud: Registers itself User->>Instance: Clicks on login User->>Cloud: Claims instance User->>Cloud: Approves login Cloud->>Instance: Creates and Gives tokens Instance->>User: Forwards tokens ``` :::warning Do **NOT** leave instances unclaimed, anybody can claim them and then access the machine on which Caido is installed ::: ## Machine claim For Teams, you can also automatically claim new instances using [Registration Keys](/dashboard/concepts/registration_key). This allows you to deploy a lot of instances in advance for testers (ahead of an engagement) or on demand (in CICD). This ensures that all the instances are safe even if no human is involved in the deployment. Currently you need to use the [Caido CLI](./cli_vs_desktop.md) to pass the Registration Key to the instance. You can use either the `--registration-key` flag or the environment variable `CAIDO_REGISTRATION_KEY`. The flow usually looks like: ```mermaid sequenceDiagram autonumber Instance->>Cloud: Registers itself with Key Cloud->>Cloud: Claims instance Note over Instance,User: Time passes (SAFE) User->>Instance: Clicks on login User->>Cloud: Approves login Cloud->>Instance: Creates and Gives tokens Instance->>User: Forwards tokens ``` Check our guide on [how to create a registration key](/dashboard/guides/create_registration_key) to get started. --- --- url: /dashboard/concepts/registration_key.md --- # Registration Key Registration Keys allow you to automatically claim new instances. This allows you to deploy instances safely without human intervention. For example, ahead of an engagement or on demand in CICD. Registration Keys are easy identifiable with the `ckey_` prefix. They can be single use or reusable, a single use key is automatically revoked on use. * Check our documentation on [instance registration](/app/concepts/instance_registration) to understand how they fit in that process. * Check our guide on [how to create a registration key](/dashboard/guides/create_registration_key) to get started. --- --- url: /app/tutorials/remote.md description: Learn how to host Caido remotely in a variety of ways. --- # Remote Hosting In this tutorial, you will learn how Caido's client/server-based architecture enables remote hosting, what advantages that setup provides, and how to configure it for different environments. ## Architecture Caido consists of two components: 1. The **client** component. 2. The **server** component. When you're using the Caido desktop application, both components are packaged together: * The client component is an Electron application installed on your local device that includes the windows, interfaces, menus, buttons, and other GUI elements you use to operate Caido. * The server component is the Caido CLI tool that runs as a background process that listens for operations generated by the client component and handles proxied network traffic. However, the server component, the Caido CLI, can be installed as a standalone binary. Once the binary is launched, instead of operating Caido via an installed desktop application, the Caido GUI becomes available as a browser web application. The decoupling of the two components is what allows you to install the server component on a remote server and access the [instance](/app/concepts/instance.md) from your local device. Being able to run the Caido CLI on a remote server and control it over the web offers several advantages: * Instead of keeping your own device awake, Caido can be offloaded to a server that is running continuously. * You can use a server with better hardware specifications than your own device, improving performance. * You and other members of your [Team](/dashboard/guides/create_team.md) can access the same instance from multiple devices. * Instances can be deployed automatically on-demand with [registration keys](/dashboard/guides/create_registration_key.md). * You can create instances using your own infrastructure, allowing you to store security audit data on your own servers. ::: warning NOTE True multi-user instance usage is not yet available. However, data can be shared between members via the [Drop](/app/tutorials/drop.md) plugin. ::: There are multiple ways to launch the Caido CLI on a remote server and access the GUI, which we will cover below. ## Downloading & Launching the Caido CLI The Caido CLI is available as either a standalone binary or a Docker image container. ### Standalone Binary ::: tip To sort JSON data, install the `jq` tool: ```bash sudo apt install jq ``` ::: To list the latest release of the Caido CLI for your device's operating system, enter: ::: code-group ```bash [Linux] curl -s https://caido.download/releases/latest | jq -r '.links[] | select(.os=="linux" and .kind=="cli") | .link' ``` ```bash [macOS] curl -s https://caido.download/releases/latest | jq -r '.links[] | select(.os=="macos" and .kind=="cli") | .link' ``` ```powershell [Windows] (curl.exe -s "https://caido.download/releases/latest" | ConvertFrom-Json).links | Where-Object { $_.os -eq "windows" -and $_.kind -eq "cli" } | Select-Object -ExpandProperty link ``` ::: To download the Caido CLI, replace `` in the following command with the appropriate link for your operating system architecture: ::: code-group ```bash [Linux] curl -L -o caido-cli.tar.gz ``` ```bash [macOS] curl -L -o caido-cli.zip ``` ```powershell [Windows] curl.exe -L -o caido-cli.zip ``` ::: To extract the Caido CLI binary from the downloaded archive, enter: ::: code-group ```bash [Linux] tar -xzf caido-cli.tar.gz ``` ```bash [macOS] unzip -o caido-cli.zip ``` ```powershell [Windows] Expand-Archive -Path caido-cli.zip -DestinationPath . ``` ::: ::: danger Running Caido with root/administrative privileges is **NOT** recommended. Doing so **will** create issues later on since any resource created by Caido will be owned by the root/administrator user. **DO NOT DO THIS.** ::: Once the binary is extracted, to launch the Caido CLI, enter: ::: code-group ```bash [Linux/macOS] ./caido-cli ``` ```powershell [Windows] caido-cli.exe ``` ::: ### Docker Image Container The Caido CLI can also be launched with [Docker Compose](https://docs.docker.com/compose/). Ensure [Docker Engine](https://docs.docker.com/engine/install/) is installed and the Docker daemon is running or launched. By default, Caido projects are not saved between container restarts unless project data is stored on the remote host. So, to persist project data, create a directory on the remote host (*e.g. `~/caido-docker`*): ```bash mkdir -p ~/caido-docker ``` Once the directory is created, create a `docker-compose.yml` file on the remote host with the following content. Replace `/home/user/caido-docker` with the absolute path to the directory created above, and replace `7000` with an unused port on the remote host if needed: ```yaml services: caido: image: caido/caido:latest container_name: caido ports: - "127.0.0.1:7000:8080" volumes: - /home/user/caido-docker:/home/caido/.local/share/caido restart: unless-stopped ``` From the directory containing the `docker-compose.yml` file, download the image: ```bash sudo docker compose pull ``` Next, obtain the `uid` and `gid` of the `caido` user in the Docker container: ```bash sudo docker compose run --rm caido id ``` To grant ownership of the directory (*e.g. `~/caido-docker`*), replace `` and `` in the following command with the `uid` and `gid` of the `caido` user: ```bash sudo chown -v -R : ~/caido-docker ``` To launch the container in the background: ```bash sudo docker compose up -d ``` ## Accessing the Instance via SSH Once the Caido CLI is launched, you can access the Caido GUI over a secure SSH tunnel. To connect to an instance, open a new terminal and replace `` with an unused port on your local device and replace `` and `` with the username and IP address of the remote host: ```shell # Standalone Binary ssh -L :127.0.0.1:8080 @ # Docker Image Container ssh -L :127.0.0.1:7000 @ ``` In a browser on your local device, navigate to `http://127.0.0.1:` to access the Caido GUI. ## Exposing an Instance to the Internet Alternatively, you can serve the Caido GUI from a domain. This option is useful for easy collaboration between team members or for sharing instances with clients. ::: danger By default, [Guest Mode](/app/guides/guest_mode.md) is **disabled** for the Caido CLI. If Guest Mode is enabled, the Caido instance will be publicly accessible without authentication. For security and confidentiality, ensure Guest Mode is disabled and avoid the `--allow-guests` command-line option when launching the Caido CLI before exposing an instance to the internet. ::: ### Nginx Configuration 1. To logically separate the internet-exposed Caido instance from your existing setup, create a new subdomain (*e.g. `caido.example.com`*) by adding an A record for the IP address of your server. 2. SSH into your server. 3. Create a new `sites-available` file for the domain and use the `proxy_pass` directive to route traffic to Caido: ```bash sudo nano /etc/nginx/sites-available/caido.example.com ``` ```txt server { server_name caido.example.com; location / { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_http_version 1.1; } listen 80; listen [::]:80; } ``` 4. Make the site available, test the configuration, and reload the web server: ```bash sudo ln -s /etc/nginx/sites-available/caido.example.com /etc/nginx/sites-enabled/ ``` ```bash sudo nginx -t ``` ```bash sudo systemctl reload nginx ``` 5. Obtain an SSL/TLS certificate: ```bash sudo certbot --nginx -d caido.example.com ``` 6. Launch the Caido CLI: ```bash ./caido-cli --ui-listen 127.0.0.1:8081 --proxy-listen 127.0.0.1:8082 --ui-domain caido.example.com --debug --no-renderer-sandbox --no-open ``` 7. Navigate to the domain specified by `--ui-domain` to access the Caido GUI. ### Docker & Traefik Configuration Caido can also be served from a domain with Docker and [Traefik](https://doc.traefik.io/traefik/). ::: warning NOTE Ensure to replace `user` with your username, `caido.example.com` with your domain, `user@example.com` with your email address, and account for any currently running processes by changing the ports. ::: 1. SSH into your server. 2. Create a `docker-compose.yml` file with the following content: ```txt services: caido: image: caido/caido:0.55.3 container_name: caido ports: - "127.0.0.1:8082:8082" volumes: - /home/user/caido/data/:/home/caido/.local/share/caido command: > caido-cli --no-renderer-sandbox --debug --no-open --ui-listen 0.0.0.0:8080 --ui-domain caido.example.com --proxy-listen 0.0.0.0:8082 restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.caido.rule=Host(`caido.example.com`)" - "traefik.http.routers.caido.entrypoints=websecure" - "traefik.http.routers.caido.tls.certresolver=letsencrypt" - "traefik.http.services.caido.loadbalancer.server.port=8080" traefik: image: traefik:v3.6 container_name: traefik restart: unless-stopped ports: - "80:80" # HTTP - "443:443" # HTTPS / TLS termination command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" # Redirect HTTP → HTTPS - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" # Let’s Encrypt - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" - "--certificatesresolvers.letsencrypt.acme.email=user@example.com" - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt ``` 3. Create a data storage location for Caido (*e.g. `/home/user/caido/data`*): ```bash mkdir -p /home/user/caido/data ``` 4. Grant ownership of the directory to the `caido` user: ```bash sudo chown -R 996:996 /home/user/caido/data ``` 5. Make the directory writable: ```bash sudo chmod -R 777 /home/user/caido/data ``` ::: warning NOTE If Nginx is running, kill the process before continuing: ```bash sudo systemctl stop nginx ``` ::: 6. Then, run the container to launch Caido: ```bash sudo docker compose up ``` 7. Navigate to the domain specified by `--ui-domain` to access the Caido GUI. ::: warning NOTE If you encounter authorization errors, **click** on the account button in the top-right corner of the Caido user-interface and select Logout to reauthenticate. ::: #### Creating Remote Instances from the Desktop Application Once the Caido CLI is running and the domain is accessible, additional instances can be created via the launch window of the desktop application. This allows you to use the desktop application to create and manage instances on the remote server. To create a new instance: 1. Open the launch window and **click** on the New instance button. 2. Select the `Remote` tab, name the instance, specify the domain name and port, and **click** on the `Create` button. Once authenticated, the remote instance GUI will be available via the desktop application. ::: tip To automate headless Caido instances via scripting, view the [Orchestrating Caido Headless](/app/tutorials/headless_orchestration.md) tutorial. ::: --- --- url: /app/guides/automate_null.md description: >- A step-by-step guide to repeating requests multiple times without payload values in Caido's Automate feature for load testing and request repetition. --- # Repeating Requests with No Payload To send the same request multiple times without any payload values, **click** anywhere within the request and then **click** on the `+ Add Placeholder` button. Once a placeholder has been marked, you will be presented with options in the `Payload` tab. From the `Type` drop-down menu, select the `Null` option. This option will present a `Number of payloads to generate` input field that allows you specify how many times the request should be resent. Once the number has been specified, **click** on the `Run` button to launch the Automate session. A new tab will be generated that contains a traffic table of the requests. To view the results of the session, **click** on this paired tab. ::: info If `Close Connection` is disabled in the `Settings` tab, the TCP connection is maintained through the session until it is terminated by the server. ::: --- --- url: /app/quickstart/replay.md description: >- A step-by-step guide to Caido's Replay feature for creating, modifying, and sending individual HTTP requests for security testing. --- # Replay The `Replay` interface gives you the ability to create, modify, and send individual requests. Each sent request and its corresponding response are recorded, enabling you to compare and identify how specific modifications affect responses. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Sending Requests to Replay](/app/guides/replay_requests.md) * [Resending Requests](/app/guides/replay_resending.md) * [Using Workflows in Replay](/app/guides/replay_workflows.md) * [Using Environment Variables in Replay](/app/guides/replay_environment_variables.md) ::: --- --- url: /burp-suite/core/reporting.md description: Map Burp Suite Pro reporting features to Caido. --- # Reporting Burp Suite Pro reporting and export features and their Caido equivalents. ## Indirectly Available ### Generating a Report Burp exports scan results and findings as formatted HTML or XML reports. Caido tracks issues in native **Findings** and exports raw traffic data through **Exports**. Caido does not ship formatted HTML or XML report generation like Burp; use **Findings** for issue tracking, **Exports** for external reporting tools, or the **Notify** plugin to push findings to notification platforms. #### Resources * [Findings](/app/quickstart/findings.md) * [Exports](/app/quickstart/exports.md) * [Exporting Requests](/app/guides/exports_requests.md) * [Notify](https://github.com/MDGDSS/caido-notify) (GitHub) --- --- url: /app/guides/replay_resending.md description: >- A step-by-step guide to resending requests in Caido's Replay feature for testing modifications and analyzing response changes. --- # Resending Requests ## ::: tip Video Demonstration To resend a request, **click** on the `Send` button. You can resend requests as many times as you want, allowing you to test how modifications alter the response. --- --- url: /app/tutorials/aws_signature.md description: >- Learn how to create a convert workflow to automatically resign AWS requests with Signature V4 authentication for API access. --- # Resign AWS Requests Workflow In this tutorial, we will create a convert workflow that will resign authenticated AWS requests sent in Replay by adding a valid [(AWS Signature V4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html) `Authorization` header. Then, by using [workflows in Replay](/app/guides/replay_environment_variables.md), you can achieve continuous, uninterrupted testing without manually updating expired sessions. ::: tip A similar method can be used for other cloud providers as many follow the same signature process. ::: ## Creating a Convert Workflow To begin, navigate to the Workflows interface, select the `Convert` tab, and **click** the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections To add nodes to the workflow, **click** on `+ Add Node` button and then the `+ Add` button of a specific node. For this workflow, the overall node layout will be: * The `Convert Start` node outputs `$convert_start.data` that represents the request that will undergo conversion. * The `Javascript` node accesses environment variables to retrieve AWS credentials, creates a signing key, signs the request, and generates a valid authentication header. * Once the header has been returned by the `Javascript` node, the resigned request will be output, and the workflow will end. ## Creating the Environment Variables For this workflow, you will need to obtain your: * AWS Access Key ID * AWS Secret Access Key * Resource region ID * Resource service ID With these values, [create environment variables](https://docs.caido.io/app/tutorials/aws_signature.html) in the `Global` environment with the following names: | Name | Value | Value Example | |----------|-------------|---------| | `AWS_ACCESS_KEY` | Your AWS Access Key ID | `AKIAXXXXXXXXXXXXXXXX` | | `AWS_SECRET_ACCESS_KEY` | Your AWS Secret Access Key | `xX3X51XXxXx77XXXXXxXXXX83x0XxX+1XXxxx8Xx` | | `AWS_REGION` | Your AWS Resource Region ID | `us-east-1` | | `AWS_SERVICE` | Your AWS Service ID | `s3` | ## Resigning AWS Requests 1. **Click** on the `Javascript` node to access its editor and ensure the `$convert_start.data` is [referenced as input data](/app/guides/workflows_references.md). 2) Then, **click** within the coding environment, select all of the existing code, and replace it with the following script: ```js import { createHmac, createHash } from "crypto"; import { RequestSpec } from "caido:utils"; function getSignatureKey(key, dateStamp, regionName, serviceName) { const kDate = createHmac("SHA256", `AWS4${key}`).update(dateStamp).digest(); const kRegion = createHmac("SHA256", kDate).update(regionName).digest(); const kService = createHmac("SHA256", kRegion).update(serviceName).digest(); const kSigning = createHmac("SHA256", kService) .update("aws4_request") .digest(); return kSigning; } function sign(sdk, spec) { const accessKey = sdk.env.getVar("AWS_ACCESS_KEY"); const secretAccessKey = sdk.env.getVar("AWS_SECRET_ACCESS_KEY"); const region = sdk.env.getVar("AWS_REGION"); const service = sdk.env.getVar("AWS_SERVICE"); const now = new Date(); const year = now.getUTCFullYear(); const month = String(now.getUTCMonth() + 1).padStart(2, "0"); const day = String(now.getUTCDate()).padStart(2, "0"); const hours = String(now.getUTCHours()).padStart(2, "0"); const minutes = String(now.getUTCMinutes()).padStart(2, "0"); const seconds = String(now.getUTCSeconds()).padStart(2, "0"); const amzDate = `${year}${month}${day}T${hours}${minutes}${seconds}Z`; const dateStamp = amzDate.slice(0, 8); const method = spec.getMethod(); const canonicalUri = spec.getPath(); const canonicalQueryString = spec.getQuery(); const host = spec.getHost(); const payload = spec.getBody()?.toRaw() ?? ""; const payloadHash = createHash("SHA256").update(payload).digest("hex"); const canonicalHeaders = `host:${host}\nx-amz-content-sha256:${payloadHash}\nx-amz-date:${amzDate}\n`; const signedHeaders = "host;x-amz-content-sha256;x-amz-date"; const canonicalRequest = [ method, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders, payloadHash, ].join("\n"); const hashedCanonicalRequest = createHash("sha256") .update(canonicalRequest) .digest("hex"); const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`; const stringToSign = [ "AWS4-HMAC-SHA256", amzDate, credentialScope, hashedCanonicalRequest, ].join("\n"); const signingKey = getSignatureKey( secretAccessKey, dateStamp, region, service, ); const signature = createHmac("sha256", signingKey) .update(stringToSign) .digest("hex"); const authorizationHeader = [ `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}`, `SignedHeaders=${signedHeaders}`, `Signature=${signature}`, ].join(", "); return { authorizationHeader, amzDate, payloadHash, }; } export function run({ data }, sdk) { try { const spec = RequestSpec.parse(data); const { authorizationHeader, amzDate, payloadHash } = sign(sdk, spec); return `Authorization: ${authorizationHeader}\r\nx-amz-date: ${amzDate}\r\nx-amz-content-sha256: ${payloadHash}\r\n`; } catch (e) { sdk.console.log(e.toString()); return data; } } ``` ::: info If you are using an older workflow (before `v0.55.0`), use `function run(input, sdk)` as signature. We used to pass the raw data directly as the first parameter. ::: 3. Close the editor window and **click** on the `Convert End` node to access its editor. 4. Reference the `$javascript.data` as input data. Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ### Script Breakdown It will output three headers (`Authorization`, `x-amz-date` and `x-amz-content-sha256`) that we will inject in our request. First, the script imports the required cryptographic functions from the backend `crypto` module and the `RequestSpec` utility to modify requests. ```js import { createHmac, createHash } from "crypto"; import { RequestSpec } from "caido:utils"; ``` Then, the `getSignatureKey` function is defined that will create the signing key using a series of `createHMAC` operations with the secret key, timestamp, region, and service name. ```js function getSignatureKey(key, dateStamp, regionName, serviceName) { const kDate = createHmac("SHA256", `AWS4${key}`).update(dateStamp).digest(); const kRegion = createHmac("SHA256", kDate).update(regionName).digest(); const kService = createHmac("SHA256", kRegion).update(serviceName).digest(); const kSigning = createHmac("SHA256", kService) .update("aws4_request") .digest(); return kSigning; } ``` The main `sign` function uses the `.getVar()` method to retrieve the environment variables, generates the current timestamp for the `x-amz-date` component, creates the canonical request with various `RequestSpec` methods and hashes any body data. ```js function sign(sdk, spec) { const accessKey = sdk.env.getVar("AWS_ACCESS_KEY"); const secretAccessKey = sdk.env.getVar("AWS_SECRET_ACCESS_KEY"); const region = sdk.env.getVar("AWS_REGION"); const service = sdk.env.getVar("AWS_SERVICE"); const now = new Date(); const year = now.getUTCFullYear(); const month = String(now.getUTCMonth() + 1).padStart(2, "0"); const day = String(now.getUTCDate()).padStart(2, "0"); const hours = String(now.getUTCHours()).padStart(2, "0"); const minutes = String(now.getUTCMinutes()).padStart(2, "0"); const seconds = String(now.getUTCSeconds()).padStart(2, "0"); const amzDate = `${year}${month}${day}T${hours}${minutes}${seconds}Z`; const dateStamp = amzDate.slice(0, 8); const method = spec.getMethod(); const canonicalUri = spec.getPath(); const canonicalQueryString = spec.getQuery(); const host = spec.getHost(); const payload = spec.getBody()?.toRaw() ?? ""; const payloadHash = createHash("SHA256").update(payload).digest("hex"); const canonicalHeaders = `host:${host}\nx-amz-content-sha256:${payloadHash}\nx-amz-date:${amzDate}\n`; const signedHeaders = "host;x-amz-content-sha256;x-amz-date"; const canonicalRequest = [ method, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders, payloadHash, ].join("\n"); const hashedCanonicalRequest = createHash("sha256") .update(canonicalRequest) .digest("hex"); ``` Next, it creates the credential scope and string to sign. ```js const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`; const stringToSign = [ "AWS4-HMAC-SHA256", amzDate, credentialScope, hashedCanonicalRequest, ].join("\n"); ``` Then, it generates the signing key, creates the final signature, pieces the `Authorization` header together, and returns it. ```js const signingKey = getSignatureKey( secretAccessKey, dateStamp, region, service, ); const signature = createHmac("sha256", signingKey) .update(stringToSign) .digest("hex"); const authorizationHeader = [ `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}`, `SignedHeaders=${signedHeaders}`, `Signature=${signature}`, ].join(", "); return { authorizationHeader, amzDate, payloadHash, }; } ``` The `run` function takes the initial `request` object as input, converts it to a mutable `RequestSpec` object, and parses it. Then, the `sign` function is called to sign the request and insert the valid `Authorization` header. ```js export function run({ data }, sdk) { try { const spec = RequestSpec.parse(data); const { authorizationHeader, amzDate, payloadHash } = sign(sdk, spec); return `Authorization: ${authorizationHeader}\r\nx-amz-date: ${amzDate}\r\nx-amz-content-sha256: ${payloadHash}\r\n`; } catch (e) { sdk.console.log(e.toString()); return data; } } ``` ## Testing the Workflow To test the workflow: 1. Send an unauthorized request in Replay to a private S3 bucket object. Without authentication, a 403 response will be returned. 2) Next, add an arbitrary `Authorization` header to the request, **click**, **hold**, and **drag** over it, and **click** the `+` button to add it as a placeholder. 3) **Click** on the associated edit button of the placeholder to open the `Placeholder Settings` window. 4. Use `CTRL` + `A` to select the whole request. With `Workflow` as the `Type`, **click** on the `Select a workflow` drop-down menu, select the workflow from the list, and **click** `Add` to save the configuration. 5) Close the editor window and **click** on the `Send` button to resend the Replay request. ::: warning Make sure all your headers are CRLF terminated, the workflow doesn't handle LF terminated headers. Click on `Options` -> `Display hidden charaters` to show them. You should see a `\r` on each header line. ::: ## The Result The content of the file will be returned in a 200 response. To view the request as it was sent, navigate to the Search interface and **click** on the associated request row. The full workflow is provided below, ready to be imported. ```json { "description": "Resigns authenticated requests using the AWS Signature V4 header method.", "edition": 2, "graph": { "edges": [ { "source": { "exec_alias": "exec", "node_id": 0 }, "target": { "exec_alias": "exec", "node_id": 2 } }, { "source": { "exec_alias": "exec", "node_id": 2 }, "target": { "exec_alias": "exec", "node_id": 1 } } ], "nodes": [ { "alias": "convert_start", "definition_id": "caido/convert-start", "display": { "x": -70, "y": 0 }, "id": 0, "inputs": [], "name": "Convert Start", "version": "0.1.0" }, { "alias": "convert_end", "definition_id": "caido/convert-end", "display": { "x": 350, "y": 0 }, "id": 1, "inputs": [ { "alias": "data", "value": { "data": "$javascript.data", "kind": "ref" } } ], "name": "Convert End", "version": "0.1.0" }, { "alias": "javascript", "definition_id": "caido/code-js", "display": { "x": 140, "y": 0 }, "id": 2, "inputs": [ { "alias": "data", "value": { "data": "$convert_start.data", "kind": "ref" } }, { "alias": "code", "value": { "data": "import { createHmac, createHash } from \"crypto\";\nimport { RequestSpec } from \"caido:utils\";\n\nfunction getSignatureKey(key, dateStamp, regionName, serviceName) {\n const kDate = createHmac(\"SHA256\", `AWS4${key}`).update(dateStamp).digest();\n const kRegion = createHmac(\"SHA256\", kDate).update(regionName).digest();\n const kService = createHmac(\"SHA256\", kRegion).update(serviceName).digest();\n const kSigning = createHmac(\"SHA256\", kService)\n .update(\"aws4_request\")\n .digest();\n return kSigning;\n}\n\nfunction sign(sdk, spec) {\n const accessKey = sdk.env.getVar(\"AWS_ACCESS_KEY\");\n const secretAccessKey = sdk.env.getVar(\"AWS_SECRET_ACCESS_KEY\");\n const region = sdk.env.getVar(\"AWS_REGION\");\n const service = sdk.env.getVar(\"AWS_SERVICE\");\n\n const now = new Date();\n const year = now.getUTCFullYear();\n const month = String(now.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(now.getUTCDate()).padStart(2, \"0\");\n const hours = String(now.getUTCHours()).padStart(2, \"0\");\n const minutes = String(now.getUTCMinutes()).padStart(2, \"0\");\n const seconds = String(now.getUTCSeconds()).padStart(2, \"0\");\n const amzDate = `${year}${month}${day}T${hours}${minutes}${seconds}Z`;\n const dateStamp = amzDate.slice(0, 8);\n\n const method = spec.getMethod();\n const canonicalUri = spec.getPath();\n const canonicalQueryString = spec.getQuery();\n const host = spec.getHost();\n const payload = spec.getBody()?.toRaw() ?? \"\";\n const payloadHash = createHash(\"SHA256\").update(payload).digest(\"hex\");\n const canonicalHeaders = `host:${host}\\nx-amz-content-sha256:${payloadHash}\\nx-amz-date:${amzDate}\\n`;\n const signedHeaders = \"host;x-amz-content-sha256;x-amz-date\";\n\n const canonicalRequest = [\n method,\n canonicalUri,\n canonicalQueryString,\n canonicalHeaders,\n signedHeaders,\n payloadHash,\n ].join(\"\\n\");\n const hashedCanonicalRequest = createHash(\"sha256\")\n .update(canonicalRequest)\n .digest(\"hex\");\n const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`;\n const stringToSign = [\n \"AWS4-HMAC-SHA256\",\n amzDate,\n credentialScope,\n hashedCanonicalRequest,\n ].join(\"\\n\");\n\n const signingKey = getSignatureKey(\n secretAccessKey,\n dateStamp,\n region,\n service,\n );\n const signature = createHmac(\"sha256\", signingKey)\n .update(stringToSign)\n .digest(\"hex\");\n const authorizationHeader = [\n `AWS4-HMAC-SHA256 Credential=${accessKey}/${credentialScope}`,\n `SignedHeaders=${signedHeaders}`,\n `Signature=${signature}`,\n ].join(\", \");\n\n return {\n authorizationHeader,\n amzDate,\n payloadHash,\n };\n}\n\nexport function run(input, sdk) {\n try {\n const spec = RequestSpec.parse(input);\n const { authorizationHeader, amzDate, payloadHash } = sign(sdk, spec);\n return `Authorization: ${authorizationHeader}\\r\\nx-amz-date: ${amzDate}\\r\\nx-amz-content-sha256: ${payloadHash}\\r\\n`;\n } catch (e) {\n sdk.console.log(e.toString());\n return input;\n }\n}", "kind": "string" } } ], "name": "Javascript", "version": "0.1.0" } ] }, "id": "2121672b-53d8-4004-aa80-d5021a954ead", "kind": "convert", "name": "Resign AWS Requests" } ``` --- --- url: /app/guides/docker.md description: >- A step-by-step guide to running Caido in Docker containers including image launching, project persistence, and custom Dockerfile examples. --- # Running in Docker Caido is available as an image on [Docker Hub](https://hub.docker.com/r/caido/caido) that can be ran directly on x86 architecture. ## Launching the Docker Image To launch the image, specify the port with the `-p` command-line option. For example, to launch the image on port `7000`, enter: ```bash docker run --rm -p 7000:8080 caido/caido:latest ``` You can then point your browser's proxy settings to `127.0.0.1:7000`. ::: tip For M1 users, it is now possible to enable [Rosetta](https://docs.docker.com/desktop/settings/mac/#use-rosetta-for-x86amd64-emulation-on-apple-silicon) in the Docker settings. You can then run images with `--platform linux/amd64`. ::: ## Project Persistence By default, projects created in the Docker container are not saved between `docker run` commands. Due to this, we recommend mounting a volume to store data on your file system to avoid losing data between Caido updates. To mount a volume, append the `-v :/home/caido/.local/share/caido` command-line option to the `docker run` command. ::: warning NOTE The host path must be an absolute path with the necessary permissions. Ensure the necessary permissions are granted to the host path with: `chown -R 999:999 ` ::: For example, to store Caido projects in `/home/my_user/my_data`, enter: ```bash docker run --rm -p 7000:8080 \ -v /home/my_user/my_data:/home/caido/.local/share/caido caido/caido:latest ``` ## Building the Image If you prefer to build the image yourself, a `Dockerfile` example is provided below: ```Dockerfile ## Base ## FROM debian:bullseye-slim as base RUN \ apt-get update && \ apt-get -y install ca-certificates && \ apt-get clean ## Download ## FROM base as download RUN \ apt-get -y install curl jq && \ curl -s https://api.caido.io/releases/latest \ | jq '.links[] | select(.display == "Linux") | .link' \ | xargs curl -s --output caido.tar.gz && \ tar -xf caido.tar.gz && \ rm caido.tar.gz ## Runtime ## FROM base RUN groupadd -r caido && useradd --no-log-init -m -r -g caido caido COPY --from=download caido /usr/bin/caido USER caido EXPOSE 8080 ENTRYPOINT ["caido"] CMD ["--listen", "0.0.0.0:8080"] ``` --- --- url: /app/guides/multiple_instances.md description: A step-by-step guide to running multiple Caido instances on the same device. --- # Running Multiple Instances To run multiple instances of Caido simultaneously, launch the Caido CLI with the `--listen ` and `--data-path ` arguments. ::: warning NOTE Ensure any additional instances are using unique ports and data storage locations. ::: Then, [import the CA certificate](/app/guides/ca_certificate_importing.md) of the new instance, configure your proxy settings to account for the new listening address, and navigate to the listening address in your browser to access the additional user interface. --- --- url: /app/guides/vps.md description: >- A step-by-step guide to running Caido on a virtual private server (VPS) including SSH port forwarding and AWS SSM configuration for remote access. --- # Running on a VPS Caido is designed to be a flexible web application security testing tool, and one of its key features is the ability for users to host it anywhere, such as on a virtual private server (VPS). ::: info By default, Caido listens on the IP address 127.0.0.1 and port 8080. This is the recommended configuration as there is currently no native proxy access control. Listening on 127.0.0.1 limits access to the local device only. ::: ## Hosting Caido on a Linux-Based VPS: To access a remote Caido instance, establish an SSH connection between your local device and VPS, and forward traffic bound to the local port to the listening address/port of the remote instance. ```bash ssh -L :127.0.0.1:8080 @ ``` Once the connection is established, you can access the Caido user-interface by navigating to `http://127.0.0.1:` in your web browser. ::: tip If you're using AWS and have [SSM](https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html) configured, you can use port forwarding instead of SSH: ```bash aws ssm start-session \ --target \ --document-name AWS-StartPortForwardingSession \ --parameters '{"portNumber":["8080"],"localPortNumber":[""]}' ``` Example for forwarding local port `9000`: ```bash aws ssm start-session \ --target \ --document-name AWS-StartPortForwardingSession \ --parameters '{"portNumber":["8080"],"localPortNumber":["9000"]}' ``` ::: --- --- url: /app/guides/projects_backups.md description: >- A step-by-step guide to creating and restoring project backups in Caido including backup creation, export, and import functionality. --- # Saving Projects Backups save all of a project's data as a self-contained file. ## Creating Backups To create a backup file, **right-click** on a project's row or **click** on the `...` button and select Create backup from the context menu. Messages will appear notifying you that the operation has been started. A subsequent message will appear once the backup has been created. *** **Click** on the download button in the Backups tab interface to export the file. ## Restoring a Project from a Backup To restore your projects from a backup, **click** the `Restore` button within the Backups tab interface or **click** on the Import button within the Projects tab interface and select a `.caidobak` file. --- --- url: /app/tutorials/scanner.md description: >- Learn how to configure and use the Scanner plugin for automated vulnerability detection, including passive and active scanning with template-based checks. --- # Scanner The [Scanner](https://github.com/caido-community/scanner) is Caido's official vulnerability detection engine that brings automated security testing capabilities to Caido. In this tutorial, you will learn how to configure the plugin to conduct both passive and active scanning. ::: info The Scanner is available for [installation](/app/guides/plugins_installing.md) in the `Official` tab of the Plugin interface. ::: The Scanner engine detects vulnerabilities with templates that are referred to as "checks". Each check contains the logical process for identifying specific security issues. ## Checks ::: tip [Learn how to create your own check templates.](https://github.com/caido-community/scanner#%E2%80%8D-developer-documentation) ::: To view the available checks, navigate to the Scanner plugin interface and **click** on the `Checks` tab. Each check is listed as a table row. A check's metadata information, including a description of the vulnerability tested for and categorical tags, can be viewed by **clicking** on the button attached to its row. The metadata also includes a check's: * `Type`: Passive type checks are silent enough to run in the background without causing noise. Active type checks require more noticible interaction with the target. * `Aggressivity`: The number of requests that are generated and sent. ## Selecting Checks The Scanner plugin runs checks either passively as traffic is proxied through Caido or actively against manually selected requests. To include or exclude a check in either passive or active scanning, **click** on it's associated checkbox in the `Passive` or `Active` column. ### Check Presets Predefined selections of passive and active checks are available as check presets. To save your current selection of checks as a custom preset, **click** on the `+ New Preset` button. ## Passive Scanning By default, once the Scanner plugin is installed, passive scanning is enabled against in-scope proxied traffic. To disable passive scanning or apply it to all proxied traffic, navigate to the `Settings` tab interface. This interface also includes rate limiting options and allows you to select the vulnerability severity levels that should generate [findings](/app/guides/workflows_findings.md) upon detection. ## Active Scanning To execute a scan manually against a specific request **right-click** within a request pane or on a traffic table row, hover your mouse cursor over `Plugins` and `Scanner`, and select Run Active Scanner to open the `Scan Launcher` window. ::: tip To scan multiple requests, either `CTRL` + **click** select multiple rows or select a range of rows with `SHIFT` + **click**. ::: All requests that the scan will be applied to will be listed in the `Targets` tab. Additional configuration options for active scans are available in the `Configuration` tab. Once the active scan is configured, **click** on the Run Scan button to run the enabled active checks. In addition to generating findings, the results of ongoing and completed active scans are available in the `Dashboard` tab interface. ::: tip To interupt an in-progress active scan, **click** on the `Cancel` button. ::: --- --- url: /burp-suite/core/scans.md description: Map Burp Suite Pro Scanner and scan operations to Caido. --- # Scans Burp Suite Pro Scanner, live tasks, and scan operations and their Caido equivalents. ## Available ### Scanner Burp includes an automated vulnerability scanner for passive and active testing. Caido offers the community **Scanner** plugin for automated vulnerability scanning in Caido. Active and passive scanning is provided by this plugin and can be extended with custom checks. #### Resources * [Scanner](https://github.com/caido-community/scanner) (GitHub) * [Scanner Tutorial](/app/tutorials/scanner.md) ### Configuring Scans Burp lets you adjust scan speed, insertion points, and audit checks for Scanner. Caido lets you configure scan behavior through the **Scanner** plugin's custom check definitions and native **Workflows**. Check selection is plugin- and workflow-specific rather than a unified scan configuration UI. #### Resources * [Scanner: Custom Checks](https://github.com/caido-community/scanner#check-definition) (GitHub) * [Workflows](/app/quickstart/workflows.md) ### Running Scans Burp launches full crawl-and-audit or targeted scans against web applications. Caido supports running active scans with the **Scanner** plugin and targeted fuzzing with native **Automate**. Combine both for coverage similar to Burp's integrated scanner. #### Resources * [Scanner](https://github.com/caido-community/scanner) (GitHub) * [Automate](/app/quickstart/automate.md) * [Scanner Tutorial](/app/tutorials/scanner.md) ### Scanning Specific HTTP Messages Burp runs an audit against selected requests rather than an entire site. Caido lets you send selected requests from **HTTP History** to the **Scanner** plugin or **Automate**. This matches Burp's "scan selected items" workflow using Caido's context menu and traffic views. #### Resources * [HTTP History](/app/quickstart/http_history.md) * [Scanner](https://github.com/caido-community/scanner) (GitHub) * [Automate](/app/quickstart/automate.md) ### Viewing Scan Results Burp lets you review discovered issues, audit items, and event logs from scans. Caido lets you review results in native **Findings** and the **Scanner** plugin's results view. Caido centralizes tracked issues in Findings rather than Burp's separate scan issue tabs. #### Resources * [Findings](/app/quickstart/findings.md) * [Scanner](https://github.com/caido-community/scanner) (GitHub) ## Indirectly Available ### Live Tasks Burp runs continuous background crawling and auditing of in-scope traffic as you browse. Caido offers native **Passive Workflows** for real-time traffic analysis as you browse. For active auditing, Caido supports running the **Scanner** plugin against selected requests. Caido does not have a single "live tasks" panel like Burp; background analysis is workflow-driven. #### Resources * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [Workflows](/app/quickstart/workflows.md) * [Scanner](https://github.com/caido-community/scanner) (GitHub) ### Application Logins Burp lets you provide credentials or recorded login sequences so Scanner can test authenticated areas. Caido lets you store credentials in native **Environment Variables**, record login flows manually in **Replay**, and use the **NTLM Authentication** plugin for NTLM-protected applications. Caido does not support Burp-style recorded login sequences or a login configuration library. #### Resources * [Environment Variables](/app/quickstart/environment.md) * [Replay](/app/quickstart/replay.md) * [Automate](/app/quickstart/automate.md) * [Refresh Authentication Tutorial](/app/tutorials/refresh_authentication.md) * [NTLM Authentication](https://github.com/caido-community/ntlm) (GitHub) ## Not Available ### Resource Pools Burp limits concurrent scan threads to control resource usage during scans. Caido has no resource pool for throttling scan concurrency. Throttle **Automate** campaigns manually or add delays in workflows to control request rate. #### Resources * [Avoiding Rate-Limiting Protections](/app/guides/automate_rate_limiting.md) * [Workflows](/app/quickstart/workflows.md) --- --- url: /app/quickstart/scopes.md description: >- A step-by-step guide to Caido's Scopes feature for defining which domains and subdomains to include or exclude from traffic analysis. --- # Scopes The `Scopes` interface gives you the ability to define which domains or subdomains should be included or excluded from Caido traffic tables and operations. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Defining a Scope](/app/guides/scopes_defining.md) * [Applying a Scope](/app/guides/scopes_applying.md) * [Managing Scopes](/app/guides/scopes_managing) ::: --- --- url: /app/quickstart/search.md description: >- A step-by-step guide to Caido's Search interface for finding and analyzing HTTP requests and responses across all proxied traffic. --- # Search The `Search` interface provides a table that contains all of the HTTP requests and their associated responses that have been proxied through or generated by Caido. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Filtering Traffic Table Rows](/app/guides/search_filtering.md) * [Viewing Modifications](/app/guides/search_modifications.md) ::: --- --- url: /app/guides/match_replace_sources.md description: >- A step-by-step guide to selecting the traffic that Match & Replace rules in Caido apply to. --- # Selecting a Traffic Source The options available under the Sources section of the Match & Replace interface determine the traffic the rules will apply to. ::: tip To target specific requests/responses, add [HTTPQL query statements](/app/guides/filters_httpql.md) in the `Condition` input field. ::: * To apply a rule to all proxied requests/responses, **click** on the `Intercept` checkbox. * To apply a rule to all requests generated by Automate sessions, **click** on the `Automate` checkbox. ::: warning NOTE The `Automate` option is not available to response fields. ::: --- --- url: /app/tutorials/discord_notification.md description: >- Learn how to create an active workflow that sends notifications to Discord using webhooks and Caido's HTTP module. --- # Send a Notification to Discord Workflow In this tutorial, we create an active workflow that will send a notification to Discord. We will use Caido's [HTTP Module](https://developer.caido.io/reference/modules/caido/http) which provides an implementation of the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). With this module, you can create and send asynchronous HTTP requests and handle their responses. ::: warning NOTE The request and response objects of this module differ from those used in the [Backend SDK](https://developer.caido.io/reference/sdks/backend/) and [Workflow SDK](https://developer.caido.io/reference/sdks/workflow/). Due to this, their properties and methods differ as well. Additionally, they are not routed through the proxy and must adhere to the HTTP specification in order to be interpreted correctly. ::: ## Creating an Active Workflow To begin, navigate to the Workflows interface, select the `Active` tab, and **click** on the `+ New workflow` button. Next, rename the workflow by typing in the `Name` input field. You can also provide an optional description of the workflow's functionality by typing in the `Description` input field. ## Nodes and Connections Too add nodes to the workflow, **click** on `+ Add Node` button and then the `+ Add` button of a specific node. For this workflow, the overall node layout will be: * The `Active Start` node outputs `$active_start.request` and `$active_start.response` objects which represent proxied requests the workflow was initiated on and their corresponding responses. * The request and response objects will be passed to the `Javascript` node. * Once the request and response objects have been processed by the script in the `Javascript` node, the workflow will end. ## Creating and Sending a Request 1. **Click** on the `Javascript` node to access its editor. 2. Then, **click** within the coding environment, select all of the existing code, and replace it with the following script: ::: warning NOTE Replace `` with the URL of your own [Discord webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks). ::: ```js // Request object under the alias of FetchRequest. import { Request as FetchRequest, fetch } from "caido:http"; export async function run(input, sdk) { // Discord webhook data. const message = { username: "Caido Bot", avatar_url: "https://www.caido.io/images/logo.color.webp", content: "Message from Caido Workflow", embeds: [{ title: "Webhook Fetch Request", description: "Hello World!", color: 14329120, fields: [ { name: "Field A", value: "Value A", inline: true }, { name: "Field B", value: "Value B", inline: true } ], footer: { text: "Sent via Caido" }, timestamp: new Date().toISOString() }] }; // Create a new request to Discord webhook. const fetchRequest = new FetchRequest("", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(message) }); try { const response = await fetch(fetchRequest); // Create response data object. const responseData = { status: response.status, statusText: response.statusText, headers: Object.fromEntries(response.headers.entries()) }; // Log the response data with proper formatting. sdk.console.log("Response data:", JSON.stringify(responseData, null, 2)); // For Discord webhooks, 204 means success. if (response.status === 204) { return "Webhook sent successfully"; } // If not 204, get the error details from response. const errorBody = await response.text(); return `Webhook failed: ${errorBody}`; } catch (error) { return `Error: ${error.message}`; } } ``` 3. Next, ensure the `$active_start.request` and `$active_start.response` objects are [referenced as input data](/app/guides/workflows_references.md). Once these steps are completed, close the editor window and **click** on the `Save` button to update and save the configuration. ## Script Breakdown To be able to send a fetch request, the `Request` class and the `fetch()` function are imported from the `caido:http` module. ```js // Request object under the alias of FetchRequest. import { Request as FetchRequest, fetch } from "caido:http"; ``` Next, an asynchronous function is defined that takes the `input` and the `sdk` interface object as parameters. ```js export async function run(input, sdk) { ``` ::: tip [View this guide for a list of Discord message options.](https://birdie0.github.io/discord-webhooks-guide/discord_webhook.html) ::: The body data of the fetch request is defined as an object and stored in the `message` variable. ```js // Discord webhook data. const message = { username: "Caido Bot", avatar_url: "https://www.caido.io/images/logo.color.webp", content: "Message from Caido Workflow", embeds: [{ title: "Webhook Fetch Request", description: "Hello World!", color: 14329120, fields: [ { name: "Field A", value: "Value A", inline: true }, { name: "Field B", value: "Value B", inline: true } ], footer: { text: "Sent via Caido" }, timestamp: new Date().toISOString() }] }; ``` Then, using `new FetchRequest()` the fetch request is defined, using a Discord Webhook URL as the `input` parameter of the constructor. The HTTP `method`, `headers`, and `body` data are specified in the [RequestOpts](https://developer.caido.io/plugins/reference/modules/caido/http.html#requestopts) object parameter. ```js // Create a new request to Discord webhook. const fetchRequest = new FetchRequest("", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(message) }); ``` Then, `fetch(fetchRequest)` is used to send the constructed request. Since we must wait for the request to be sent and response to be returned, the `await` directive is used. The response is stored in the `response` variable. ```js try { const response = await fetch(fetchRequest); ``` By accessing the `response` object properties, we can print the data to the backend logs. ```js // Create response data object. const responseData = { status: response.status, statusText: response.statusText, headers: Object.fromEntries(response.headers.entries()) }; // Log the response data with proper formatting. sdk.console.log("Response data:", JSON.stringify(responseData, null, 2)); // For Discord webhooks, 204 means success. if (response.status === 204) { return "Webhook sent successfully"; } // If not 204, get the error details from response. const errorBody = await response.text(); return `Webhook failed: ${errorBody}`; } catch (error) { return `Error: ${error.message}`; } } ``` ## Testing the Workflow To test the workflow: 1. **Right-click** on a request to open the context menu. 2. Hover over the `Run workflow` option, and select the workflow. ## The Result You will receive a message in your Discord channel. Within the logs, the message will resemble: ```text 2025-04-09T00:45:25.697833Z INFO main service|workflow: Executing workflow (g:58) as task 2025-04-09T00:45:25.697858Z INFO main service|task: Running task 2025-04-09T00:45:25.697862Z INFO main service|workflow: Workflow (g:58) task assigned ID: 26 2025-04-09T00:45:26.134839Z INFO executor:0|arbiter:7 js|sdk: Response data:, { "status": 204, "statusText": "No Content", "headers": { "date": "Wed, 09 Apr 2025 00:45:26 GMT", "content-type": "text/html; charset=utf-8", "connection": "keep-alive", "set-cookie": "_cfuvid=.E8ALL.xBWASGB1xARc0HgFKDv10bpItHt35AsAKJDE-1744159526028-0.0.1.1-604800000; path=/; domain=.discord.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "x-ratelimit-bucket": "3d2712a9e4fe17cc9d3fed4a8e672e5f", "x-ratelimit-limit": "5", "x-ratelimit-remaining": "4", "x-ratelimit-reset": "1744159527", "x-ratelimit-reset-after": "1", "via": "1.1 google", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", "report-to": "{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=ZIGoTFpSBw9RLoXTZmN0CKYNnESTcIYHDgSl42ygSs1E9uOAgvjN%2FMmks8w9SLiHDAzyu5n8WDyMRHcPiyYa0LkUcpMyXEaoPd0c7HE9rHkCh24fR55k2qRmgTJL\"}],\"group\":\"cf-nel\",\"max_age\":604800}", "nel": "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}", "x-content-type-options": "nosniff", "reporting-endpoints": "csp-sentry=\"https://o64374.ingest.sentry.io/api/5441894/security/?sentry_key=8fbbce30bf5244ec9429546beef21870&sentry_environment=stable\"", "content-security-policy": "frame-ancestors 'none'; default-src https://o64374.ingest.sentry.io; report-to csp-sentry; report-uri https://o64374.ingest.sentry.io/api/5441894/security/?sentry_key=8fbbce30bf5244ec9429546beef21870&sentry_environment=stable", "server": "cloudflare", "cf-ray": "92d5fb4c58d5f7ab-LAX" } } 2025-04-09T00:45:26.135041Z INFO executor:0|arbiter:7 service|task: Task (26) done 2025-04-09T00:45:26.135079Z INFO main service|task: Finishing task 26 ``` --- --- url: /app/guides/replay_requests.md description: >- A step-by-step guide to sending requests from other Caido interfaces to the Replay interface for manual request testing and modification. --- # Sending HTTP Requests to Replay ## ::: tip Video Demonstration You can send HTTP requests from other interfaces to the Replay interface in various ways: * By **right-clicking** on a request row in a traffic table or within a request pane, hovering your mouse cursor over `Send to Replay`, and selecting the Collection to include it in. - Or by selecting a request row or focusing a request pane and using the default keyboard shortcut `CTRL` + `R`. Requests in the Replay interface are referred to as "sessions". Each session is listed as a tab that stores the associated request. Replay sessions can also be created manually by **clicking** on the `+ New Session` button and entering a connection URL. --- --- url: /app/guides/automate_multiple.md description: >- A step-by-step guide to sending multiple payloads in Caido's Automate feature using different strategies like All, Sequential, Parallel, and Matrix combinations. --- # Sending Multiple Payloads To use multiple payload values, **click**, **hold**, and **drag** over multiple request elements you want to replace and then **click** on the `+ Add Placeholder` button. Once placeholders have been marked, select a strategy from the drop-down menu. ## Single Payload Set Strategies Both the `All` and `Sequential` strategies utilize a single payload set. ### All The All strategy will replace all placeholders with the same payload value. | Request | Payload | |---------|-----------------------------------------------------| | 1 | username=`sytten`\&password=`sytten` | | 2 | username=`corb3nik`\&password=`corb3nik` | | 3 | username=`chriscremesure`\&password=`chriscremesure` | ### Sequential The Sequential strategy will switch a payload value between all placeholders. The original values are preserved. | Request | Payload | |---------|---------------------------------------------| | 1 | username=`sytten`\&password=`qwerty` | | 2 | username=`caido`\&password=`sytten` | | 3 | username=`corb3nik`\&password=`qwerty` | | 4 | username=`caido`\&password=`corb3nik` | | 5 | username=`chriscremesure`\&password=`qwerty` | | 6 | username=`caido`\&password=`chriscremesure` | ## Multi-Payload Set Strategies Both the `Parallel` and `Matrix` strategies utilize multiple payload sets. **Click** on a placeholder to define its own payload set. *** *** *** ### Parallel The Parallel strategy will combine payload values across their sets in ascending order. Due to this, each set must have the same payload count. | Request | Payload | |---------|------------------------------------------| | 1 | username=`sytten`\&password=`password` | | 2 | username=`corb3nik`\&password=`admin` | | 3 | username=`chriscremesure`\&password=`123` | ### Matrix The Matrix strategy will test all the possible combinations of payload values across different sets. | Request | Payload | |---------|-----------------------------------------------| | 1 | username=`sytten`\&password=`password` | | 2 | username=`sytten`\&password=`admin` | | 3 | username=`sytten`\&password=`123` | | 4 | username=`corb3nik`\&password=`password` | | 5 | username=`corb3nik`\&password=`admin` | | 6 | username=`corb3nik`\&password=`123` | | 7 | username=`chriscremesure`\&password=`password` | | 8 | username=`chriscremesure`\&password=`admin` | | 9 | username=`chriscremesure`\&password=`123` | ::: info If `Close Connection` is disabled in the `Settings` tab, the TCP connection is maintained through the session until it is terminated by the server. ::: --- --- url: /app/guides/automate_numerical.md description: >- A step-by-step guide to sending numerical payloads in Caido's Automate feature with configurable ranges, increments, and zero-padding options. --- # Sending Numerical Payloads To send numerical payload values, **click**, **hold**, and **drag** over the request element you want to replace and then **click** on the `+ Add Placeholder` button. Once a placeholder has been marked, you will be presented with options in the `Payload` tab. From the `Type` drop-down menu, select the `Numbers` option. This option will present multiple input fields that give you control over the number to start with, the number to end with, the incremental value, and the minimum number of digits to use. ::: tip To account for multi-digit numbers, ensure to set an appropriate value for the `Minimum digits (zero padded)` field. ::: Once the configuration has been made, **click** on the `Run` button to launch the Automate session. A new tab will be generated that contains a traffic table of the payload requests. To view the results of the session, **click** on this paired tab. ::: info If `Close Connection` is disabled in the `Settings` tab, the TCP connection is maintained through the session until it is terminated by the server. ::: --- --- url: /app/guides/automate_wordlists.md description: >- A step-by-step guide to using wordlists in Caido's Automate feature for systematic payload testing with hosted files or simple lists. --- # Sending Payloads from a Wordlist To use a wordlist of payload values, **click**, **hold**, and **drag** over the request element you want to replace and then **click** on the `+ Add Placeholder` button. Once a placeholder has been marked, you will be presented with options in the `Payload` tab. From the `Type` drop-down menu, select either: * `Hosted File`: This option will present a `Selected file` drop-down menu from which you can select a wordlist that you have uploaded to your Caido instance. - `Simple List`: This option will present an input field that allows you to manually type in a wordlist, one payload per new line. You can also load a wordlist file directly by **clicking** on the `Load from file...` button. Once a selection has been made, **click** on the `Run` button to launch the Automate session. A new tab will be generated that contains a traffic table of the payload requests. To view the results of the session, **click** on this paired tab. ::: info If `Close Connection` is disabled in the `Settings` tab, the TCP connection is maintained through the session until it is terminated by the server. ::: --- --- url: /app/guides/automate_requests.md description: >- A step-by-step guide to sending requests from other Caido interfaces to the Automate interface for automated testing and fuzzing campaigns. --- # Sending Requests to Automate You can send requests from other interfaces to the Automate interface in various ways: * By **right-clicking** on a request row in a traffic table or within a request pane and **clicking** `Send to Automate`. - Or by selecting a request row or focusing a request pane and using the default keyboard shortcut `CTRL` + `M`. Requests in the Automate interface are referred to as "sessions". Each session is listed as a tab that stores the associated request. --- --- url: /app/guides/replay_websocket.md description: A step-by-step guide to sending WebSocket messages in Caido's Replay feature. --- # Sending WebSocket Messages To send a WebSocket message in Replay, **click** on the attached to the `+ New Session` button and select WebSocket. Enter a connection URL and **click** on the `Connect` button to create a new WebSocket session. This will send the HTTP upgrade request to the server and establish a WebSocket connection. Once the connection is established, you can send messages to the server by entering text in the input field and **clicking** the button. --- --- url: /app/tutorials/android_physical_device.md description: Learn how to install Android Studio. --- # Setup & Configuration To proceed with the tutorials for a physical device, you will need to download/install Android Studio, the official IDE for developing Android applications. ## Android Studio Android Studio is the official IDE for developing Android applications. It provides tools for building, testing, and debugging apps, and for managing virtual and physical devices. The **Standard** installation includes the **Android SDK** (Software Development Kit), which is the set of libraries, APIs, build tools, and emulator components needed to develop and run Android software. ::: warning NOTE This tutorial was written using: * Android Studio Otter 3 Feature Drop | 2025.2.3 RC 3 January 8, 2026. To download this release visit: We recommend using the same version to ensure the instructions align. ::: Once `Android Studio Otter 3 Feature Drop | 2025.2.3 RC 3 January 8, 2026` has been downloaded for your operating system, launch the installation wizard and select the `Standard` installation type. --- --- url: /app/tutorials/android_virtual_device.md description: Learn how to install Android Studio and create a virtual Android device. --- # Setup & Configuration To proceed with the tutorials for a virtual device, you will need to download/install **Android Studio**. ## Android Studio Android Studio is the official IDE for developing Android applications. It provides tools for building, testing, and debugging apps, and for managing virtual and physical devices. The **Standard** installation includes the **Android SDK** (Software Development Kit), which is the set of libraries, APIs, build tools, and emulator components needed to develop and run Android software. ::: warning NOTE This tutorial was written using: * Android Studio Otter 3 Feature Drop | 2025.2.3 RC 3 January 8, 2026. To download this release visit: We recommend using the same version to ensure the instructions align. ::: Once `Android Studio Otter 3 Feature Drop | 2025.2.3 RC 3 January 8, 2026` has been downloaded for your operating system, launch the installation wizard and select the `Standard` installation type. ## Creating an Android Virtual Device ::: warning NOTE The virtual device tutorials were written using: * API 30 "R"; Android 11.0 * Google APIs Intel x86 Atom System Image System images that include Google Play in their build are signed with a release key and don't allow root access. In order to capture HTTPS traffic generated by an application with Caido, avoid selecting any Google Play builds when creating a virtual device. Additionally, avoid selecting any ATD builds as they do not include a user interface for the device. Instead, use images listed as: * Google APIs * Android Open Source Project (AOSP) * Default Android System Image * Base versions (Android x.x.x ()) ::: Once Android Studio is installed and launched, to create a virtual device: 1. **Click** on the More Actions button and select `Virtual Device Manager`. 2. **Click** on the `+ Create Virtual Device` button. 3. **Click** on the `New hardware profile...` button. 4. Name the device in the **Device Name** input field and continue with the default configuration settings by **clicking** on the `Finish` button. 5. Select the device from the table and **click** on the `Next` button. 6. In the `API` drop-down menu, select `API 30 "R"; Android 11.0`. 7. In the `System Image` table select `Google APIs Intel x86 Atom System Image`. 8) **Click** on the `Finish` button and then the `Yes` button in the **Confirm Download** window. 9) Once the package is installed, click on the `Finish` button. --- --- url: /app/quickstart/setup.md description: >- A step-by-step guide to initial setup for Caido including authentication, instance configuration, and CA certificate import. --- # Setup & Next Steps Once Caido has been launched: 1. **Click** on the `Start` button and log in with your account credentials or create an account. 2. Once you are authenticated, name your [instance](/app/concepts/instance.md) and grant access to your account username, email address, and subscription. ::: info ADDITIONAL OPTIONS `Enable the AI assistant feature`: Available to Individual and Team tier [subscriptions](https://www.caido.io/pricing). `Stay logged-in for an extended period`: Extends the validity of an authenticated session. Both options are enabled by default. However, you can disable either by **clicking** on their checkboxes. ::: 3. Return to Caido and **click** on the `+ Create a project` button. 4. Give the project a name and **click** `+ Create`. 5. Then, continue with the [Importing Caido's CA Certificate](/app/guides/ca_certificate_importing.md) guide. ## What's next? Once you have created your first project and Caido's CA certificate is imported, you'll be ready to start testing web applications for security vulnerabilities. This user documentation will serve as a central knowledge base to help you along the way. ### New to Caido? If you are a new user or want to compare Caido to other web security auditing toolkits, the following `Features Overview` pages give a succinct description of each Caido feature. ### Documentation Overview If you are looking for guidance, technical information, or explanations: * For step-by-step instructions to accomplish common tasks, view the [How-to Guides](/app/guides/). * For hands-on learning experiences that teach you through practical examples, view the [Tutorials](/app/tutorials/). * For detailed technical information on Caido's features and capabilities, view the [Reference](/app/reference/) section. * For explanations of key principles to help you understand how and why Caido works the way it does, view the [Concepts](/app/concepts/) section. * For answers to questions we commonly receive, view the [FAQ](/faq.md). * For resolutions to commonly experienced errors and instructions on how to report a bug, view the [Troubleshooting](/app/troubleshooting/) section. --- --- url: /app/tutorials/shift.md description: Learn how to configure and use the Shift plugin to automate tasks. --- # Shift ## ::: tip Video Demonstration [Shift](https://github.com/caido-community/shift) is Caido's official AI/LLM plugin that can be instructed to automate tasks in your security assessments. In this tutorial, you will learn how to use the plugin's two main components: [Shift Core](#shift-core) and [Shift Agents](#shift-agents). ::: info Shift is available for [installation](/app/guides/plugins_installing.md) in the `Official` tab of the Plugin interface. ::: Shift integrates AI/LLM models directly into Caido's user-interface, making the models context-aware. With access to a variety of tools that can carry out actions within Caido, you can submit prompts, written in natural language, to assign tasks to a model of your choosing such as: ```txt Generate a wordlist of common sensitive files that may be publicly exposed. ``` ```txt Update this request to reflect this JS: ``` ```txt Create a M&R rule to replace the selected text with: isAdmin=true ``` ```txt Find similar requests to this. ``` ::: tip Shift is highly capable and should be able to carry out any task you could do with a well-written prompt. ::: ## Configuration To use Shift, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `AI` tab. Enter your API key for your provider and **click** on the `Verify` button. Within the `Settings` interface of Shift, there are also options to limit the number of API calls a Shift Agent can make and an input field to provide a general system prompt or more contextual information about your target. ## Shift Core With Shift Core, you can provide direct instructions to the model by using the default keyboard shortcut `CTRL` + `SPACE`, typing in a prompt, and pressing `ENTER` or **clicking** on the button. *** ## Shift Agents With Shift Agents, you can assign tasks to a model that will be handled autonomously as background processes. ### Custom Prompts For common tasks, you can create and save reusable prompts by **clicking** on the `+ Add prompt` button within the `Custom Prompts` tab. ::: warning NOTE When writing custom prompts, provide detailed information and guidelines for the model to follow, such as: * The root cause of the vulnerability. * An example of its secure implementation. * Example payloads or exploitation techniques. * Examples of commonly vulnerable endpoints or components. * Indications of successful exploitation. * Resources to target after successful exploitation. * Edge cases and similar vulnerabilities. * Common testing mistakes that may produce false positives. ::: ::: tip [View how the default custom prompts are written as a reference.](https://github.com/caido-community/shift/blob/87aa9f1fef55af5b7e4ced5e2c848a428ad23182/packages/frontend/src/stores/config/prompts.ts) ::: To use a custom prompt, **click** on the `+` button within the message input field, select the prompt by name, and reference it in the message. *** ## AI Session Renaming Shift is also able to automatically rename Replay session tabs from their numerical names to descriptive names that identify the purpose of the request. To enable this feature, and configure additional settings, navigate to the `AI Session Renaming` tab. --- --- url: /app/quickstart/sitemap.md description: >- A step-by-step guide to Caido's Sitemap interface for visualizing target file systems and domain structures from proxied traffic. --- # Sitemap As you proxy traffic through Caido, the content you access across domains and subdomains and will be presented as a hierarchal, tree-like structures within the `Sitemap` interface, providing you with a visual representation of a target's file system. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Viewing a Sitemap](/app/guides/sitemap_viewing.md) * [Deleting a Sitemap](/app/guides/sitemap_deleting.md) ::: --- --- url: /app/guides/sorting.md description: >- A step-by-step guide to sorting traffic table rows in Caido by clicking column names to toggle listing order for better data organization. --- # Sorting Traffic Table Rows To determine which traffic table columns you can sort rows by, hover your mouse cursor over the column names. If your cursor becomes a hand icon , you can toggle the listing order of a table by **clicking** a column's name. --- --- url: /app/troubleshooting/startup.md description: >- Troubleshooting Caido startup issues including unreachable instances, connection errors, and configuration problems. --- # Startup Issues ## "Instance is unreachable" This error may occur when a Caido subprocess has failed to spawn. If you encounter this error message after attempting to launch a Caido instance, enable safe mode to disable either the frontend or backend component of a plugin and recover the instance. To disable the frontend component of a plugin, access Caido in your browser by navigating to . In the Plugins interface, open the `Installed` tab, and **click** on the button attached to a plugin row to expand the component settings. Then, **click** on the frontend component checkbox to remove its fill. To disable the backend component of a plugin, launch Caido with the `--safe` command-line option. ```bash caido --safe ``` ## "Encountered an error when communicating with the destination server" This error may occur when your proxy settings are misconfigured. ```text Encountered an error when communicating with the destination server Failed to acquire connection Caused by: 0: Failed to perform TLS handshake 1: error:1408F10B:SSL routines:ssl3_get_record:wrong version number:ssl/record/ssl3_record:c:332 ``` If you encounter this error message while proxying traffic through Caido, check your proxy settings and ensure the `Type` is set to HTTP. ## "Could not initialize configuration" This error may occur due to internet connection issues. Caido requires an internet connection on first launch, during login, and after 7 days offline (*the time period after which your authentication token needs to be refreshed*). ```text Error: Could not initialize configuration Caused by: 0: Authentication service error 1: Cloud operation failed 2: Cloud unavailable 3: error sending request for url (https://api.caido.io/oauth2/register): error trying to connect: tcp connect error: Connection refused (os error 111) 4: error trying to connect: tcp connect error: Connection refused (os error 111) 5: tcp connect error: Connection refused (os error 111) 6: Connection refused (os error 111) ``` If you encounter this error message, check your internet connection. ## Launching Caido on Arch Linux with Hyprland If you are unable to launch Caido on Arch with Hyprland, it may be due to a lack of support for Electron applications. Install XWayland to allow X11 applications to run in a Wayland environment. ```bash sudo pacman -S xorg-xwayland ``` Then, launch Caido through XWayland. ```bash env ELECTRON_OZONE_PLATFORM_HINT=x11 ./caido ``` ## Blank Screen If you encounter a blank screen in the desktop application, launch Caido with the `--disable-gpu` command-line option. ```bash caido --disable-gpu ``` --- --- url: /app/reference/streamql.md description: >- Find detailed reference information on StreamQL query language used in Caido for filtering WebSocket messages with namespaces, fields, and operators. --- # StreamQL StreamQL is the query language used in Caido that gives you the ability to filter WebSocket messages. The constructing primitives of a StreamQL query statement, in order of position, are the: 1. [Namespace](#namespaces) 2. [Field](#fields) 3. [Operator](#operators) 4. [Value](#values) ## Namespaces ::: info Namespaces are project-specific. ::: | Namespace | Description | |-----------|-------------| | `ws` | All WebSocket traffic. | | `stream` | All stream messages. | | `preset` | Filter presets. | ::: warning NOTE The `preset` namespace does not have any fields available and instead takes a direct value of a [filter preset's](/app/guides/filters_defining.md) name/alias. ::: ## Fields ### ws | Available Fields | Description | Value Type | |------------------|-------------|------------| | `created_at` | The date and time the message was sent. | Date/Time: [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) (`2024-06-24T17:03:48+00:00`) / [ISO 8601](https://datatracker.ietf.org/doc/html/rfc3339#appendix-A) (`2024-06-24T17:03:48+0000`) / [RFC2822](https://datatracker.ietf.org/doc/html/rfc2822) (`Mon, 24 Jun 2024 17:03:48 +0000`) / [RFC7231](https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.2) (`Mon, 24 Jun 2024 17:03:48 GMT`) / [ISO9075](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_get-format) (`2024-06-24T17:03:48Z`) | | `direction` | The direction of the message. | String/Byte: `server`/`client` | | `format` | The message type. | String/Byte: `Binary`, `Text`, `Close`, `Ping`, `Pong` | | `len` | The message size in bytes. | Integer | | `raw` | The full raw data of the message. | String/Byte | ### stream | Available Fields | Description | Value Type | |------------------|-------------|------------| | `host` | The hostname of the destination server. | String/Byte | | `path` | The URL path. | String/Byte | | `port` | The port of the destination server. | Integer | | `protocol` | The protocol of the destination server. | String/Byte | | `source` | The Caido feature source of the stream message. | String/Byte | | `tls` | If the connection used TLS/SSL encryption. | Boolean (`true`/`false`) | ## Operators | Operator | Description | Value Type | Additional Details | |----------|-------------|------------|-------------------| | `eq` | Equal to the supplied value. | String/Byte, Integer | Case sensitive. | | `gt` | Greater than the supplied value. | Date/Time, Integer | | | `gte` | Greater than or equal to the supplied value. | Integer | | | `lt` | Less than the supplied value. | Date/Time, Integer | | | `lte` | Less than or equal to the supplied value. | Integer | | | `ne` | Not equal to the supplied value. | String/Byte, Integer | Case sensitive. | | `cont` | Contains the supplied value. | String/Byte | Case insensitive. | | `like` | The [SQLite LIKE Operator](https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators). | String/Byte | Case sensitive for Unicode characters beyond the ASCII range. | | `ncont` | Does not contain the supplied value. | String/Byte | Case insensitive. | | `nlike` | The [SQLite NOT LIKE Operator](https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators). | String/Byte | Case sensitive for Unicode characters beyond the ASCII range. | | `regex` | Matches to the regular expression. | String/Byte | Rust-flavored syntax. | | `nregex` | Does not match to the regular expression. | String/Byte | Rust-flavored syntax. | ::: tip In SQLite - the `%` character matches zero or more characters (*`%.js` matches `.map.js`*) and the `_` character matches one character (*`v_lue` matches `vAlue`*). Visit and select **Rust** syntax to test regular expressions. ::: ::: warning NOTE Not all regex features are currently supported by Caido (*such as look-ahead expressions*) as they are not included in the regex library of Rust. ::: ## Values ### preset | Available Values | Example | |------------------|---------| | A filter preset's alias. | `preset:"no-health-check"` | | A filter preset's name. | `preset:"No Health Check"` | ### source | Available Values | Additional Details | Example | |------------------|--------------------|---------| | `automate`, `intercept`, `plugin`, `replay`, `workflow` | Requires lowercase. Autocomplete is not supported. | `stream.source.eq:"intercept"` | ## Combining Statements Query statements can be combined together using logical operators and logical grouping. ### Logical Operators | Operator | Description | |----------|-------------| | AND | Both the left and right clauses must be true. | | OR | Either the left or right clause must be true. | ::: info Operators are case insensitive. Both have the **same priority**. ::: ### Logical Grouping Caido supports the priority of operations: `AND` has a higher priority than `OR`. * ` AND OR ` is equivalent to `(( AND ) OR )`. * ` OR AND ` is equivalent to `( OR ( AND ))`. * ` AND AND ` is equivalent to `(( AND ) AND )`. ::: tip While parentheses are optional, we recommend using them to make your logical grouping clear. ::: ## Comments Caido supports both single-line and multi-line comments in StreamQL queries. ::: tip Comments can be used to write descriptions or temporarily disable certain query statements. ::: --- --- url: /app/troubleshooting/report_bug.md description: >- A step-by-step guide to reporting bugs in Caido including log collection, reproduction steps, and GitHub issue submission. --- # Submitting a Report To report a bug or receive support, please contact a member of the Caido team by submitting a [contact form](https://www.caido.io/contact) or [send us a message on Discord](https://links.caido.io/www-discord) and be prepared to provide the following resources/information. ::: tip Your issue may already be known, resolved, or a feature request has been made! Search for it here: * [Github Issues](https://github.com/caido/caido/issues) ::: ## Setup Information We will typically need the following information for every case. Please provide us with your: * Operating system. * Version number/name. * Caido client in use (*CLI/desktop application/web application*). * The version of Caido in use. * Both [log files](/app/guides/logs_viewing.md) that include the issue. ::: tip EXAMPLE I am using: * **OS:** Mac OS * **OS Version:** 12 (Monterey) * **Caido Client:** Caido Desktop * **Caido Version:** 0.33.0 ::: ## Log Files As Caido utilizes a [client/server architecture](/app/concepts/instance.md), both frontend and backend logs are produced. ::: danger As log files can contain sensitive information, only send them in private conversations with a verified member of the Caido team. If you are contacting us on Discord, we will open a private channel before asking for logs. ::: ::: warning NOTE Ensure to [enable debug mode](/app/troubleshooting/debugging.md) to assist with troubleshooting. ::: ### Backend Logs To obtain the backend log files of your instance, navigate to the `/logs` subdirectory of the data storage directory. The default location of this directory is dependent on your operating system: | OS | Location | | ------- | ------------------------------------------------ | | Linux | `~/.local/share/caido` | | MacOS | `~/Library/Application\ Support/io.caido.Caido/` | | Windows | `%APPDATA%\caido\Caido\data` | ### Frontend Logs To obtain the frontend logs, either: * Access the DevTools interface by pressing the `F12` key, using the keybinding `CTRL` + `SHIFT` + `I`, or selecting `Inspect` from the **right-click** context menu. Within the `Console` **right-click** and select `Save as...`/`Save all Messages to File`/etc. to export the messages as a `.log` file. * **Click** on the Logs button at the bottom of the Caido user-interface, record your activity, and then **click** on the button to export the messages as a `.log` file. * Press the `ALT` key to open the menu bar, **click** on `View`, and select `Toggle Developer Tools`. ## Steps to Reproduce In order to assist you, it is **critical** that you provide a detailed timeline of the exact steps you took leading up to the bug. This ensures we are able to reproduce the issue in an accurate and timely manner. ::: tip EXAMPLE To reproduce the bug, follow these steps: 1. In the `Intercept` interface, **click** on the `Response` button. 2. Begin intercepting responses, by **clicking** on the Forwarding button to toggle it to Queuing. 3. In a terminal, execute `curl -x 127.0.0.1:8080 https://example.com`. 4. Modify status code of the intercepted response. 5. **Click** the `Forward` button. 6. Confirm in terminal that the response was not modified. ::: ## Submit a Github Issue ::: danger Ensure to remove/redact any sensitive information in submissions. ::: Feel free to [create a new issue](https://github.com/caido/caido/issues/new?assignees=\&labels=\&projects=\&template=bug.md\&title=) on Github. For simplicity, a template is provided with sections to provide all the necessary information. --- --- url: /app/quickstart/support.md description: >- A step-by-step guide to Caido support resources including GitHub issues, troubleshooting guides, and Discord community access. --- # Support ## Github: Issues and Roadmap Your issue may already be known, resolved, or a feature request has been made! Search for it here: * [Github Issues](https://github.com/caido/caido/issues) View the roadmap to stay up-to-date with Caido's development here: * [Roadmap](https://github.com/orgs/caido/projects) ## Caido on Discord With an active community and constant discussion, feel free to ask any questions! [Join Caido's Discord server!](https://links.caido.io/www-discord) --- --- url: /burp-suite/core/target-and-scope.md description: Map Burp Suite Pro Target and Scope features to Caido. --- # Target & Scope Burp Suite Pro target management, site map, and scope features and their Caido equivalents. ## Available ### Target Burp provides a view of in-scope hosts, site structure, and discovered content. Caido splits target management across native **Sitemap**, **Scopes**, and **Findings** rather than a single Target tab. Sitemap shows discovered structure, Scopes define what is in bounds, and Findings tracks notable items — together covering Burp Target's role. #### Resources * [Sitemap](/app/quickstart/sitemap.md) * [Scopes](/app/quickstart/scopes.md) * [Findings](/app/quickstart/findings.md) ### Sitemap Burp displays a tree view of discovered hosts, directories, and endpoints. Caido offers native **Sitemap** that displays discovered hosts and endpoints in a tree view. It is populated from proxied traffic; the **Crawler** community plugin can automate discovery to extend the sitemap beyond manual browsing. #### Resources * [Sitemap](/app/quickstart/sitemap.md) * [Viewing the Sitemap](/app/guides/sitemap_viewing.md) * [Crawler](https://github.com/caido-community/crawler) (GitHub) ### Scope Burp lets you define which hosts and URLs are in scope for testing. Caido offers native **Scopes** to define in-scope hosts. Scoped traffic can be highlighted and filtered across views, similar to Burp's scope configuration. #### Resources * [Scopes](/app/quickstart/scopes.md) * [Defining Scopes](/app/guides/scopes_defining.md) * [Applying Scopes](/app/guides/scopes_applying.md) ### Issue Definitions Burp lets you customize how Scanner reports and categorizes issue types. Caido lets you define custom finding types through the **Scanner** plugin's custom check definitions. Custom issue types are plugin-driven rather than a built-in editor. #### Resources * [Scanner: Custom Checks](https://github.com/caido-community/scanner#check-definition) (GitHub) ## Indirectly Available ### Crawl Paths Burp visualizes how its crawler reached specific endpoints. Caido has no crawl-path visualization like Burp's crawler tree. Caido lets you review discovered endpoints in **Sitemap**, run the **Crawler** plugin for automated discovery, or use **Workflows** for custom crawling logic. #### Resources * [Sitemap](/app/quickstart/sitemap.md) * [Workflows](/app/quickstart/workflows.md) * [Crawler](https://github.com/caido-community/crawler) (GitHub) --- --- url: /app/guides/match_replace_testing.md description: >- A step-by-step guide to testing Match & Replace rules in Caido using the Test button and rule ordering for proper traffic modification. --- # Testing Rules ::: warning NOTE If your rule is not working, ensure you're viewing and matching data as it is actually sent by **clicking** on the `Raw` button above a HTTP request or response. ::: To ensure your rules achieve the desired outcome, you can test them against content inside the `Before` editor by **clicking** on the `Test` button. Applied rules are listed in the `Active Rules` list and will be applied in top to bottom order. To avoid collisions between rules, you can rearrange their order by **left-clicking**, **dragging**, **holding**, and **releasing** a rule either above or below other rules in the list. --- --- url: /burp-suite/core/tools.md description: Map Burp Suite Pro tools to Caido equivalents. --- # Tools Burp Suite Pro tools — Proxy, Repeater, Intruder, utilities, and related features — and their Caido equivalents. ## Available ### Command Palette Burp provides a quick-access launcher for tools, settings, and actions via the keyboard. Caido includes a native command palette opened with `Ctrl/Cmd+K`. It exposes navigation, plugin commands, and shortcuts rather than Burp's tool-centric launcher, but serves the same quick-access purpose. #### Resources * [Command Shortcuts](/app/reference/command_shortcuts.md) ### Search Burp provides global search across its tools for requests, issues, and configuration. Caido offers native **Search** with **HTTPQL** to query captured traffic across your project. Search replaces Burp's cross-tool search with a traffic-focused query language rather than a unified issue-and-config index. #### Resources * [Search](/app/quickstart/search.md) * [HTTPQL](/app/reference/httpql.md) * [Search Filtering](/app/guides/search_filtering.md) ### Context Menu Burp offers right-click actions on requests, responses, and site map entries. Caido provides native context menu actions on requests and responses in HTTP History, Replay, and related views. Available actions depend on the current view and installed plugins. #### Resources * [Context Menu Options](/app/reference/context_menu.md) ### Filter Settings Burp applies shared filter configuration across its tables and views. Caido offers native **Filters** that apply across traffic tables and can be combined with HTTPQL. Filters are view-scoped rather than a single global filter profile shared by every Burp tool. #### Resources * [Filters](/app/quickstart/filters.md) * [Applying Filters](/app/guides/filters_applying.md) * [Defining Filters](/app/guides/filters_defining.md) ### Proxy Burp captures HTTP/S traffic through an intercepting proxy between your browser and target applications. Caido offers native **Intercept** and **HTTP History** to handle proxied traffic capture. Intercept pauses traffic for review; HTTP History stores the full log. Together they cover Burp Proxy's core workflow without a separate Proxy tool tab. #### Resources * [Intercept](/app/quickstart/intercept.md) * [HTTP History](/app/quickstart/http_history.md) * [Intercepting Traffic](/app/guides/intercept_traffic.md) ### Proxy Intercept Burp lets you pause, inspect, and modify individual requests and responses in flight. Caido offers native **Intercept** to pause, inspect, and forward or drop individual requests and responses. Behavior matches Burp's intercept queue, integrated into Caido's main traffic workflow. #### Resources * [Intercept](/app/quickstart/intercept.md) * [Intercepting Traffic](/app/guides/intercept_traffic.md) ### HTTP History Burp maintains a persistent log of all proxied HTTP traffic with filtering and search. Caido offers native **HTTP History** as the persistent traffic log. It supports filtering, search, and sending entries to Replay or Automate. It is the primary workspace for reviewing proxied HTTP traffic. #### Resources * [HTTP History](/app/quickstart/http_history.md) * [Filtering HTTP History](/app/guides/http_history_filtering.md) ### WebSockets History Burp captures and inspects WebSocket messages proxied through the proxy. Caido offers native **WS History** to capture WebSocket frames proxied through the instance. It provides a dedicated view for WebSocket traffic separate from HTTP History. #### Resources * [WS History](/app/quickstart/ws_history.md) ### Match and Replace Burp automatically modifies requests or responses matching defined rules as they pass through the proxy. Caido offers native **Match & Replace** to apply rules to traffic in transit, similar to Burp's match-and-replace rules. Rules can target requests, responses, and specific scopes. #### Resources * [Match & Replace](/app/quickstart/match_replace.md) * [Match & Replace Reference](/app/reference/match_replace.md) * [Testing Match & Replace Rules](/app/guides/match_replace_testing.md) ### Repeater Burp lets you manually modify and resend individual HTTP requests to observe response changes. Caido offers native **Replay** to edit and resend individual requests. Replay is accessed from HTTP History and the context menu rather than a dedicated Repeater tab, but supports the same manual request manipulation workflow. #### Resources * [Replay](/app/quickstart/replay.md) * [Resending Requests](/app/guides/replay_resending.md) * [Sending Requests to Replay](/app/guides/replay_requests.md) ### Intruder Burp performs automated payload injection for fuzzing, brute-forcing, and enumeration attacks. Caido offers native **Automate** for payload-based attacks. Automate supports wordlists, numeric ranges, multiple payload sets, and preprocessors — covering Burp Intruder's core fuzzing and brute-force workflows with a different UI model. #### Resources * [Automate](/app/quickstart/automate.md) * [Sending Requests to Automate](/app/guides/automate_requests.md) * [Sending Payloads from a Wordlist](/app/guides/automate_wordlists.md) ### Inspector Burp provides a structured view of request and response components (headers, parameters, cookies). Caido does not have a separate Inspector panel. Request and response components are edited inline in **Replay**, **HTTP History**, and **Automate** using built-in structured editors. Headers, parameters, and cookies are accessible without switching to a dedicated tool. #### Resources * [Replay](/app/quickstart/replay.md) * [HTTP History](/app/quickstart/http_history.md) ### Message Editor Burp lets you edit HTTP messages in raw and parsed form across its tools. Caido builds native message editors into **Replay**, **Intercept**, and **Automate**. You can switch between structured and raw editing within each view rather than using a shared editor component across separate Burp tabs. The **Hex** community plugin adds hex view and edit modes in HTTP History and Replay. #### Resources * [Replay](/app/quickstart/replay.md) * [Intercept](/app/quickstart/intercept.md) * [Automate](/app/quickstart/automate.md) * [Request and Response Modes](/app/guides/request_response_modes.md) * [Hex](https://github.com/hahwul/Hex) (GitHub) ### Decoder Burp encodes, decodes, and hashes data in common formats. Caido offers native **Convert Workflows** to transform data between formats. The **Convert Tools** community plugin adds a Decoder-like toolbox for on-demand encoding, decoding, and format conversion. Unlike Burp's standalone Decoder tab, Caido combines workflow-driven conversion with optional plugin utilities. #### Resources * [Convert Workflows](/app/concepts/workflows_intro.md#convert-workflows) * [Workflows](/app/quickstart/workflows.md) * [Convert Tools](https://github.com/caido-community/convert-tools) (GitHub) ### Comparer Burp compares requests, responses, and arbitrary data with word-level and byte-level diffing. Caido offers the community **Compare** plugin to diff requests and responses. Caido does not ship a native Comparer tab; diffing is handled by a dedicated plugin. #### Resources * [Compare](https://github.com/caido-community/Compare) (GitHub) ### Sequencer Sequencer analyzes the randomness of session tokens and CSRF tokens. Caido offers the **Sequencer** community plugin to collect tokens from traffic and run statistical randomness tests, similar to Burp Sequencer. Install it from the Community Store in **Plugins**. #### Resources * [Sequencer](https://github.com/caido-community/sequencer) (GitHub) * [Installing Plugins](/app/guides/plugins_installing.md) ### Collaborator Burp includes an out-of-band interaction server for detecting blind SSRF, XXE, and similar vulnerabilities. Caido supports out-of-band interaction testing through community plugins such as **QuickSSRF**, **OmniOAST**, or **SLCyber Tools** (Surf for SSRF). Caido does not ship a built-in Collaborator server; dedicated plugins provide the same capability. #### Resources * [QuickSSRF](https://github.com/caido-community/quickssrf) (GitHub) * [OmniOAST](https://github.com/hahwul/OmniOAST) (GitHub) * [SLCyber Tools](https://github.com/caido-community/slcyber-tools) (GitHub) ### Logger Burp captures and reviews traffic from all tools in a unified log. Caido offers native **Search** that queries all captured traffic across the project, covering much of Burp Logger's review workflow. Caido also supports enhanced logging with custom fields through the **Cerebrum** plugin. #### Resources * [Search](/app/quickstart/search.md) * [Search Filtering](/app/guides/search_filtering.md) * [Cerebrum](https://github.com/DewSecOff/Caido-Plugin-Cerebrum) (GitHub) ### Organizer Organizer stores and annotates interesting requests for later review. Caido offers native **Findings** to track notable requests and issues. Findings serves a similar annotation and review purpose to Burp Organizer, tied to Caido's findings model rather than a separate request collection. #### Resources * [Findings](/app/quickstart/findings.md) ### Content Discovery Burp brute-forces hidden directories and files on a web server. Caido offers native **Automate** with wordlists to brute-force paths and files, and the **Crawler** community plugin for automated sitemap and endpoint discovery. Together they cover Burp's content discovery and crawl-driven enumeration workflows. #### Resources * [Automate](/app/quickstart/automate.md) * [Sending Payloads from a Wordlist](/app/guides/automate_wordlists.md) * [Crawler](https://github.com/caido-community/crawler) (GitHub) ### Generate CSRF PoC Burp builds cross-site request forgery proof-of-concept HTML from captured requests. Caido offers the **CSRF PoC Generator** community plugin to build CSRF proof-of-concept HTML from captured requests. Install it from the Community Store and generate PoCs from HTTP History or Replay. #### Resources * [CSRF PoC Generator](https://github.com/BugBountyzip/CaidoCSRF) (GitHub) ## Indirectly Available ### Dashboard Burp provides a central hub that shows scan progress, issue summaries, and task status. Caido does not have a single dashboard tab. Instead, traffic-centric views like HTTP History and Search are the default workspace, and some community plugins ship their own dashboard pages for scanning or authorization testing. #### Resources * [Plugins](/app/quickstart/plugins.md) * [Scanner](https://github.com/caido-community/scanner) (GitHub) * [Autorize](https://github.com/caido-community/autorize) (GitHub) ### Customizing Burp's Layout Burp lets you rearrange tabs, split panes, and customize the UI layout. Caido has a fixed application layout and does not support Burp-style tab rearrangement. For custom views, community plugins can add dedicated pages through the plugin SDK. #### Resources * [Creating a Page](https://developer.caido.io/guides/page.html) (developer docs) ### Engagement Tools Burp bundles a suite of utilities for target analysis, content discovery, and PoC generation. Caido does not bundle engagement utilities into a single tool suite. Equivalent workflows are spread across native features like **Sitemap** and **Automate**, plus purpose-built plugins such as **Exploit Generator**, **CSRF PoC Generator**, and **Crawler**. #### Resources * [Sitemap](/app/quickstart/sitemap.md) * [Automate](/app/quickstart/automate.md) * [Exploit Generator](https://github.com/stealthcopter/CaidoExploitGenerator) (GitHub) * [CSRF PoC Generator](https://github.com/BugBountyzip/CaidoCSRF) (GitHub) * [Crawler](https://github.com/caido-community/crawler) (GitHub) ### Target Analyzer Target analyzer summarizes a target's technology stack, content types, and dynamic URLs. Caido has no dedicated target analyzer. Caido lets you review technology hints in **HTTP History** responses, use passive workflows to flag stack indicators, and install plugins such as **JS Analyzer** or **RetireJS Scanner** for JavaScript and library analysis on captured traffic. #### Resources * [HTTP History](/app/quickstart/http_history.md) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [JS Analyzer](https://github.com/caido-community/JS-Analyzer) (GitHub) * [RetireJS Scanner](https://github.com/bensh/caido-retirejs) (GitHub) ### Manual Testing Simulator The manual testing simulator simulates user interactions for manual testing scenarios. Caido offers native **Replay** for manual request-level testing, or a **preconfigured browser** for browser-based interaction. The **PwnFox** plugin integrates multi-container browser profiles for parallel sessions. Caido does not ship a dedicated interaction simulator like Burp's manual testing simulator. #### Resources * [Replay](/app/quickstart/replay.md) * [Using a Preconfigured Browser](/app/guides/preconfigured_browser.md) * [PwnFox](https://github.com/caido-community/pwnfox) (GitHub) ### DOM Invader Burp supports browser-based testing for DOM XSS, prototype pollution, and web message vulnerabilities. Caido has no built-in DOM Invader equivalent. The **DOMLogger++** plugin pairs with a browser extension to monitor and debug JavaScript sinks using customizable rules — partial coverage for DOM-focused testing, not Burp's full in-browser attack surface. #### Resources * [Replay](/app/quickstart/replay.md) * [Passive Workflows](/app/concepts/workflows_intro.md#passive-workflows) * [DOMLogger++](https://github.com/kevin-mizu/domloggerpp-caido) (GitHub) ## Not Available ### Clickbandit Clickbandit generates clickjacking proof-of-concept overlays against a target page. Caido has no clickjacking PoC generator. Build PoCs manually with HTML iframes and verify framing protections by replaying requests and inspecting response headers. #### Resources * [Replay](/app/quickstart/replay.md) ### Infiltrator Infiltrator modifies compiled class files to test deserialization and injection in Java applications. Caido has no equivalent to Infiltrator's bytecode manipulation. Use external Java instrumentation tools for class-level testing and Caido's Replay for HTTP-level request manipulation. #### Resources * [Replay](/app/quickstart/replay.md) --- --- url: /app/concepts/traffic_splitting.md description: >- Understand the core concepts behind Caido's traffic splitting algorithm routes requests between proxy forwarding and UI/API, including upstream determination logic. --- # Traffic Splitting By default, Caido listens for all traffic on a single port and uses a splitting algorithm to determine if requests are either: * [GraphQL](/app/concepts/graphql.md) API operations resulting from interactions with the Caido GUI (*client component*). * Intended to be forwarded to a destination server. ## Traffic Split Algorithm The following diagram is a representation of the algorithm that is used to route a request to the correct component. ::: warning NOTE When Caido listens on a specific IP address like `127.0.0.1:8080`, the request's host and port must match the connection URL exactly for the algorithm to route it correctly. Complications arise when listening on all interfaces (`0.0.0.0:8080`), as the matching behavior depends on which network interface the request arrives on. In Docker setups with port forwarding (e.g., `docker run -p 8084:8080 caido/caido:latest`), the connection URL inside the container may be `172.17.0.2:8080`, but clients connect to `127.0.0.1:8084`. Since the IP addresses and ports don't match, requests may be incorrectly routed. In these cases, use [specific listeners](/app/guides/listening_ports.md) to separate proxying from the API to ensure proper routing. ::: ```mermaid flowchart TD Request --> TLS{{Is TLS Client Hello?}} TLS --Yes --> InvisibleTLS{{Is Invisible Proxying?}} TLS --No --> HTTP{{Is HTTP Request?}} InvisibleTLS --Yes --> Proxy InvisibleTLS --No --> API HTTP ---->|No| Kill[Kill Connection] HTTP --Yes --> Connect{{Is CONNECT Method?}} Connect --Yes --> Proxy Connect --No --> Tunnel{{Host/Port in URI?
Default Port: Scheme}} Tunnel --Yes --> DNS{{Host IP/Port Matches Caido Listener?}} Tunnel --No --> Direct{{Host/Port in Header?
Default Port: 80}} Direct ---->|No| Kill Direct --Yes --> InvisibleHttp{{Is Invisible Proxying?}} InvisibleHttp --No --> API InvisibleHttp --Yes --> DNS DNS --Yes --> API DNS --No --> Proxy ``` ### Is TLS Client Hello? The subsequent request is assumed to be intended for a destination server since the API is not accessible via a TCP/TLS connection using `https://`. ### Is CONNECT Method? **Yes**: The request is generated by a [proxy-aware](/app/concepts/web_traffic.md#proxy-aware-clients) client. Caido establishes TCP/TLS connections with both the client and the destination server. **No**: The request's intended recipient requires further evaluation. ### Host/Port in URI? ```http GET http://www.google.com/ HTTP/1.1 ``` If no port is specified, the schema default is used: * `http://`: 80 * `https://`: 443 ### Host/Port in Header? ```http GET / HTTP/1.1 Host: 127.0.0.1:8080 ``` ```http GET / HTTP/1.1 Host: www.google.com ``` If no port is specified, the default is 80. ### Host IP/Port Matches Caido Listener? The host and port is then compared against the IP and port of Caido's listening address. | Request | Listening Address | Destination | Response | Error | |---------|--------------------|-------------|----------|----------| | GET `http://www.google.com/` HTTP/1.1 | `127.0.0.1:8080` | Proxy | 200 OK | | | GET `http://www.google.com/` HTTP/1.1 Host: 127.0.0.1 | `127.0.0.1:8080` | Proxy | 301 Moved Permanently Location: `http://www.google.com/` | | | GET `http://www.google.com/` HTTP/1.1 Host: 127.0.0.1:8080 | `127.0.0.1:8080` | Proxy | 301 Moved Permanently Location: `http://www.google.com:8080/` | Failed to connect: www.google.com:8080 | | GET `http://127.0.0.1:8080/` HTTP/1.1 | `127.0.0.1:8080` | API | 200 OK | | | GET `http://127.0.0.1:8080/` HTTP/1.1 Host: www.google.com | `127.0.0.1:8080` | API | 403 Forbidden | Host/IP is not allowed to connect to Caido *View the [Domain Allowlist](/app/guides/domain_allowlist.md) guide.* | | GET / HTTP/1.1 Host: 127.0.0.1:8080 | `127.0.0.1:8080` | API | 200 OK | | | GET / HTTP/1.1 Host: 127.0.0.1 | `127.0.0.1:8080` | API | 502 Bad Gateway | Failed to connect: 127.0.0.1:80 | | GET / HTTP/1.1 Host: www.google.com | `127.0.0.1:8080` | Proxy | 200 OK | | If [invisible proxying](/app/tutorials/invisible_proxy.md) is enabled and configured to proxy traffic generated by proxy-unaware [thick clients](/app/concepts/web_traffic.md#thick-clients) the behavior will be the same. However, without a [DNS rewrite](/app/guides/dns_rewrites.md), Caido will not forward the request to the IP address of the destination server. The destination will resolve to the API, resulting in 400 Bad Request responses due to malformed requests. ## Upstream Determination Algorithm Once Caido has determined that the request should be forwarded to a destination server, it uses the following algorithm to determine to what upstream to send the request to: ```mermaid flowchart TD Request --> TLS{{Is TLS?}} TLS --Yes --> InvisibleTLS{{Is Invisible Proxying?}} TLS --No --> HTTP{{Is HTTP Request?}} InvisibleTLS --Yes --> Handshake{{Handshake Using SNI?}} InvisibleTLS --->|No| Error Handshake --Yes --> HeaderTLS{{Host/Port in Header?}} Handshake --->|No| Error HeaderTLS --Yes --> SNI[Domain: SNI
Port: Host Header Port / 443 Default
 ] HeaderTLS --No --> Error HTTP --->|No| Error HTTP --Yes --> Connect{{Is CONNECT Method?}} Connect ---->|Yes| ConnectTunnel[Domain: Authority Domain
Port: Authority Port
 ] Connect --No --> Url{{Host/Port in URI?}} Url ---->|Yes| Tunnel[Domain: URI Authority Domain
Port: URI Authority Port / Default for Scheme
 ] Url --No --> InvisibleHttp{{Is Invisible Proxying?}} InvisibleHttp --Yes --> Header{{Host/Port in Header?}} InvisibleHttp --->|No| Error Header ---->|No| Error Header --Yes --> Direct[Domain: Host Header Domain
Port: Host Header Port / 80 Default
 ] ``` --- --- url: /app/troubleshooting.md description: >- Common error solutions, debugging guides, and bug reporting instructions for Caido issues. --- # Troubleshooting The Troubleshooting section provides potential remedies to commonly encountered errors and misconfigurations, as well as directives on reporting a bug. --- --- url: /app/tutorials/android_troubleshooting.md description: >- Learn possible resolutions for errors encountered when attempting to proxy HTTP/HTTPS traffic generated by Android devices. --- # Troubleshooting ::: warning NOTE Due to the variety of Android testing configurations, the potential resolutions are non-exhaustive. Individual research may be necessary in order to resolve errors encountered with your specific setup. ::: ## Traffic Isn't Appearing in HTTP History If traffic is not appearing in the HTTP History table, network configuration settings may be the cause. Disable `Mobile data` usage, VPN connections, and/or set the Wi-Fi **Proxy hostname** to `10.0.2.2`. ## "Failed to spawn: unable to find process with name 'gadget'" If you encounter this error after attempting to execute Frida, ensure the application is launched. ## "Failed to spawn: unable to communicate with remote frida-server; please ensure that major versions match and that the remote Frida has the feature you are trying to use" - "TypeError: not a function" If you encounter this error after attempting to execute Frida, ensure the versions of Frida, Frida Tools, and Frida Gadget are compatible with each other. [View the releases in the Frida repository.](https://github.com/frida/frida/releases) ```bash frida --version ``` ```bash pip show frida-tools ``` ## Certificate Errors If you encounter an error after attempting to install Caido's CA certificate, either: ### Verify the Certificate Ensure the certificate is the one specific to your active instance: [ CA Certificate Management](/app/guides/ca_certificate_managing.md) Ensure the certificate name is compatible with the Android system: [Renaming Caido's CA Certificate](/app/tutorials/android_add_certificate.md#renaming-caido-s-ca-certificate) ### Ignore Certificate Errors 1. Obtain the SPKI fingerprint of your Caido instance CA certificate by executing the `get_spki_fingerprint.py` file. ```py #!/usr/bin/env python3 """ Script to extract SPKI fingerprint from a certificate Mimics: openssl x509 -in $YOUR_CA_CERTIFICATE -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 """ import base64 import hashlib from cryptography import x509 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat def get_spki_fingerprint_openssl_style(cert_pem): """ Extract the SPKI fingerprint from a certificate in PEM format Mimics the OpenSSL command: openssl x509 -in $YOUR_CA_CERTIFICATE -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 Args: cert_pem (str): Certificate in PEM format Returns: str: Base64 encoded SHA-256 hash of the public key in DER format """ # Parse the certificate cert = x509.load_pem_x509_certificate(cert_pem.encode('utf-8')) # Get the public key bytes in DER format (equivalent to openssl pkey -pubin -outform der) public_key_bytes = cert.public_key().public_bytes( encoding=Encoding.DER, format=PublicFormat.SubjectPublicKeyInfo ) # Calculate SHA-256 hash in binary (equivalent to openssl dgst -sha256 -binary) hash_binary = hashlib.sha256(public_key_bytes).digest() # Encode in base64 (equivalent to openssl enc -base64) base64_fingerprint = base64.b64encode(hash_binary).decode('utf-8') return base64_fingerprint def get_spki_fingerprint_hex(cert_pem): """ Extract the SPKI fingerprint from a certificate in PEM format (hex format) Args: cert_pem (str): Certificate in PEM format Returns: str: SHA-256 fingerprint of the SPKI in hex format """ # Parse the certificate cert = x509.load_pem_x509_certificate(cert_pem.encode('utf-8')) # Get the public key bytes (SPKI) public_key_bytes = cert.public_key().public_bytes( encoding=Encoding.DER, format=PublicFormat.SubjectPublicKeyInfo ) # Calculate SHA-256 hash fingerprint = hashlib.sha256(public_key_bytes).hexdigest() # Format as colon-separated hex pairs (common format for fingerprints) formatted_fingerprint = ':'.join(fingerprint[i:i+2].upper() for i in range(0, len(fingerprint), 2)) return formatted_fingerprint def get_certificate_input(): """ Get certificate input from user """ print("Please paste your certificate (including BEGIN and END lines):") print("Press Enter twice when finished:") lines = [] while True: line = input() if line.strip() == "" and lines and lines[-1].strip() == "": break lines.append(line) # Remove the last empty line if lines and lines[-1].strip() == "": lines.pop() return '\n'.join(lines) def main(): try: # Get certificate from user input cert_pem = get_certificate_input() # Validate that it looks like a certificate if not cert_pem.strip().startswith('-----BEGIN CERTIFICATE-----'): print("Error: Certificate should start with '-----BEGIN CERTIFICATE-----'") return if not cert_pem.strip().endswith('-----END CERTIFICATE-----'): print("Error: Certificate should end with '-----END CERTIFICATE-----'") return # Get the OpenSSL-style base64 fingerprint base64_fingerprint = get_spki_fingerprint_openssl_style(cert_pem) print("\nSPKI Fingerprint (OpenSSL style - Base64):") print(base64_fingerprint) # Also show the hex format for comparison hex_fingerprint = get_spki_fingerprint_hex(cert_pem) print(f"\nSPKI Fingerprint (Hex format):") print(hex_fingerprint) # Show the raw hex without colons raw_fingerprint = hex_fingerprint.replace(':', '').lower() print(f"\nRaw hex: {raw_fingerprint}") print(f"\nEquivalent OpenSSL command:") print("openssl x509 -in certificate.pem -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64") except Exception as e: print(f"Error processing certificate: {e}") if __name__ == "__main__": main() ``` ```bash python get_spki_fingerprint.py ``` 2. Create a file named `chrome` with the following content with the SPKI fingerprint as the value of the `--ignore-certificate-errors-spki-list` argument. ```txt chrome --ignore-certificate-errors-spki-list= ``` 3. Execute the `adb` tool with the device ID as the value of the `-s` argument and `root` to gain root privileges. ```bash adb -s root ``` 4. Execute `adb push` to push the `chrome` file to the following locations: * /data/local/chrome-command-line * /data/local/android-webview-command-line * /data/local/webview-command-line * /data/local/content-shell-command-line * /data/local/tmp/chrome-command-line * /data/local/tmp/android-webview-command-line * /data/local/tmp/webview-command-line * /data/local/tmp/content-shell-command-line ```bash adb push chrome /data/local/chrome-command-line && adb push chrome /data/local/android-webview-command-line && adb push chrome /data/local/webview-command-line && adb push chrome /data/local/content-shell-command-line && adb push chrome /data/local/tmp/chrome-command-line && adb push chrome /data/local/tmp/android-webview-command-line && adb push chrome /data/local/tmp/webview-command-line && adb push chrome /data/local/tmp/content-shell-command-line ``` 5. Set the appropriate permissions on each location. ```bash adb shell "chmod 555 -v /data/local/chrome-command-line /data/local/android-webview-command-line /data/local/webview-command-line /data/local/content-shell-command-line /data/local/tmp/chrome-command-line /data/local/tmp/android-webview-command-line /data/local/tmp/webview-command-line /data/local/tmp/content-shell-command-line" ``` 6. Kill Chrome. ```bash adb shell am force-stop com.android.chrome ``` 7. Launch Chrome. 8. Navigate to `chrome://version` and verify that `chrome --ignore-certificate-errors-spki-list=` is listed in the **Command Line** arguments. --- --- url: /app/tutorials.md description: >- Learn how to master Caido through hands-on tutorials and community-contributed guides with practical examples. --- # Tutorials The Tutorials section contains example projects to help you get the most out of Caido. ## Community Tutorials Learn from the community through these contributed guides and videos. 🎉 ::: info Got a tutorial? If you have a tutorial you'd like to share with the community, please follow the [Contribution Guidelines](/app/guides/documentation.md)! Please note that these videos are not endorsed by Caido. ::: --- --- url: /app/concepts/workflows_nodes.md description: >- Understand the core concepts behind Caido workflow nodes - actions, conditions, connections, aliases, and input types for building complex automation sequences. --- # Understanding Nodes **Nodes** are simply **actions** or **conditions**. By connecting nodes together, complex action sequences based on certain conditions are created. Nodes are visually represented by Caido as draggable blocks, colorized by category. They utilize an input/output model that can be used to send data altered by one node to a subsequent node. ## Connecting Nodes A `Connection` is visually represented by the gray line between nodes and determine the order of execution. Workflows use a top-down heirachical structure (*the node at the very top represents the beginning of the flow and the Node at the bottom represents the end of the flow*). 1. The down arrow within a circle icon represents a node's `socket`. 2. **Click** and drag a bottom socket to the top socket of the next/a subsequent node in the flow to create a `connection`. ## Aliases A node's `Alias` is an arbitrarily set identifier used to uniquely reference the associated node within a workflow. Aliases can consist of lowercase letters, hyphens, underscores and numbers. ::: info This differs from a node's name which simply serves cosmetic purposes to assist in the visual representation. ::: ## Input Types ### 1. Constant Value Type `Constant Values` - the input used by the node's execution will be the ***supplied value***. * To use this input type, manually enter the data to be used in the `Data` field. ### 2. Reference Value Type `Reference Values` - the input used by the node's execution will be the ***output of a previous node***. * To use this input type, the content of the `Data` field under `Inputs` with the `Use reference` checkbox ***selected*** should be formatted using the following syntax: ```text $[node_alias].[property_alias] ``` *Example (pictured above):* * *The value* `$start.data` *is the output of the* **Start** *node being taken as input by the* **Base64 Encode** *node*. * *The output of the* **Base64 Encode** *node will be referenced by the* **End** *node as* `$base64_encode.data`. ## Categories Certain nodes are specific to a workflow type (Passive/Active/Convert). Though, in general, nodes can be categorized broadly and associated together by color: ### Start/End Nodes These nodes are color categorized together by their yellow marked tabs. They mark the beginning and end of a workflow. ### Control Nodes These nodes are color categorized together by their green marked tabs and allow you to dictate the execution flow. ### Code Nodes These nodes are color categorized together by their red marked tabs and provide a way to integrate Shell commands and Javascript. ### Miscellaneous Nodes (Blue) These nodes are color categorized together by their blue marked tabs. The actions they perform include encoding/decoding, hashing/dehashing and filtering. ::: info The development of nodes will be ongoing and new nodes will be included in future Caido releases. ::: --- --- url: /app/reference/burp_vs_caido.md --- --- --- url: /burp-suite.md --- --- --- url: /app/guides/files_uploading.md description: >- A step-by-step guide to uploading files to Caido instances for use in Automate sessions and workflow operations. --- # Uploading Files To upload files to your Caido instance, **click** on the Upload button. ::: info Once a file has been uploaded, it will be available in the `Selected file` drop-down menu for `Hosted File` Automate sessions. ::: --- --- url: /app/guides/upstream.md description: >- A step-by-step guide to configuring upstream proxies in Caido for forwarding traffic through HTTP and SOCKS proxies with authentication and scope control. --- # Upstream to Another Proxy To forward traffic proxied by Caido to an upstream proxy, **click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `Network` tab. Then, **click** on the `+ Add Proxy` button under the `HTTP Proxies` or `SOCKS Proxies` sections. Type in the listening address/port of the upstream proxy in the associated input fields. ::: tip Ensure upstream HTTP proxies are listening on a different address/port than Caido. ::: The additional configuration settings are optional: * `Use HTTPS`: Establishes an encrypted connection with the upstream proxy. * `Included Hosts`/`Excluded Hosts`: Allows you to [define a scope preset](/app/guides/scopes_defining.md) to manage what traffic is sent upstream. * `Resolve DNS over SOCKS proxy`: DNS resolution will be performed by the SOCKS proxy. * `Username`/`Password`: These input fields allow you to supply credentials for upstream proxies that require authentication. ::: tip To ensure your configurations successfully forward traffic, you can test them by **clicking** on the Test button. ::: *** Once you have defined the upstream proxy settings, **click** on the `+ Create` button save the configuration. ::: info * If both SOCKS and HTTP proxies are enabled, traffic will flow through the SOCKS proxy first, then through the HTTP proxy. * Calls to [Caido's cloud server](/app/concepts/cloud.md) will not flow through additional proxies. ::: *** *** --- --- url: /app/tutorials/mcp.md description: >- Learn how to integrate AI models and agents with Caido using the Caido MCP Server. --- # Using a Caido MCP Server In this tutorial, you will learn how to integrate a Caido MCP Server to be used with Cursor and Claude Code. ## Caido MCP Server The community developed [Caido MCP Server](https://github.com/c0tton-fluff/caido-mcp-server) provides AI models/agents with a variety of tools and controlled access to project data. ::: warning The Caido MCP Server is **not** officially affiliated with Caido. As with any third-party projects, ensure to review the code and assess the potential security risks before installation and execution. ::: With contextual awareness of a project's proxied traffic, extensions, and configurations - the Caido MCP Server gives you the ability to instruct AI assistants to: * Intercept and forward traffic. * Filter traffic with HTTPQL query statements. * Send requests via Replay. * List Automate and Replay sessions. * Obtain request/response data. * Create and list findings and scope presets. * Discover the recorded endpoints in the Sitemap. * List and switch between projects. * List workflows and filter presets. [View a complete list of the individual tools.](https://github.com/c0tton-fluff/caido-mcp-server?tab=readme-ov-file#tools) ### Installation To install the Caido MCP Server: 1. Clone the repository. ```bash git clone --branch v1.1.0 https://github.com/c0tton-fluff/caido-mcp-server.git ``` 2. Navigate into the root directory. ```bash cd caido-mcp-server ``` 3. Compile the server. ::: code-group ```bash [Linux/macOS] go build -o caido-mcp-server . ``` ```powershell [Windows] go build -o caido-mcp-server.exe . ``` ::: [View alternative installation methods.](https://github.com/c0tton-fluff/caido-mcp-server?tab=readme-ov-file#install) ### Configuration Once the server is installed, to connect it to Caido: 1. Launch Caido. 2. Execute the `login` command with the listening address of the Caido instance as the value of the `-u` argument. ::: code-group ```bash [Linux/macOS] caido-mcp-server login -u http://127.0.0.1:8080 ``` ```powershell [Windows] caido-mcp-server.exe login -u http://127.0.0.1:8080 ``` ::: 3. **Click** on the `Allow` button to authorize the server. ## Configuring an MCP Client Once the server is installed, configured, and you are authenticated, models/agents can be configured as clients. ### Cursor To use the Caido MCP Server with the Cursor desktop application: 1. Create a `~/.cursor/mcp.json` file with the following content (*ensure to replace the value of the `command` key with the path location of your `caido-mcp-server` binary*). ::: code-group ```json [Linux/macOS] { "mcpServers": { "caido": { "command": "/Users/ninjeeter/caido-mcp-server/caido-mcp-server", "args": ["serve"], "env": { "CAIDO_URL": "http://127.0.0.1:8080" } } } } ``` ```json [Windows] { "mcpServers": { "caido": { "command": "C:\\Users\\ninje\\caido-mcp-server\\caido-mcp-server.exe", "args": ["serve"], "env": { "CAIDO_URL": "http://127.0.0.1:8080" } } } } ``` ::: 2. Ensure Caido is running and listening at the same address as the value of the `CAIDO_URL` environment variable (*e.g. `http://127.0.0.1:8080`*). 3. Restart Cursor (*or **click** on **View** in the navigation bar, select **Command Palette...**, and select **Developer: Reload Window***). ::: tip To verify the configuration, **click** on the button to access the **Cursor Settings** and select **Tools & MCP**. 4. **Click** on the `+ New Chat` button. 5. To verify the connection, submit the message "Send a Replay request to example.com". ::: warning Consider the reduction in oversight before selecting `Allowlist MCP Tool`. A new Replay session will be created and a summary of the request and response will be returned. ### Claude CLI To use the Caido MCP Server with the Claude CLI tool: 1. In the configuration object of the `~/.claude.json` file, add the following `mcpServers` object as a field (*ensure to replace the value of the `command` key with the path location of your `caido-mcp-server` binary*). ::: code-group ```json [Linux/macOS] "mcpServers": { "caido": { "type": "stdio", "command": "/Users/ninjeeter/caido-mcp-server/caido-mcp-server", "args": ["serve"], "env": { "CAIDO_URL": "http://127.0.0.1:8080" } } } ``` ```json [Windows] "mcpServers": { "caido": { "type": "stdio", "command": "C:\\Users\\ninje\\caido-mcp-server\\caido-mcp-server.exe", "args": ["serve"], "env": { "CAIDO_URL": "http://127.0.0.1:8080" } } } ``` ::: 2. Save the changes to `.claude.json`. 3. Start a Claude session. ```bash claude ``` 4. To verify the connection, submit the message "Send a Replay request to example.com". ::: warning Consider the reduction in oversight before selecting `2. Yes, and don't ask again for caido - caido_send_request commands in...`. A new Replay session will be created and a summary of the request and response will be returned. --- --- url: /app/guides/preconfigured_browser.md description: A step-by-step guide to launching a browser preconfigured for use with Caido. --- # Using a Preconfigured Browser As an alternative to importing Caido's CA certificate in your browser, Caido also supports [Chrome](https://www.google.com/chrome/) and [Chromium](https://www.chromium.org/developers/how-tos/get-the-code/) preconfigurations. To launch a preconfigured browser, **click** on the button in the top-right toolbar of the Caido user-interface, and then **click** on the associated `Launch` button of an installed browser. --- --- url: /app/tutorials/github_action.md description: Learn how to orchestrate Caido in GitHub Actions for CI/CD --- # Using Caido in GitHub Actions This tutorial will guide you through setting up and using Caido in a GitHub Actions CI/CD pipeline. You'll learn how to: * Set up a headless Caido instance in GitHub Actions * Configure secrets for secure authentication * Create scripts to interact with your Caido instance ## 1. Creating a Registration Key To safely deploy Caido instances in automated environments without human intervention, you'll need to use a [Registration Key](/dashboard/concepts/registration_key). Registration keys automatically claim new instances, ensuring they're secure even when deployed in CI/CD pipelines. ### Creating a Registration Key First, create a registration key in the [Caido Dashboard](https://dashboard.caido.io): 1. Navigate to your `Team` workspace 2. Go to the Registration Keys section 3. Click `Create Key` 4. Configure the key: * **Description**: `CI/CD Pipeline` * **Prefix**: `cicd` (or your preferred prefix) * **Expiration**: Set an expiration date appropriate for your use case * **Reusable**: Yes (recommended for CI/CD) For detailed instructions, see our guide on [creating a registration key](/dashboard/guides/create_registration_key). ## 2. Creating a Personal Access Token (PAT) To authenticate your scripts with the Caido instance, you'll need a [Personal Access Token (PAT)](/dashboard/concepts/pat). PATs allow headless authentication without requiring browser interaction. ### Creating a PAT 1. Visit the [Caido Dashboard](https://dashboard.caido.io) 2. Navigate to the Developer page **in your Workspace** 3. Click `+ Create Token` 4. Configure the token: * **Name**: `CI/CD Automation` * **Resource Owner**: Select your `Team` * **Expiration**: Set an expiration date For detailed instructions, see our guide on [creating a PAT](/dashboard/guides/create_pat). ## 3. Configuring GitHub Secrets To securely store your registration key and PAT, you'll need to add them as GitHub repository secrets. This ensures they're encrypted and only accessible to your GitHub Actions workflows. ### Adding Secrets to Your Repository 1. Navigate to your GitHub repository 2. Go to **Settings** → **Secrets and variables** → **Actions** 3. Click **New repository secret** 4. Add the following secrets: * **Name**: `CAIDO_REGISTRATION_KEY` * **Value**: Your registration key (e.g., `ckey_xxxxx`) * **Name**: `CAIDO_PAT` * **Value**: Your Personal Access Token (e.g., `caido_xxxxx`) ::: warning Never commit secrets directly in your code or workflow files. Always use GitHub Secrets for sensitive information. ::: ## 4. Creating the Automation Script Now we'll create a script that uses the `@caido/sdk-client` to interact with your Caido instance. This script will demonstrate common CI/CD use cases like creating projects, running scans, and checking results. ### Setting Up the Project First, create a directory for your automation scripts and initialize it: ```bash mkdir script cd script pnpm init ``` Install the Caido SDK client: ```bash pnpm install @caido/sdk-client ``` ### The Automation Script Create a file named `index.ts`: ```typescript import { Client } from "@caido/sdk-client"; async function main() { // Get the Caido instance URL from environment or use default const instanceUrl = process.env["CAIDO_INSTANCE_URL"] ?? "http://localhost:8080"; // Get the Personal Access Token from environment const pat = process.env["CAIDO_PAT"]; if (pat === undefined || pat === "") { console.error("❌ Error: CAIDO_PAT environment variable is required"); console.error(" Set it with: export CAIDO_PAT=caido_xxxxx"); process.exit(1); } const client = new Client({ url: instanceUrl, auth: { pat: pat, cache: { file: ".secrets.json", }, }, }); await client.connect(); console.log("✅ Connected to Caido instance"); const viewer = await client.user.viewer(); console.log("Viewer: ", JSON.stringify(viewer, null, 2)); } main().catch((error: unknown) => { console.error("❌ Fatal error:", error); process.exit(1); }); ``` ### Adding Scripts to package.json Add the following to your `package.json`: ```json { "scripts": { "test": "node index.ts" }, "devDependencies": { "@types/node": "^20.0.0", "typescript": "^5.3.0" } } ``` ## 5. Creating the GitHub Actions Workflow Now we'll create a GitHub Actions workflow that sets up Caido and runs your automation script. ### Workflow File Create `.github/workflows/caido-tests.yml`: ```yaml name: Run Caido Security Scan on: push: branches: - 'main' jobs: scan: runs-on: ubuntu-latest services: caido: image: caido/caido:latest ports: - 8080:8080 env: CAIDO_REGISTRATION_KEY: ${{ secrets.CAIDO_REGISTRATION_KEY }} steps: - name: Checkout Repo uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v6 with: node-version: '24' - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10 - name: Install script dependencies working-directory: script run: pnpm install - name: Run script working-directory: script run: pnpm start env: CAIDO_PAT: ${{ secrets.CAIDO_PAT }} CAIDO_INSTANCE_URL: http://localhost:8080 ``` ## 6. Customizing for Your Use Case You can extend this setup for various security testing scenarios: ### Create an OOB link ```typescript // Execute a workflow const pluginPackage = await client.plugin.pluginPackage("quickssrf"); if (pluginPackage === undefined) { console.error("❌ Error: Plugin package not found"); process.exit(1); } const settings = await pluginPackage.callFunction({ name: "getSettings", }); await pluginPackage.callFunction({ name: "startInteractsh", arguments: [ { serverURL: settings.serverURL, token: settings.token, pollingInterval: settings.pollingInterval, correlationIdLength: settings.correlationIdLength, correlationIdNonceLength: settings.correlationIdNonceLength, }, ], }); const result = await pluginPackage.callFunction({ name: "generateInteractshUrl", arguments: [settings.serverURL], }); ``` ### Running Scans ::: info Will be added soon ::: ## Next Steps For a complete working example, check out the [caido-community/cicd-example](https://github.com/caido-community/cicd-example) repository. --- --- url: /app/concepts/offline.md --- # Using Caido Offline Caido can also be used offline to conduct security testing in internet-restricted environments, including internal networks, isolated systems, and when performing onsite penetration tests. However, since authentication requires communication with our cloud platform, in order to utilize an instance and subscription features, internet connectivity is required: * On initial launch. * For certain updates. * To authenticate from a new location/device. Once authenticated, Caido will operate in offline mode for 7 days. After this period, internet connectivity will be required again to obtain access tokens. ::: warning NOTE If internet access is completely unavailable, Caido can still be used in [Guest Mode](/app/guides/guest_mode.md) ::: --- --- url: /app/tutorials/skills.md description: Learn how to use Caido Skills to integrate Caido with AI agents. --- # Using Caido Skills In this tutorial, you will learn how to use Caido Skills to integrate Caido with AI agents. ## Agent Skills [Agent Skills](https://agentskills.io/home) is an open standard for extending the capabilities of AI agents. At its most basic, a skill is a folder that contains a `SKILL.md` file. The file begins with a "frontmatter" header that provides basic information to a AI agent. The two required fields of a frontmatter header are the skill name and a brief description of what the skill does and when it should be used. ```yaml --- name: my-skill description: This skill does XYZ and should be used when a user prompt begins with "Run my-skill". --- ``` Once the frontmatter is written, the instructions of the skill can be defined in Markdown format in the rest of the file. ```markdown --- name: my-skill description: This skill does XYZ and should be used when a user prompt begins with "Run my-skill". --- # My Skill At a high-level this skill... ## Step-by-Step Instructions 1. Start with... 2. ... 3. ... ## Examples An example use case of this skill is... ``` In addition to instructions defined in a `SKILL.md` file, a skill folder can also include categorical sub-folders for additional content to provide an agent with like scripts, references, and assets. These can then be referenced in the `SKILL.md` file using relative paths from the skill folder root. [View examples of skill folders.](https://github.com/anthropics/skills/tree/main/skills) ## Caido Skills The official [Caido Skills](https://github.com/caido/skills) provides AI agents with the [Caido Client SDK](https://github.com/caido/sdk-js/tree/main/packages/sdk-client), giving agents the ability to connect, authenticate, and interact with an instance programmatically. Caido Skills provides complete coverage of Caido's API, allowing you to instruct AI agents to carry out tasks that you would normally have to do manually such as send HTTP requests with Replay, fuzz payloads with Automate, search for proxied traffic, and more. [View a complete list of capabilities.](https://github.com/caido/skills/tree/main/skills/caido-mode#whats-covered) ## Claude Code ::: warning NOTE In this tutorial we will cover adding Caido Skills using the Claude Code CLI tool. However, the skill package is available to other AI agents. A full list of available agents is available following the `Which agents do you want to install to?` prompt of the installation. ::: Claude Code is an AI agent designed to work within a project to assist with development. Once Claude Code, is granted access to a project, it is able to read, edit, and execute its files - making it skill compatible. [View the official documentation for instructions on how to install the Claude Code CLI tool.](https://code.claude.com/docs/en/overview#get-started) ## Configuration & Installation To make the Caido Skills available to the Claude Code CLI tool: 1. Create a new project (*e.g. `my-project`*) to store the Caido Skills package. ```bash mkdir my-project ``` 2. Navigate to the project directory. ```bash cd my-project ``` 3. Add Caido Skills to the project. ```bash pnpx skills add caido/skills --skill='*' ``` Or: ```bash pnpm dlx skills add caido/skills --skill='*' ``` 4. When prompted, use the down arrow key and spacebar to select `Claude Code` and press `ENTER` to add it as an additional agent. 5) Select either the `Project` or `Global` installation scope. 6. Select the `Symlink` installation method. ::: warning Before proceeding with the installation, ensure to review and assess any messages displayed as Security Risk Assessments. ::: 7. To proceed with the installation, select `Yes` and press `ENTER`. *** 8. Navigate to the `caido-mode` directory. ```bash cd .agents/skills/caido-mode/ ``` 9. Install the dependencies. ```bash npm install ``` ## Authentication To authenticate to your Caido instance: 1. [Create a Personal Access Token (PAT)](https://docs.caido.io/dashboard/guides/create_pat.html). ::: info Typically, authentication requires user interaction (*clicking `Login`, submitting account credentials, and granting your device authorization to access an instance*). With a PAT, authorization is granted immediately, and the PAT is exchanged for an access token and a refresh token. A custom SecretsTokenCache (*implementing the SDK's TokenCache interface*) persists these tokens to `secrets.json` file in `~/.claude/config` so they survive across CLI invocations. ::: 2. Execute the `setup` command and provide the PAT. ```bash npx tsx caido-client.ts setup "" ``` ```txt Connecting to http://localhost:8080... [caido] Attempting to load cached token [caido] Starting authentication flow [caido] Authentication flow completed [caido] Saving token to cache Authenticated as: 01HWVM3E34S2G1BKHWB9ACEHK3 Saved to /Users/ninjeeter/.claude/config/secrets.json URL: http://localhost:8080 PAT: caido_8yWtyz... Access token: cached ``` 3. To verify the authentication, execute the `auth-status` command. ```bash npx tsx caido-client.ts auth-status ``` ```txt [caido] Attempting to load cached token [caido] Loaded token from cache { "authenticated": true, "user": { "kind": "CloudUser", "id": "01ABCD2E34F5G6HIJKL7MNOPQ8", "profile": { "identity": { "email": "user@example.com", "name": "User Name" }, "subscription": { "plan": { "name": "Individual" }, "entitlements": [ { "name": "feature:assistant" }, { "name": "feature:automate_workflows" }, { "name": "feature:export_filtered_requests" }, { "name": "feature:export_unlimited_findings" }, { "name": "feature:project_backups" }, { "name": "feature:replay_workflows" }, { "name": "feature:search_bar" }, { "name": "feature:unlimited_environments" }, { "name": "feature:unlimited_filter_presets" }, { "name": "feature:unlimited_plugins" }, { "name": "feature:unlimited_projects" }, { "name": "feature:unlimited_workflows" }, { "name": "node:advanced" }, { "name": "support:discord_role" } ] } } }, "health": { "name": "caido", "version": "0.55.3", "ready": true }, "url": "http://localhost:8080" } ``` 4. Navigate to the project directory. ```bash cd ../../../ ``` 5. Launch the Claude Code CLI. ```bash claude ``` 6. Grant access to the project directory. ```txt Quick safety check: Is this a project you created or one you trust? (Like your own code, a well-known open source project, or work from your team). If not, take a moment to review what's in this folder first. Claude Code'll be able to read, edit, and execute files here. Security guide ❯ 1. Yes, I trust this folder 2. No, exit Enter to confirm · Esc to cancel ``` ::: warning NOTE Assess and accept any security prompts encountered to continue. ::: 7. With Caido launched, test the Caido Skills integration. ```txt Check the interception status of Caido. ``` *** --- --- url: /app/guides/match_replace_capturing.md description: >- A step-by-step guide to using capturing groups in Caido's Match & Replace feature to extract and reference specific parts of regular expressions. --- # Using Capturing Groups By encasing sections of a regular expression with parentheses, you can extract and reference specific subpatterns. Known as "capturing groups", these value groups can then be referenced using `$` followed by the group's number, starting from `1`. ## JSON Capturing Groups ::: tip To test your regular expressions, visit [regex101.com](https://regex101.com). ::: To capture key-value string pairs from JSON such as: ```json {"key":"value"} ``` With the `Matcher` set to `Regex`, type the following regular expression in the input field: ```regex \{\"([^\"]+)\":\"([^\"]+)\"\} ``` To reference the capturing groups in the `Replacer` input field, select `Term` and use: * `$1` to reference `key`. * `$2` to reference `value`. ::: warning NOTE Caido does not currently support look-around and backreference regular expressions. ::: ::: tip To use `$` and an integer literally, escape the `$` with another `$`: `{"$$1":"$2"}` becomes `{"$1":"value"}`. ::: --- --- url: /app/guides/replay_environment_variables.md description: >- A step-by-step guide to using environment variables in Caido's Replay feature for dynamic request modification and placeholder configuration. --- # Using Environment Variables in Replay ## ::: tip Video Demonstration To insert an environment variable in a Replay request, **click**, **hold**, and **drag** over the value you want to replace and **click** the `+` button to add it as a placeholder. Then, **click** on the associated edit button of the placeholder to open the `Placeholder Settings` window. With `Environment Variable` as the `Type`, **click** on the `Select an environment variable` drop-down menu, select a environment variable from the list, and **click** `Add` to save the configuration. Applied environment variables are listed and will be applied in top to bottom order. To avoid collisions between variables, you can rearrange their order by **left-clicking**, **dragging**, **holding**, and **releasing** a variable either above or below other variables in the list. Close the settings window and send the request. ::: tip To verify the addition was successful, you can view the request by navigating to the Search interface. ::: --- --- url: /app/guides/foxyproxy.md description: >- A step-by-step guide to installing and configuring the FoxyProxy browser extension for Chrome and Firefox. --- # Using FoxyProxy The FoxyProxy browser extension gives you the ability to quickly enable/disable your browser's use of Caido as a proxy. ## ::: tip Video Demonstration ## Chrome To install the browser extension, launch the Chrome browser, navigate to , and **click** on the `Add to Chrome` button. In the pop-up window, **click** on the `Add extension` button. *** Once the extension is installed, **click** on the button in the top-right corner of the browser window, and then either **click** on the button or **right-click** on the extension and select `Pin to Toolbar`. Then, [continue to the configuration instructions](#configuring-foxyproxy). ## Firefox To install the browser extension, launch the Firefox browser, navigate to , and **click** on the `Add to Firefox` button. In the pop-up window, select `Allow extension to run in private windows`, and then **click** on the `Add` button. In the subsequent pop-up window, **click** on the `OK` button. Once the extension is installed, [continue to the configuration instructions](#configuring-foxyproxy). ## Configuring FoxyProxy **Click** on the FoxyProxy toolbar button and select `Options`. Next, select the `Proxies` tab and **click** on the `Add button`. In the configuration interface, give an arbitrary name to the proxy configuration in the `Title` input field, and set the following settings: * `Type`: `HTTP` * `Hostname`: `127.0.0.1` * `Port`: `8080` Once the configuration is set, **click** on the `Save` button. ## Enabling/Disabling Proxying To enable proxying to pass web traffic through Caido, **click** on the FoxyProxy toolbar button and select the saved configuration by its name. To disable proxying, select the Disable option. --- --- url: /app/tutorials/litellm.md description: >- Learn how to configure LiteLLM, Caido, and Shift to use models from multiple LLM providers via a unified proxy. --- # Using LiteLLM with Shift ::: danger **On March 24, 2026 at 10:52 UTC versions v1.82.7 and v1.82.8 of the `litellm` package on PyPI were found to be compromised with credential-stealing malware.** The recommended actions to take are: * Remove/uninstall `litellm 1.82.7`/`litellm 1.82.8` immediately. * Check for `litellm_init.pth` in your site-packages/directory. * Rotate ALL credentials that were present as environment variables or in config files on any system where `litellm 1.82.8` was installed. View more details and updates: * * ::: [LiteLLM](https://docs.litellm.ai/) is an open-source proxy/gateway that provides a unified interface for accessing multiple LLM providers. In this tutorial, you will learn how to configure LiteLLM, Caido, and [Shift](/app/tutorials/shift.md) to use models from various providers that are not directly supported. ## LiteLLM Configuration The following Docker Compose file runs two services: LiteLLM and a PostgreSQL database for chat history persistence. 1. Save the following `docker-compose.yml` file and navigate to its directory: ```yml services: litellm: build: context: . args: target: runtime image: ghcr.io/berriai/litellm:main-stable ports: - '4000:4000' environment: LITELLM_MASTER_KEY: sk-admin-key-1234567890 DATABASE_URL: 'postgresql://llmproxy:dbpassword9090@db:5432/litellm' STORE_MODEL_IN_DB: 'True' STORE_PROMPTS_IN_SPEND_LOGS: 'True' depends_on: - db db: image: postgres:16 restart: always container_name: litellm_db environment: POSTGRES_DB: litellm POSTGRES_USER: llmproxy POSTGRES_PASSWORD: dbpassword9090 ports: - '5439:5432' volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data: name: litellm_postgres_data ``` 2. With Docker running, enter the following terminal command: ```bash docker-compose up ``` 3. Navigate to in your browser and login. 4) Select `Models + Endpoints`, `Add a Model`, configure your model [provider](https://docs.litellm.ai/docs/providers/) details, and **click** on the `Add Model` button to save the configuration. 5. Next, select `Virtual Keys`, **click** on the `+ Create New Key` button, configure the key, and **click** on the `Create Key` button to save the configuration. ## Caido Configuration 1. **Click** on the account button in the top-right corner of the Caido user-interface, select `Settings`, and open the `AI` tab. 2. Add your virtual key to the `OpenAI API Key` field and the listening address of LiteLLM in the `OpenAI Base URL (optional)` field. ## Shift Configuration 1. Next, navigate to the `Models` interface of Shift, select `OpenAI` from the drop-down menu, and **click** on the `+ Add Custom Model` button. 2. In the pop-up window, select `OpenAI` from the drop-down menu, enter the alias of the model you created in LiteLLM, and provide the `Model ID` using the following syntax: ```txt openai/ ``` 3. **Click** on the `Add` button to save the configuration and then **click** on its sliding radio button to enable the model. 4. Once the model has been added, it will be available as an option in Shift's model selection drop-down menu. --- --- url: /app/guides/caido_extension.md description: >- A step-by-step guide to installing and configuring the Caido browser extension for Firefox. --- # Using the Caido Browser Extension Caido's browser extension gives you the ability to quickly enable/disable your browser's use of Caido as a proxy. ## Firefox To install the browser extension, launch the Firefox browser, navigate to , and **click** on the `Add to Firefox` button. In the pop-up window, select `Allow extension to run in private windows`, and then click on the `Add` button. In the subsequent pop-up window, **click** on the `OK` button. Once the extension is installed, [continue to the configuration instructions](#configuring-the-caido-browser-extension). ## Configuring the Caido Browser Extension **Click** on the Caido Extension toolbar button. ### Automatic Configuration To automatically detect the proxy settings of your instance and create a configuration, launch Caido and **click** on the Auto-detect button. **Click** on the Confirm button to save the configuration. ### Manual Configuration To manually create a configuration, **click** on the `+ Create a proxy` button. In the configuration interface, give an arbitrary name to the proxy configuration in the `Name` input field, and set the following settings: * `Host`: `127.0.0.1` * `Port`: `8080` Once the configuration is set, **click** on the `+ Create` button. ## Enabling/Disabling Proxying To enable proxying to pass web traffic through Caido, **click** on the Caido Extension toolbar button and **click** on the sliding radio button. To disable proxying, **click** on the sliding radio button to remove its fill. --- --- url: /app/guides/workflows_javascript.md --- # Using the JavaScript Node The `Javascript` node allows you to write and execute JavaScript code within a workflow via the `run` function. ::: warning NOTE These code blocks will serve as a starting point for your workflow scripts. View the full [Workflow SDK](https://developer.caido.io/reference/sdks/workflow/) to customize your scripts to achieve the intended results. ::: ## Input The data made available to the node is dependant on the workflow type and is passed as the `input` parameter and can either be: ### NodeInput (Convert) ```ts export type NodeInput = { data?: Bytes; // An array of bytes represented in decimal notation. extra?: Record; }; ``` ### NodeInputHTTP (Passive/Active) ```ts export type NodeInputHTTP = { request?: Request; // An object representation of an HTTP request. response?: Response; // An object representation of an HTTP response. extra?: Record; }; ``` *** The JavaScript node can receive additional input via `extra?: Record;` from either the [output of an upstream node](/app/guides/workflows_references.md) or static input of type: * `String` * `Integer` * `Float` * `Boolean` * `Bytes` * `Map` * `Array` ::: tip View the [Additional Input](#additional-input) section for examples. ::: ## SDK The [Workflow SDK](https://developer.caido.io/reference/sdks/workflow/) is made available to the node via the `sdk` parameter, which provides a variety of methods to convert data, interact with proxied traffic, and carry out actions within Caido. ::: code-group ```js [Convert Workflows] /** * @param {NodeInput} input * @param {SDK} sdk * @returns {MaybePromise} */ export function run({ data, extra }, sdk) {} ``` ```js [Passive/Active Workflows] /** * @param {NodeInputHTTP} input * @param {SDK} sdk * @returns {MaybePromise} */ export async function run({ request, response, extra }, sdk) {} ``` ::: ## Logging to the Console To log messages to the backend logs, access the various level methods via the `sdk.console` object. ```js export async function run({ request, response, extra }, sdk) { sdk.console.debug('Debug message.'); sdk.console.error('Error message.'); sdk.console.log('Log message.'); sdk.console.warn('Warning message.') } ``` ::: warning NOTE To include DEBUG level messages in the backend logs, ensure to [enable debug mode](/app/troubleshooting/debugging.md). ::: ## Testing/Debugging JavaScript Node Workflows To test the execution and debug your JavaScript node scripts before using workflows against targets, provide mock requests and responses in the editors, and **click** on the Run button. ::: tip Mock Examples ::: code-group ```http [Request] POST /api/user HTTP/1.1 Host: example.com Content-Type: application/json Content-Length: 54 {"username":"admin","password":"secret","role":"user"} ``` ```http [Response] HTTP/1.1 200 OK Content-Type: application/json Content-Length: 71 {"status":"success","userId":123,"message":"User created successfully"} ``` ::: ::: tip Monitor the [logs](/app/guides/logs_viewing.md) when debugging. ::: ## Conversion To output byte data as a string, use the `.asString()` method. ### Convert Bytes to a String ```js export function run({ data, extra }, sdk) { let parsed = sdk.asString(data); sdk.console.log(parsed); return parsed; } ``` ## Requests & Responses The `request` and `response` object types provide a variety of methods for handling proxied traffic. ### Obtaining Request Data ::: code-group ```js [Current Request Elements] export async function run({ request, response, extra }, sdk) { if (request) { sdk.console.log(`${request.getId()}`); sdk.console.log(`${request.getCreatedAt()}`); sdk.console.log(`${request.getUrl()}`); sdk.console.log(`${request.getTls()}`); sdk.console.log(`${request.getPort()}`); sdk.console.log(`${request.getMethod()}`); sdk.console.log(`${request.getHost()}`); sdk.console.log(`${request.getPath()}`); sdk.console.log(`${request.getQuery()}`); sdk.console.log(`${request.getHeader('User-Agent')}`); sdk.console.log(`${request.getBody().toText()}`); } } ``` ```js [Current Request Headers] export async function run({ request, response, extra }, sdk) { if (request) { let headers = request.getHeaders(); sdk.console.log(JSON.stringify(headers, null, 2)); return JSON.stringify(headers, null, 2); } } ``` ```js [Current Full Request] export async function run({ request, response, extra }, sdk) { if (request) { sdk.console.log(`${request.getRaw().toBytes()}`); sdk.console.log(`${request.getRaw().toText()}`); } } ``` ```js [Full Requests from Project by HTTPQL Query] export async function run({ request, response, extra }, sdk) { const page = await sdk.requests .query() .filter('req.host.eq:"example.com"') .first(10) // Or .last() .execute(); sdk.console.log(`Found ${page.items.length} matching requests:`); page.items.forEach(item => { if (item.request) { sdk.console.log(`${item.request.getRaw().toBytes()}`); sdk.console.log(`${item.request.getRaw().toText()}`); } }); } ``` ::: ### Obtaining Response Data ::: code-group ```js [Current Response Elements] export async function run({ request, response, extra }, sdk) { if (response) { sdk.console.log(`${response.getId()}`); sdk.console.log(`${response.getCreatedAt()}`); sdk.console.log(`${response.getRoundtripTime()}`); sdk.console.log(`${response.getCode()}`); sdk.console.log(`${response.getHeader('Content-Type')}`); sdk.console.log(`${response.getBody().toText()}`); } } ``` ```js [Current Response Headers] export async function run({ request, response, extra }, sdk) { if (response) { let headers = response.getHeaders(); sdk.console.log(JSON.stringify(headers, null, 2)); return JSON.stringify(headers, null, 2); } } ``` ```js [Current Full Response] export async function run({ request, response, extra }, sdk) { if (response) { sdk.console.log(`${response.getRaw().toBytes()}`); sdk.console.log(`${response.getRaw().toText()}`); } } ``` ```js [Full Responses from Project by HTTPQL Query] export async function run({ request, response, extra }, sdk) { const page = await sdk.requests .query() .filter('req.host.eq:"example.com"') .first(10) // Or .last() .execute(); sdk.console.log(`Found ${page.items.length} matching responses:`); page.items.forEach(item => { if (item.response) { sdk.console.log(`${item.response.getRaw().toBytes()}`); sdk.console.log(`${item.response.getRaw().toText()}`); } }); } ``` ::: ### Obtaining Request and Response Pair Data ::: code-group ```js [Current Request and Response Elements] export async function run({ request, response, extra }, sdk) { if (request) { let requestId = request.getId(); let retrieved = await sdk.requests.get(requestId); if (retrieved) { if (retrieved.request) { sdk.console.log(`${retrieved.request.getId()}`); sdk.console.log(`${retrieved.request.getCreatedAt()}`); sdk.console.log(`${retrieved.request.getUrl()}`); sdk.console.log(`${retrieved.request.getTls()}`); sdk.console.log(`${retrieved.request.getPort()}`); sdk.console.log(`${retrieved.request.getMethod()}`); sdk.console.log(`${retrieved.request.getHost()}`); sdk.console.log(`${retrieved.request.getPath()}`); sdk.console.log(`${retrieved.request.getQuery()}`); sdk.console.log(`${retrieved.request.getHeader('User-Agent')}`); sdk.console.log(`${retrieved.request.getBody().toText()}`); } if (retrieved.response) { sdk.console.log(`${retrieved.response.getId()}`); sdk.console.log(`${retrieved.response.getCreatedAt()}`); sdk.console.log(`${retrieved.response.getRoundtripTime()}`); sdk.console.log(`${retrieved.response.getCode()}`); sdk.console.log(`${retrieved.response.getHeader('Content-Type')}`); sdk.console.log(`${retrieved.response.getBody().toText()}`); } } } } ``` ```js [Current Full Request and Response] export async function run({ request, response, extra }, sdk) { if (request) { let requestId = request.getId(); let retrieved = await sdk.requests.get(requestId); if (retrieved) { if (retrieved.request) { sdk.console.log(`${retrieved.request.getRaw().toBytes()}`); sdk.console.log(`${retrieved.request.getRaw().toText()}`); } if (retrieved.response) { sdk.console.log(`${retrieved.response.getRaw().toBytes()}`); sdk.console.log(`${retrieved.response.getRaw().toText()}`); } } } } ``` ```js [Full Requests and Responses from Project by HTTPQL Query] export async function run({ request, response, extra }, sdk) { const page = await sdk.requests .query() .filter('req.host.eq:"example.com"') .first(10) // Or .last() .execute(); sdk.console.log(`Found ${page.items.length} matching pairs:`); page.items.forEach(item => { if (item.request) { sdk.console.log(`${item.request.getRaw().toBytes()}`); sdk.console.log(`${item.request.getRaw().toText()}`); } if (item.response) { sdk.console.log(`${item.response.getRaw().toBytes()}`); sdk.console.log(`${item.response.getRaw().toText()}`); } }); } ``` ::: ### Filtering Requests ::: code-group ```js [Filter by Request Element] export async function run({ request, response, extra }, sdk) { let requestPath = request.getPath(); if (requestPath === '/api/user') { sdk.console.log(`${response.getRaw().toBytes()}`); sdk.console.log(`${response.getRaw().toText()}`); } } ``` ```js [Filter by Response Element] export async function run({ request, response, extra }, sdk) { let responseCode = response.getCode(); if (responseCode === 200) { sdk.console.log(`${request.getRaw().toBytes()}`); sdk.console.log(`${request.getRaw().toText()}`); } } ``` ```js [Check if Request is in Scope] export async function run({ request, response, extra }, sdk) { if (request) { if (sdk.requests.inScope(request)) { sdk.console.log(`${request.getHost()} is in scope.`); } else { sdk.console.log(`${request.getHost()} is out of scope.`); } } } ``` ```js [Match Request Against HTTPQL Query] export async function run({ request, response, extra }, sdk) { if (request) { let matchesFilter = sdk.requests.matches( 'req.method.eq:"POST" AND req.path.cont:"/api/"', request, response ); if (matchesFilter) { sdk.console.log(`${request.getRaw().toBytes()}`); sdk.console.log(`${request.getRaw().toText()}`); if (response) { sdk.console.log(`${response.getRaw().toBytes()}`); sdk.console.log(`${response.getRaw().toText()}`); } } else { sdk.console.log(`Request does not match the filter.`); } } } ``` ::: ### Creating and Sending a Request ```js export async function run({ request, response, extra }, sdk) { if (request) { let spec = new RequestSpec('https://example.com/endpoint?parameter=value'); // Caido will infer the scheme, host, path, and query from the URL parameter. // The default HTTP method is GET and requests without an explicit path will be made to the web root. let resend = await sdk.requests.send(spec); } } ``` ### Modifying and Sending a Request ::: code-group ```js [Request Elements] export async function run({ request, response, extra }, sdk) { if (request) { let spec = request.toSpec(); let method = spec.setMethod('GET'); let path = spec.setPath('/endpoint'); let query = spec.setQuery('parameter=value'); let port = spec.setPort(80); let host = spec.setHost('www.example.com'); let tls = spec.setTls(false); let header = spec.setHeader('Custom-Header', '123ABC321XYZ'); let resend = await sdk.requests.send(spec); } } ``` ```js [Removing a Header] export async function run({ request, response, extra }, sdk) { if (request) { let spec = request.toSpec(); spec.removeHeader('If-None-Match'); let resend = await sdk.requests.send(spec); } } ``` ::: ### Adding or Modifying Request Body Data ::: code-group ```js [String] export async function run({ request, response, extra }, sdk) { if (request) { let spec = request.toSpec(); let body = new Body('{"parameter":"value"}'); // The inclusion of the `updateContentLength` parameter is optional and its default value is `true`. let options = {updateContentLength: true}; spec.setBody(body, options); let resend = await sdk.requests.send(spec); } } ``` ```js [Number] export async function run({ request, response, extra }, sdk) { if (request) { let spec = request.toSpec(); let body = new Body([123, 34, 112, 97, 114, 97, 109, 101, 116, 101, 114, 34, 58, 34, 118, 97, 108, 117, 101, 34, 125]); let options = {updateContentLength: true}; spec.setBody(body, options); let resend = await sdk.requests.send(spec); } } ``` ```js [Uint8Array] export async function run({ request, response, extra }, sdk) { if (request) { let spec = request.toSpec(); let body = new Body(new Uint8Array([123, 34, 112, 97, 114, 97, 109, 101, 116, 101, 114, 34, 58, 34, 118, 97, 108, 117, 101, 34, 125])); let options = {updateContentLength: true}; spec.setBody(body, options); let resend = await sdk.requests.send(spec); } } ``` ::: ### Parsing JSON from Body Data ::: code-group ```js [Request Body] export async function run({ request, response, extra }, sdk) { if (request) { try { let body = request.getBody(); sdk.console.log(`Length: ${body.length}`); let jsonData = body.toJson(); sdk.console.log(`Username: ${jsonData.username}`); sdk.console.log(`Password: ${jsonData.password}`); sdk.console.log(`Role: ${jsonData.role}`); } catch (error) { sdk.console.error('Body is not valid JSON'); } } } ``` ```js [Response Body] export async function run({ request, response, extra }, sdk) { if (response) { try { let body = response.getBody(); sdk.console.log(`Length: ${body.length}`); let jsonData = body.toJson(); sdk.console.log(`Status: ${jsonData.status}`); sdk.console.log(`User ID: ${jsonData.userId}`); sdk.console.log(`Message: ${jsonData.message}`); } catch (error) { sdk.console.error('Body is not valid JSON'); } } } ``` ::: *** ### Creating Replay Sessions ::: code-group ```js [Default Collection] export async function run({ request, response, extra }, sdk) { if (request) { let session = await sdk.replay.createSession(request); sdk.console.log(`Created replay session with ID: ${session.getId()}`); } } ``` ```js [First Custom Collection] export async function run({ request, response, extra }, sdk) { if (request) { let collections = await sdk.replay.getCollections(); let session = await sdk.replay.createSession(request, collections[1]); sdk.console.log(`Created replay session in ${collections[1].getName()}`); } } ``` ```js [Custom Collection by Name] export async function run({ request, response, extra }, sdk) { if (request) { let collections = await sdk.replay.getCollections(); let targetCollection = collections.find(col => col.getName() === "Queries"); if (targetCollection) { let session = await sdk.replay.createSession(request, targetCollection); sdk.console.log(`Created replay session in ${targetCollection.getName()} collection.`); } else { sdk.console.log('Collection not found.'); } } } ``` ::: ## Findings The `findings` interface provides methods for handling findings. ### Creating Findings ::: code-group ```js [Creating a Finding] export async function run({ request, response, extra }, sdk) { if (request) { let finding = { title: `Request Monitor Passive Workflow.`, description: `Request ${request.getId()} ${request.getMethod()} ${request.getPath()} to ${request.getHost()} was sent.`, reporter: "Request Monitor", request: request }; await sdk.findings.create(finding); } } ``` ```js [Avoiding Duplicates] export async function run({ request, response, extra }, sdk) { if (request) { let finding = { title: `Request Monitor Passive Workflow.`, description: `Request ${request.getId()} ${request.getMethod()} ${request.getPath()} to ${request.getHost()} was sent.`, reporter: "Request Monitor", request: request, dedupeKey: `monitor-${request.getHost()}` }; let created = await sdk.findings.create(finding); if (created) { sdk.console.log('New finding created'); } else { sdk.console.log('Finding already exists (deduplicated)'); } } } ``` ::: ### Obtaining Finding Data ::: code-group ```js [Last Finding for Request by Reporter] // Active workflow selected via request context menu. export async function run({ request, response, extra }, sdk) { if (request) { // Get finding for this request from "Request Monitor" reporter let finding = await sdk.findings.get({ reporter: "Request Monitor", request: request }); if (finding) { sdk.console.log(`Finding ID: ${finding.getId()}`); sdk.console.log(`Title: ${finding.getTitle()}`); sdk.console.log(`Description: ${finding.getDescription()}`); sdk.console.log(`Reporter: ${finding.getReporter()}`); sdk.console.log(`Request ID: ${finding.getRequestId()}`); sdk.console.log(`Dedupe Key: ${finding.getDedupeKey()}`); } else { sdk.console.log('No finding found for this request from Request Monitor'); } } } ``` ```js [Most Recent Finding] export async function run({ request, response, extra }, sdk) { const result = await sdk.graphql.execute(` query GetMostRecentFinding { findings(first: 1, order: { by: CREATED_AT, ordering: DESC }) { edges { node { id title description reporter createdAt } } } } `); if (result.data?.findings?.edges?.length > 0) { const recentFinding = result.data.findings.edges[0].node; sdk.console.log(`Finding ID: ${recentFinding.id}`); sdk.console.log(`Title: ${recentFinding.title}`); sdk.console.log(`Description: ${recentFinding.description}`); sdk.console.log(`Reporter: ${recentFinding.reporter}`); sdk.console.log(`Created At: ${recentFinding.createdAt}`); } else { sdk.console.log('No findings found'); } } ``` ::: ## Projects The `projects` interface returns data about your Caido projects. ### Obtaining Project Data ```js export async function run({ request, response, extra }, sdk) { let currentProject = await sdk.projects.getCurrent(); sdk.console.log(`Project ID: ${currentProject.getId()}`); sdk.console.log(`Version: ${currentProject.getVersion()}`); sdk.console.log(`Current Project: ${currentProject.getName()}`); sdk.console.log(`Data Storage Location: ${currentProject.getPath()}`); sdk.console.log(`Status: ${currentProject.getStatus()}`); } ``` ## Environments The `env` interface provides methods for handling environment variables across the environments in your project. ### Set an Environment Variable ```js [Set Environment Variable] export async function run({ request, response, extra }, sdk) { if (response) { let body = response.getBody(); let jsonData = body.toJson(); // Set userId in response body as environment variable. // By default, it will be set in the Global environment. // Use env: to specify a custom environment. await sdk.env.setVar({ name: 'USER_ID', value: jsonData.userId.toString(), secret: false, global: true }); sdk.console.log(`User ID ${jsonData.userId} saved to Global environment.`); } } ``` ### Obtain Environment Variable Data ```js [Get All Variables] export async function run({ request, response, extra }, sdk) { let variables = sdk.env.getVars(); sdk.console.log(`Found ${variables.length} environment variables:`); variables.forEach(variable => { sdk.console.log(`Name: ${variable.name}`); sdk.console.log(`Value: ${variable.value}`); sdk.console.log(`Is Secret: ${variable.isSecret}`); sdk.console.log('---'); }); } ``` ### Use an Environment Variable ```js export async function run({ request, response, extra }, sdk) { if (request) { let apiKey = sdk.env.getVar('API_KEY'); if (apiKey) { let spec = request.toSpec(); spec.setHeader('Authorization', `Bearer ${apiKey}`); let result = await sdk.requests.send(spec); if (result && result.request) { sdk.console.log(`${result.request.getRaw().toText()}`); } if (result && result.response) { sdk.console.log(`${result.response.getRaw().toText()}`); } } else { sdk.console.log('API_KEY not found.'); } } } ``` ## Scopes The `scope` interface provides methods for handling scope presets in your project. ### Obtaining Scope Preset Data ::: code-group ```js [All Scope Names] export async function run({ request, response, extra }, sdk) { let scopes = await sdk.scope.getAll(); scopes.forEach(scope => { sdk.console.log(`Scope: ${scope.name}`); }); } ``` ```js [Scope Details] export async function run({ request, response, extra }, sdk) { let scopes = await sdk.scope.getAll(); scopes.forEach(scope => { sdk.console.log(`Scope Name: ${scope.name}`); sdk.console.log(`ID: ${scope.id}`); sdk.console.log(`Allowlist: ${JSON.stringify(scope.allowlist)}`); sdk.console.log(`Denylist: ${JSON.stringify(scope.denylist)}`); sdk.console.log('---'); }); } ``` ::: ### Updating a Scope Preset ::: code-group ```js [Adding a Domain to the Denylist] export async function run({ request, response, extra }, sdk) { if (request) { let host = request.getHost(); // Check if host contains "cdn". if (host.includes('cdn')) { let scopes = await sdk.scope.getAll(); // Find the scope preset named "Target". let targetScope = scopes.find(scope => scope.name === "Target"); if (targetScope) { if (!targetScope.denylist.includes(host)) { let updatedDenylist = [...targetScope.denylist, host]; const result = await sdk.graphql.execute(` mutation UpdateScope($id: ID!, $input: UpdateScopeInput!) { updateScope(id: $id, input: $input) { scope { id name denylist } } } `, { id: targetScope.id, input: { name: targetScope.name, allowlist: targetScope.allowlist, denylist: updatedDenylist } }); if (result.data?.updateScope?.scope) { sdk.console.log(`Added ${host} to Target scope denylist`); } else if (result.errors) { sdk.console.error(`Error updating scope: ${JSON.stringify(result.errors)}`); } } else { sdk.console.log(`${host} already in denylist`); } } else { sdk.console.error('Target scope not found'); } } } } ``` ::: ## Additional Input The `Extra (map)` configuration provides additional data as input. ### Referencing Output of an Upstream Node To include the output data of an upstream node **click** on the button to the right of `Extra (map)` and type in a key name. Then, **click** on the button to the right of the key and select the output data alias of the upstream node. For example, to use the output of a `Shell` node (*in this case `echo 'Shell STDOUT'`*) the configuration will resemble: The data can then be referenced as a property of the `extra` input parameter (*in this case `extra.stdout`*): ```js export async function run({ request, response, extra }, sdk) { if (request) { let host = request.getHost(); let additional = sdk.asString(extra.stdout); sdk.console.log(`${host}-${additional}`); } return { data: null, extra }; } ``` ### Static Data To include additional static data **click** on the button to the right of `Extra (map)` and type in a key name. Then, **click** on the button to the right of the key and select the data type from the drop-down menu. For example, to use elements in an array (*in this case strings `B` and `C`*) the configuration will resemble: The data can then be referenced as a property of the `extra` input parameter (*in this case `extra.elements[0]` and `extra.elements[1]`*): ```js /** * @param {NodeInput} input * @param {SDK} sdk * @returns {MaybePromise} */ export function run({ data, extra }, sdk) { let input = sdk.asString(data); let first = sdk.asString(extra.elements[0]); let second = sdk.asString(extra.elements[1]); sdk.console.log(`Additional static data concat: ${input}-${first}-${second}`); return { data: `${input}-${first}-${second}`, extra }; } ``` --- --- url: /app/guides/workflows_shell.md description: >- A guide on using the Shell node in Caido workflows to run terminal commands and scripts. --- # Using the Shell Node The `Shell` node allows you to run terminal commands and scripts in Caido workflows. ## Shell Node Editor To select the terminal to use, **click** on the drop-down menu in the `Shell (choice)` section of the editor. ::: tip Use `echo $SHELL` to determine the appropriate selection. ::: The Shell node editor provides two coding environments: * `Code (code)`: The runtime commands/script with access to Caido provided data. * `Init (code)`: The optional initialization commands/script to execute before runtime (*such as creating nonexistent directories to save files to*). ::: warning NOTE By default, `Init (code)` sources from configuration files (`.bashrc`/`.zshrc`) to provide custom PATH variables and aliases. ::: *** ## Input The data made available to your terminal can either be: * The input data for convert workflows. * Environment variables or Base64 encoded request and response JSON object properties for passive/active workflows. ::: tip View the [Passing Data Between Nodes](/app/guides/workflows_references.md) guide to learn how to use the output of a workflow node as the input of a connected downstream node. ::: ## Testing/Debugging Shell Node Workflows To test the execution and debug your Shell node commands/scripts before using workflows against targets, provide mock requests and responses in the editors, and **click** on the Run button. ::: tip Monitor the [logs](/app/guides/logs_viewing.md) when debugging. ::: The details of each run will be listed in the `View` drop-down menu. To view the execution details of the Shell node, **click** on its associated button. ## Convert Workflows To convert data, run terminal commands/scripts against the input data. ### Base64 Encoding ::: code-group ```cmd [cmd] powershell -Command "$data = [Console]::In.ReadToEnd(); [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($data.TrimEnd()))" ``` ```powershell [powershell] $data = [Console]::In.ReadToEnd(); [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($data.TrimEnd())) ``` ```sh [sh] cat - | base64 ``` ```zsh [zsh] cat - | base64 ``` ```bash [bash] cat - | base64 ``` ```wsl [wsl] cat - | base64 ``` ::: ## Passive/Active Workflows ### Environment Variables Request URLs, headers, and the working project name are available via environment variables. #### URL to File ::: code-group ```cmd [cmd] echo %CAIDO_URL% > %USERPROFILE%\url.txt ``` ```powershell [powershell] $env:CAIDO_URL | Out-File -FilePath "$HOME\url.txt" ``` ```sh [sh] echo "$CAIDO_URL" > ~/url.txt ``` ```zsh [zsh] echo "$CAIDO_URL" > ~/url.txt ``` ```bash [bash] echo "$CAIDO_URL" > ~/url.txt ``` ```bash [wsl] echo "$CAIDO_URL" > ~/url.txt ``` ::: #### Project Name to File ::: code-group ```cmd [cmd] echo %CAIDO_PROJECT% > %USERPROFILE%\project.txt ``` ```powershell [powershell] $env:CAIDO_PROJECT | Out-File -FilePath "$HOME\project.txt" ``` ```sh [sh] echo "$CAIDO_PROJECT" > ~/project.txt ``` ```zsh [zsh] echo "$CAIDO_PROJECT" > ~/project.txt ``` ```bash [bash] echo "$CAIDO_PROJECT" > ~/project.txt ``` ```bash [wsl] echo "$CAIDO_PROJECT" > ~/project.txt ``` ::: #### Specific Header to File ::: code-group ```cmd [cmd] echo %CAIDO_REQUEST_HEADER__HOST% > %USERPROFILE%\host.txt ``` ```powershell [powershell] $env:CAIDO_REQUEST_HEADER__HOST | Out-File -FilePath "$HOME\host.txt" ``` ```sh [sh] echo "$CAIDO_REQUEST_HEADER__HOST" > ~/host.txt ``` ```zsh [zsh] echo "$CAIDO_REQUEST_HEADER__HOST" > ~/host.txt ``` ```bash [bash] echo "$CAIDO_REQUEST_HEADER__HOST" > ~/host.txt ``` ```bash [wsl] echo "$CAIDO_REQUEST_HEADER__HOST" > ~/host.txt ``` ::: #### All Headers to File ::: code-group ```cmd [cmd] set | findstr "CAIDO_REQUEST_HEADER__" > %USERPROFILE%\headers.txt ``` ```powershell [powershell] Get-ChildItem env: | Where-Object {$_.Name -like "CAIDO_REQUEST_HEADER__*"} | ForEach-Object { "$($_.Name)=$($_.Value)" } | Out-File -FilePath "$HOME\headers.txt" ``` ```sh [sh] env | grep "^CAIDO_REQUEST_HEADER__" > ~/headers.txt ``` ```zsh [zsh] env | while IFS='=' read -r name value; do   if [[ "$name" == CAIDO_REQUEST_HEADER__* ]]; then     echo "$name=$value"   fi done > ~/Desktop/formatted-headers.txt ``` ```bash [bash] env | grep "^CAIDO_REQUEST_HEADER__" > ~/headers.txt ``` ```bash [wsl] env | grep "^CAIDO_REQUEST_HEADER__" > ~/headers.txt ``` ::: #### All Headers to File Formatted ::: code-group ```cmd [cmd] set | findstr "CAIDO_REQUEST_HEADER__" > %USERPROFILE%\headers.txt ``` ```powershell [powershell] Get-ChildItem env: | Where-Object {$_.Name -like "CAIDO_REQUEST_HEADER__*"} | ForEach-Object { $name = $_.Name -replace '^CAIDO_REQUEST_HEADER__', '' -replace '_', '-' $name = (Get-Culture).TextInfo.ToTitleCase($name.ToLower()) "${name}: $($_.Value)" } | Out-File -FilePath "$HOME\formatted-headers.txt" ``` ```sh [sh] title_case() {  echo "$1" | awk -F'-' '{     for(i=1; i<=NF; i++) {       $i = toupper(substr($i,1,1)) tolower(substr($i,2))     }     print $0   }' | tr ' ' '-' } env | grep "^CAIDO_REQUEST_HEADER__" | while IFS='=' read -r name value; do   case "$name" in     CAIDO_REQUEST_HEADER__*)       header=$(echo "$name" | sed 's/^CAIDO_REQUEST_HEADER__//' | tr '_' '-' | tr '[:upper:]' '[:lower:]')       formatted_header=$(title_case "$header")       echo "$formatted_header: $value"       ;;   esac done > ~/Desktop/formatted-headers.txt ``` ```zsh [zsh] title_case() {  echo "$1" | awk -F'-' '{     for(i=1; i<=NF; i++) {       $i = toupper(substr($i,1,1)) tolower(substr($i,2))     }     print $0   }' | tr ' ' '-' } env | grep "^CAIDO_REQUEST_HEADER__" | while IFS='=' read -r name value; do   header=$(echo "$name" | sed 's/^CAIDO_REQUEST_HEADER__//' | tr '_' '-' | tr '[:upper:]' '[:lower:]')   formatted_header=$(title_case "$header")   echo "$formatted_header: $value" done > ~/Desktop/formatted-headers.txt ``` ```bash [bash] env | grep "^CAIDO_REQUEST_HEADER__" | while IFS='=' read -r name value; do header="${name#CAIDO_REQUEST_HEADER__}" header="${header//_/-}" header=$(echo "$header" | tr '[:upper:]' '[:lower:]' | sed 's/\b\(.\)/\U\1/g') echo "$header: $value" done > ~/formatted-headers.txt ``` ```bash [wsl] env | grep "^CAIDO_REQUEST_HEADER__" | while IFS='=' read -r name value; do header="${name#CAIDO_REQUEST_HEADER__}" header="${header//_/-}" header=$(echo "$header" | tr '[:upper:]' '[:lower:]' | sed 's/\b\(.\)/\U\1/g') echo "$header: $value" done > ~/formatted-headers.txt ``` ::: #### Running a Tool Against a Domain ::: code-group ```cmd [cmd] nslookup %CAIDO_REQUEST_HEADER__HOST% > "%USERPROFILE%\nslookup.txt" 2>&1 ``` ```powershell [powershell] nslookup $env:CAIDO_REQUEST_HEADER__HOST | Out-File -FilePath "$HOME\nslookup.txt" ``` ```sh [sh] nslookup $CAIDO_REQUEST_HEADER__HOST > $HOME/nslookup.txt ``` ```zsh [zsh] nslookup $CAIDO_REQUEST_HEADER__HOST > ~/nslookup.txt ``` ```bash [bash] nslookup $CAIDO_REQUEST_HEADER__HOST > ~/nslookup.txt ``` ```bash [wsl] nslookup $CAIDO_REQUEST_HEADER__HOST > ~/nslookup.txt ``` ::: #### Enumerating Subdomains ::: code-group ```cmd [cmd] %USERPROFILE%\go\bin\subfinder.exe -d %CAIDO_REQUEST_HEADER__HOST% -o %USERPROFILE%\subs.txt ``` ```powershell [powershell] & "$HOME\go\bin\subfinder.exe" -d $env:CAIDO_REQUEST_HEADER__HOST -o "$HOME\subs.txt" ``` ```sh [sh] ~/go/bin/subfinder -d "$CAIDO_REQUEST_HEADER__HOST" -o ~/subs.txt ``` ```zsh [zsh] ~/go/bin/subfinder -d "$CAIDO_REQUEST_HEADER__HOST" -o ~/subs.txt ``` ```bash [bash] ~/go/bin/subfinder -d "$CAIDO_REQUEST_HEADER__HOST" -o ~/subs.txt ``` ```bash [wsl] ~/go/bin/subfinder -d "$CAIDO_REQUEST_HEADER__HOST" -o ~/subs.txt ``` ::: ### Requests & Responses Raw requests and responses are available as a JSON object via STDIN. *** ::: warning NOTE The `request` and `response` JSON parameter data is Base64 encoded. * For **cmd**, use `powershell -Command` to execute PowerShell commands. * For **powershell**, use the built-in `ConvertFrom-Json` cmdlet (*no installation needed*). * For **bash/zsh/sh/wsl**, [install jq](https://jqlang.org/download/) to parse JSON. ::: #### Request to File ::: code-group ```cmd [cmd] powershell -Command "$json = [Console]::In.ReadToEnd() | ConvertFrom-Json; [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.request)) | Out-File -FilePath \"$env:USERPROFILE\request.txt\"" ``` ```powershell [powershell] $json = $input | ConvertFrom-Json [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.request)) | Out-File -FilePath "$HOME\request.txt" ``` ```sh [sh] cat - | jq -r .request | base64 -d > ~/request.txt ``` ```zsh [zsh] cat - | jq -r .request | base64 -d > ~/request.txt ``` ```bash [bash] cat - | jq -r .request | base64 -d > ~/request.txt ``` ```bash [wsl] cat - | jq -r .request | base64 -d > ~/request.txt ``` ::: #### Request Headers to File ::: code-group ```cmd [cmd] powershell -Command "$json = [Console]::In.ReadToEnd() | ConvertFrom-Json; $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.request)); $lines = $decoded -split \"`r`n\"; $lines[1..($lines.IndexOf('')-1)] | Out-File -FilePath \"$env:USERPROFILE\request-headers.txt\"" ``` ```powershell [powershell] $json = $input | ConvertFrom-Json $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.request)) $lines = $decoded -split "`r`n" $lines[1..($lines.IndexOf("")-1)] | Out-File -FilePath "$HOME\request-headers.txt" ``` ```sh [sh] cat - | jq -r .request | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/request-headers.txt ``` ```zsh [zsh] cat - | jq -r .request | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/request-headers.txt ``` ```bash [bash] cat - | jq -r .request | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/request-headers.txt ``` ```bash [wsl] cat - | jq -r .request | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/request-headers.txt ``` ::: #### Response to File ::: code-group ```cmd [cmd] powershell -Command "$json = [Console]::In.ReadToEnd() | ConvertFrom-Json; [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.response)) | Out-File -FilePath \"$env:USERPROFILE\response.txt\"" ``` ```powershell [powershell] $json = $input | ConvertFrom-Json [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.response)) | Out-File -FilePath "$HOME\response.txt" ``` ```sh [sh] cat - | jq -r .response | base64 -d > ~/response.txt ``` ```zsh [zsh] cat - | jq -r .response | base64 -d > ~/response.txt ``` ```bash [bash] cat - | jq -r .response | base64 -d > ~/response.txt ``` ```bash [wsl] cat - | jq -r .response | base64 -d > ~/response.txt ``` ::: #### Response Headers to File ::: code-group ```cmd [cmd] powershell -Command "$json = [Console]::In.ReadToEnd() | ConvertFrom-Json; $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.response)); $lines = $decoded -split \"`r`n\"; $lines[1..($lines.IndexOf('')-1)] | Out-File -FilePath \"$env:USERPROFILE\response-headers.txt\"" ``` ```powershell [powershell] $json = $input | ConvertFrom-Json $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.response)) $lines = $decoded -split "`r`n" $lines[1..($lines.IndexOf("")-1)] | Out-File -FilePath "$HOME\response-headers.txt" ``` ```sh [sh] cat - | jq -r .response | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/response-headers.txt ``` ```zsh [zsh] cat - | jq -r .response | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/response-headers.txt ``` ```bash [bash] cat - | jq -r .response | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/response-headers.txt ``` ```bash [wsl] cat - | jq -r .response | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/response-headers.txt ``` ::: #### Response Body to File ::: code-group ```cmd [cmd] powershell -Command "$json = [Console]::In.ReadToEnd() | ConvertFrom-Json; $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.response)); $bodyStart = $decoded.IndexOf(\"`r`n`r`n\") + 4; $body = $decoded.Substring($bodyStart); $body | Out-File -FilePath \"$env:USERPROFILE\response-body.txt\"" ``` ```powershell [powershell] $json = $input | ConvertFrom-Json $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($json.response)) $bodyStart = $decoded.IndexOf("`r`n`r`n") + 4 $body = $decoded.Substring($bodyStart) $body | Out-File -FilePath "$HOME\response-body.txt" ``` ```sh [sh] cat - | jq -r .response | base64 -d | sed -n '2,/^\r$/p' | sed '/^\r$/d' > ~/response-headers.txt ``` ```zsh [zsh] cat - | jq -r .response | base64 -d | sed '1,/^\r$/d' > ~/response-body.txt ``` ```bash [bash] cat - | jq -r .response | base64 -d | sed '1,/^\r$/d' > ~/response-body.txt ``` ```bash [wsl] cat - | jq -r .request | base64 -d > ~/request.txt ``` ::: --- --- url: /app/guides/replay_workflows.md description: >- A step-by-step guide to applying workflows to Replay requests in Caido for dynamic value modification and automated request processing. --- # Using Workflows in Replay ## ::: tip Video Demonstration To apply a workflow to a value in a Replay request, **click**, **hold**, and **drag** over the value you want to replace and **click** the `+` button to add it as a placeholder. Then, **click** on the associated edit button of the placeholder to open the `Placeholder Settings` window. With `Workflow` as the `Type`, **click** on the `Select a workflow` drop-down menu, select a workflow from the list, and **click** `Add` to save the configuration. Applied workflows are listed and will be applied in top to bottom order. To avoid collisions between workflows, you can rearrange their order by **left-clicking**, **dragging**, **holding**, and **releasing** a workflow either above or below other workflows in the list. Close the settings window and send the request. To verify the application was successful, you can view the request by navigating to the Search interface. --- --- url: /app/guides/zeroomega.md description: >- A step-by-step guide to installing and configuring the ZeroOmega browser extension for Chrome and Firefox. --- # Using ZeroOmega The ZeroOmega browser extension gives you the ability to quickly enable/disable your browser's use of Caido as a proxy. ## Chrome To install the browser extension, launch the Chrome browser, navigate to , and **click** on the `Add to Chrome` button. In the pop-up window, **click** on the `Add extension` button. Once the extension is installed, **click** on the button in the top-right corner of the browser window, and then either **click** on the button or **right-click** on the extension and select `Pin to Toolbar`. Then, [continue to the configuration instructions](#configuring-zeroomega). ## Firefox To install the browser extension, launch the Firefox browser, navigate to , and **click** on the `Add to Firefox` button. In the pop-up window, select `Allow extension to run in private windows`, and then **click** on the `Add` button. In the subsequent pop-up window, **click** on the `OK` button. Once the extension is installed, [continue to the configuration instructions](#configuring-zeroomega). ## Configuring ZeroOmega Either continue with the `Welcome to ZeroOmega` tutorial or **click** on the `Skip guide` or `X` button to close the pop-up window. Next, select the `proxy` profile tab, change the value of the `Server` input field to Caido's default listening IP address of `127.0.0.1`, and **click** on the Apply changes button to update and save the configuration. ## Enabling/Disabling Proxying To enable proxying to pass web traffic through Caido, **click** on the ZeroOmega toolbar button and select proxy. To disable proxying, select the \[Direct] option. --- --- url: /app/guides/sitemap_viewing.md description: >- A step-by-step guide to viewing and navigating Caido's sitemap interface including domain expansion, request viewing, and search functionality. --- # Viewing a Sitemap To view the root domain or subdomains of a Sitemap, reveal the child nodes of a root node by **clicking** on the button attached to it. ::: info The lock icon represents connections via HTTPS. ::: To view the content of a specific Fully Qualified Domain Name (FQDN), continue revealing the child nodes by **clicking** on the buttons attached to the parent nodes. **Clicking** on a node will reveal its associated requests in the traffic table. Select a request row to view the request and its corresponding response. ::: tip You can search for a specific Sitemap by typing its Fully Qualified Domain Name (FQDN) in the Search domain... input field. ::: --- --- url: /app/guides/logs_viewing.md description: A step-by-step guide to viewing both the frontend and backend Caido log files. --- # Viewing Logs As Caido utilizes a [client/server architecture](/app/concepts/instance.md), both frontend and backend logs are produced. ::: danger As log files can contain sensitive information, only send them in private conversations with a verified member of the Caido team. If you are contacting us on Discord, we will open a private channel before asking for logs. ::: ::: warning NOTE Ensure to [enable debug mode](/app/troubleshooting/debugging.md) to assist with troubleshooting. ::: ## Backend Logs To view the backend log files of your instance, either: * Navigate to the `/logs` subdirectory of the data storage directory. The default location of this directory is dependent on your operating system: | OS | Location | | ------- | ------------------------------------------------ | | Linux | `~/.local/share/caido` | | MacOS | `~/Library/Application\ Support/io.caido.Caido/` | | Windows | `%APPDATA%\Caido\Caido\data` | * Or, **click** on the Logs button in the desktop application user interface and **click** on the Record button to capture the backend logs for a certain interval of time. To save the recording, **click** on the button. ## Frontend Logs To view the frontend log files of your instance, access the DevTools interface by either: * Pressing the `F12` key. * Using the keybinding `CTRL` + `SHIFT` + `I`. * Or, selecting `Inspect` from the **right-click** context menu. To save the frontend logs, **right-click** within the `Console` and select `Save as...`/`Save all Messages to File`/etc. to export the messages as a `.log` file. --- --- url: /app/guides/http_history_modifications.md description: >- A step-by-step guide to viewing modifications made to requests and responses in Caido's HTTP History interface using the Original Request dropdown menu. --- # Viewing Modifications ::: info Traffic that has been modified can be quickly identified by the presence of `Edited` in the `State` column of the traffic table. ::: To view any modifications that have made to requests or responses, or the original state, **click** on the `Original Request` drop-down menu and select an option. --- --- url: /app/guides/search_modifications.md description: >- A step-by-step guide to viewing modifications made to requests and responses in Caido's Search interface using the Original Request dropdown menu. --- # Viewing Modifications To view any modifications that have made to requests or responses, or the original state, **click** on the `Original Request` drop-down menu and select an option. --- --- url: /app/quickstart.md description: >- An introduction to Caido and download and installation instructions for Windows, Linux, and macOS. --- # Welcome to Caido! ## What is Caido? Caido is a lightweight web security auditing toolkit, built *by hackers for hackers*. Normally, users interact with web applications in a manner intentionally designed by developers. Web applications expect certain requests and will reply with programmatically predetermined responses. With Caido, you gain the unexpected ability to view, intercept, and modify the bidirectional communication between your browser and servers hosting web applications. It is through this subversion of expectations that you can find weaknesses in systems. ## Who is Caido for? **Anyone.** With its intiutive design, Caido makes web application hacking accessible to beginners. While its comprehensive set of features and extensibility equip experienced security professionals with the tools they need to streamline their workflows. ## Get Started We are excited to have you here. Let's get you onboarded. To start using Caido, continue with the download and installation instructions for your operating system: * [Caido for Windows](/app/quickstart/windows.md) * [Caido for Linux](/app/quickstart/linux.md) * [Caido for macOS](/app/quickstart/mac.md) --- --- url: /app/concepts/workflow_flow.md description: >- Understand the core concepts behind workflow execution order and data flow in Caido - sequential node processing and data referencing between nodes. --- # Workflow Execution and Data Flow ::: info [Learn the difference between plugins and workflows in Caido.](https://developer.caido.io/concepts/workflow) ::: The order of workflow operation can be split into two concepts: ## Workflow Execution A workflow processes nodes in sequential order: 1. Beginning at the root of the Node tree with an entry node. 2. Every subsequent node in the chain is processed in order. The execution may take the path of another branch based on conditionals. 3. The workflow ends either when it reaches an explicit exit node or when no more nodes are available in the chain. ## Workflow Data Flow Each node in a workflow has an input and output data type. ::: info [Learn more about the node data types.](/app/reference/workflow_data_types.md) ::: With this typed data system, even though nodes are processed sequentially, you do not need a direct line between two nodes in order to pass data from one to another. Instead, data can be referenced using dot notation of a node's alias and it's output alias: ```text $[node_alias].[output_alias] ``` ::: tip You can view the data type by **clicking** on a node and viewing the value within the parenthesis next to the name of the object. ::: --- --- url: /app/reference/workflow_data_types.md description: >- Find detailed reference information on workflow node data types and their compatibility conversions in Caido workflow automation. --- # Workflow Node Data Types Nodes are defined by various different input and output data types. When referencing a node's data for use in another, the types must be compatible with each other. ## Data Type Conversions Data can be shared across nodes as long as the types are `Exact` (*expected*) or are `Compatible` based on the following conversions: ::: tip You can view the data type by **clicking** on a node and viewing the value within the parenthesis. This will be above the reference data drop-down menu. ::: ::: info [View the SDK for the types here.](https://developer.caido.io/reference/sdks/workflow/data) ::: ### String Strings are compatible with: | Type | Description | |------|-------------| | String: Choice | Variation of string. | | String: Code | Variation of string. | | Bytes | Encoded as UTF-8 with lossy conversion (invalid characters are replaced with `�`). | | Bool | Converts to `"true"` or `"false"`. | | Integer | Base-10 decimal encoding. | ### Bytes Bytes are compatible with: | Type | Description | |------|-------------| | String | UTF-8 encoded bytes. | | Bool | Converts to `"true"` or `"false"` in bytes. | | Integer | First converts to string type and then to UTF-8 encoded bytes. | ### Bool Booleans are compatible with: | Type | Description | |------|-------------| | Integer | Is `true` if integer is not zero - otherwise `false`. | | Bytes/String | Is `true` for `"true"`, `"on"`, `"yes"`, and `"1"` - otherwise `false`. | ### Integer Integers are compatible with: | Type | Description | |------|-------------| | Bool | Is `true` if integer is `1` - `false` if `0`. | | Bytes | Converted to string loosely, supports hex (`0x`), binary (`0b`), octal (`0o`), supports sign (`+`, `-`). | | String | Parsed from string, supports hex (`0x`), binary (`0b`), octal (`0o`), supports sign (`+`, `-`). | ### Float Floats are compatible with: | Type | Description | |------|-------------| | Integer | Converted to float (e.g., `1` becomes `1.0`). | | String | Parsed from string as decimal number, supports scientific notation and sign (`+`, `-`). | ### Map There is no conversion besides their own. ### Array There is no conversion besides their own. ### Request & Responses There is no conversion besides their own. --- --- url: /app/reference/workflow_nodes.md description: >- Find detailed reference information on Caido workflow nodes including JavaScript, Shell, If/Else, and other automation components. --- # Workflow Nodes ## Passive Workflow Nodes | Node | Description | |------|-------------| | On Intercept Request | Triggers a workflow when a request passes through the proxy. | | On Intercept Response | Triggers a workflow when a response passes through the proxy. | | Passive End | Ends the passive workflow. | | If/Else | Branches off based on the conditional output of a previous node. | | If/Else Javascript | Branches off based on a JavaScript condition. | | Javascript | Runs JavaScript. | | Shell | Runs a shell command. | | Check Finding | Checks if a finding already exists. | | Create Finding | Reports a finding to the system. | | In Scope | Checks if a request is in-scope. | | Matches HTTPQL | Matches a request/response against an HTTPQL query statement. | | Set Color | Sets the traffic table request row color. | | Logging | Prints a message to the logs. | ## Active Workflow Nodes | Node | Description | |------|-------------| | Active Start | Starts the active workflow. | | Active End | Ends the active workflow. | | If/Else | Branches off based on the conditional output of a previous node. | | If/Else Javascript | Branches off based on a JavaScript condition. | | Javascript | Runs JavaScript. | | Shell | Runs a shell command. | | Check Finding | Checks if a finding already exists. | | Create Finding | Reports a finding to the system. | | In Scope | Checks if a request is in-scope. | | Matches HTTPQL | Matches a request/response against an HTTPQL query statement. | | Set Color | Sets the traffic table request row color. | | Logging | Prints a message to the logs. | ## Convert Workflow Nodes | Node | Description | |------|-------------| | Convert Start | Starts conversion. | | Convert End | Ends conversion. | | If/Else | Branches off based on the conditional output of a previous node. | | If/Else Javascript | Branches off based on a JavaScript condition. | | Javascript | Runs JavaScript. | | Shell | Runs a shell command. | | Base64 Decode | Converts Base64-encoded data back to original format. | | Base64 Encode | Converts data to Base64-encoded format. | | Hex Decode | Converts hexadecimal strings back to original data. | | Hex Encode | Converts data to hexadecimal format. | | HTML Decode | Converts HTML entities back to original characters. | | HTML Encode | Converts text to HTML-safe encoded format. | | Join | Joins two elements. | | JSON Minify | Minifies JSON input. | | JSON Prettify | Prettifies JSON input. | | JWT Decode | Base64 decodes the header and payload segments of JSON Web Tokens. | | Match & Replace | Match and replace on input. | | MD5 Hash | Hashes input using MD5 algorithm. | | SHA1 Hash | Hashes input using SHA1 algorithm. | | SHA2 Hash | Hashes input using SHA2 algorithm. | | Trim | Trims input string. | | URL Decode | Converts URL-encoded text back to original characters. | | URL Encode | Converts text to URL-safe encoded format. | --- --- url: /app/concepts/workflows_intro.md description: >- Understand the core concepts behind Caido Workflows - creating customizable action sequences for passive, active, and convert operations in security testing. --- # Workflows **Workflows** provide an intuitive way to create, save and reuse customizable actions or sequences of actions that will be performed under certain specified conditions. With workflows, you have the ability to extend the functionality of Caido to suit your individual needs. As Caido utilizes a client/server architecture, the workflows you create are executed server-side - thereby offloading processing power, providing enhanced performance and allowing seamless usage across multiple devices. Workflows created by others can also be downloaded and imported into your Caido instance. *A workflow that will take user-provided input, base64 encode it and then output the results.* ## Passive Workflows `Passive` workflows take **requests** or **responses** as input. Their execution occurs in the "background" as you conduct your testing, extending the efficiency of your process. Passive workflows are **automatically triggered** when their specifications/conditions are met. If the specifications/conditions of the workflow are not met throughout every step of the workflow - the workflow will stop processing the request/response. These specifications/conditions are set by nodes and include prerequisites such as: * If the request/response is within a set scope. * If the request/response is a match according to [HTTPQL](/app/reference/httpql.md) syntax. * If the prior node's specification/condition evaluated to True or False (*Boolean value*). ## Active Workflows `Active` workflows also take **requests** or **responses** as input. However, they are manually triggered, usually by **right-clicking** on a request/response in the HTTP History or Search pages. ## Convert Workflows `Convert` workflows take on **bytes** as input. They will perform actions against the supplied input and output the results. --- --- url: /app/quickstart/workflows.md description: >- A step-by-step guide to Caido's Workflows feature for creating automated multi-step processes and task automation in security testing. --- # Workflows Within the `Workflows` interface, you can construct multi-step processes to execute certain actions or conversions, allowing you to automate tasks on an immediate, discretionary, or repeated basis. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Creating Workflows](/app/guides/workflows_creating.md) * [Creating Findings](/app/guides/workflows_findings.md) * [Passing Data Between Nodes](/app/guides/workflows_references.md) * [Using the JavaScript Node](/app/guides/workflows_javascript.md) * [Using the Shell Node](/app/guides/workflows_shell.md) ::: ::: warning STEP-BY-STEP TUTORIALS * [Send a Notification to Discord Workflow](/app/tutorials/discord_notification.md) * [Add a Header Workflow](/app/tutorials/add_header.md) * [Color Request Rows Workflow](/app/tutorials/color_requests.md) * [Refresh Authentication Workflow](/app/tutorials/refresh_authentication.md) * [Decode a JWT Workflow](/app/tutorials/decode_jwt.md) * [MD5 Hash Workflow](/app/tutorials/md5_hash.md) * [Resign AWS Requests Workflow](/app/tutorials/aws_signature.md) ::: --- --- url: /app/quickstart/workspace.md description: >- A step-by-step guide to Caido's Workspace interface for managing projects, backups, and instance data organization. --- # Workspace The `Workspace` interface lists all the Caido projects and any backups of your instance. ## ::: tip Video Demonstration ::: tip HOW-TO GUIDES * [Saving Projects](/app/guides/projects_backups.md) * [Recovering Read-Only Projects](/app/guides/projects_recovering.md) ::: --- --- url: /dashboard/concepts/workspace.md --- # Workspace Workspaces provide a central repository for various objects in the Caido ecosystem. Each User and Team gets a `Default` Workspace. It will eventually we possible to create more workspaces and assign access permissions to them. At the moment a Workspace can contain: * [Instances](/app/concepts/instance): An installation of Caido * [Registration Keys](./registration_key.md): Keys to automatically claim instances :::info The Workspace page in the application is **NOT** related to the concept of Dashboard Workspaces. ::: --- --- url: /app/guides/filters_httpql.md description: >- A guide on writing HTTPQL queries in Caido to filter rows in the traffic tables. --- # Writing HTTPQL Queries With HTTPQL, you can include or exclude traffic proxied through Caido from traffic tables and operations. HTTPQL query statements filter either requests (`req`), responses (`resp`), or specific table rows (`id`). The filtering is further refined by specifying an available field, operator, and comparison value, using dot notation. ```sql ..:"" ``` ::: warning NOTE These statements will serve as a starting point for your HTTPL queries. View the full [HTTPQL](/app/reference/httpql.md) reference to customize your query statements to achieve the intended results. ::: ## Filtering Requests by Host To filter requests made to `example.com`, use the `host` field. ::: code-group ```sql [Including] req.host.eq:"www.example.com" req.host.regex:"^example.com$" ``` ```sql [Excluding] req.host.ne:"www.example.com" req.host.nregex:"^example.com$" ``` ```sql [Including All Subdomains] req.host.cont:".example.com" req.host.like:"%.example.com" ``` ```sql [Excluding All Subdomains] req.host.ncont:".example.com" req.host.nlike:"%.example.com" ``` ::: ## Filtering Requests by Time To filter requests by date/time, use the `created_at` field. ::: code-group ```sql [Request Before Dec 5th 2025] req.created_at.lt:"2025-12-05" ``` ```sql [Request After Dec 5th 2025] req.created_at.gt:"2025-12-05" ``` ```sql [Requests Before Dec 5th 2025 8:30AM] req.created_at.lt:"2025-12-05T08:30:00+00:00" ``` ```sql [Requests After Dec 5th 2025 After 8:30AM] req.created_at.gt:"2025-12-05T08:30:00+00:00" ``` ::: ## Filtering Responses by Status Code To filter responses by status code, use the `code` field. ::: code-group ```sql [Including 200] resp.code.eq:200 ``` ```sql [Excluding 200] resp.code.ne:200 ``` ::: To specify a range of status codes, use the `gt`, `lt`, `gte`, or `lte` operators. ## Filter Requests by ID To filter traffic by the numerical table row value, use the `id` field. ::: code-group ```sql [Include a Specific Request] row.id.eq:50 ``` ```sql [Exclude a Specific Request] row.id.ne:50 ``` ```sql [Subsequent Requests] row.id.gt:50 ``` ```sql [Prior Requests] row.id.lt:50 ``` ::: To include the specific request ID, use the `gte` or `lte` operators. ## Filter by Request/Response Content To match against a value in a full request or response, use the `raw` field. ::: code-group ```sql [Include Requests with JSON Body Data] req.raw.cont:"application/json" ``` ```sql [Include Responses with isAdmin: true] resp.raw.cont:"\"isAdmin\":true" ``` ::: --- --- url: /app/quickstart/ws_history.md description: >- A step-by-step guide to Caido's WebSocket History interface for viewing and analyzing all proxied WebSocket streams and messages. --- # WS History The `WS History` interface provides a table that contains all of the WebSocket streams and associated messages that have been proxied through Caido.