Skip to content

Configuration

GraphQLer reads a TOML file passed with --config. Without it, <PATH>/config.toml is used if present, otherwise one is generated there. CLI flags override the file, and the resolved configuration is written back to <PATH>/config.toml on every run.

Common settings

Variable Description Type Default
MAX_LEVENSHTEIN_THRESHOLD Levenshtein distance for matching object names to ID inputs Integer 20
MAX_OBJECT_CYCLES Max times the same object is materialised in one query/mutation Integer 5
MAX_OUTPUT_SELECTOR_DEPTH Max depth of output selections (guards against recursive types) Integer 5
USE_OBJECTS_BUCKET Store returned objects for later requests Boolean true
USE_DEPENDENCY_GRAPH Order requests using the dependency graph Boolean true
ALLOW_DELETION_OF_OBJECTS Remove objects from the bucket after a successful DELETE Boolean false
MAX_FUZZING_ITERATIONS Number of sweeps through all chains Integer 1
MAX_TIME Maximum run time in seconds Integer 3600
REQUEST_TIMEOUT Per-request timeout in seconds Integer 120
TIME_BETWEEN_REQUESTS Minimum delay between requests in seconds Float 0.001
DEBUG Debug mode Boolean false
SKIP_MAXIMAL_PAYLOADS Skip payloads that request every possible output field Boolean false
SKIP_DOS_ATTACKS Skip DoS detections (on by default to avoid taking the service down) Boolean true
SKIP_INJECTION_ATTACKS Skip injection detections Boolean false
SKIP_MISC_ATTACKS Skip miscellaneous detections Boolean false
SKIP_ENUMERATION_ATTACKS Skip field-charset and ID enumeration detections (many requests per node) Boolean true
SKIP_SUBSCRIPTIONS Skip subscription fuzzing (--subscriptions enables it) Boolean true
SUBSCRIPTION_PROTOCOL graphql-transport-ws or legacy subscriptions-transport-ws String graphql-transport-ws
SKIP_NODES Query/mutation names to skip List []
DISABLE_MUTATIONS Only generate and run Query chains (--disable-mutations) Boolean false
SAVE_ENDPOINT_RESULTS Write per-endpoint result files Boolean true
IDOR_SECONDARY_AUTH Secondary (attacker) token for IDOR chains String unset
SKIP_IDOR_CHAIN_FUZZING Disable the IDOR chain phase Boolean false
SKIP_UAF_CHAIN_FUZZING Disable the use-after-delete chain phase Boolean false
[CUSTOM_HEADERS] Headers sent with every request Table Accept = "application/json"

LLM settings are described in LLM features.

Custom headers

[CUSTOM_HEADERS]
Accept = "application/json"
Cookie = "session=abc123"
X-Api-Key = "secret"

Authentication profiles

--auth sets the primary Authorization header. Named profiles are passed as profile=token:

python -m graphqler --mode run --url <URL> \
  --auth 'primary=Bearer <VICTIM_TOKEN>' \
  --auth 'secondary=Bearer <ATTACKER_TOKEN>'

primary is the default identity; secondary is equivalent to --idor-auth and enables IDOR chains.

Example configuration

An annotated example shipped with GraphQLer (graphqler/examples/config.toml). Defaults in the table above come from graphqler/config.py.

# Configuration

# For debugging purposes
DEBUG = false

# For clairvoyance
WORDLIST_PATH = "static/wordlist.txt"

# For the resolver
MAX_LEVENSHTEIN_THRESHOLD = 20  # A very high threshold, we could probably lower this, but this almost guarantees us to find a matching object name - ID

# ── LLM-based dependency resolver (opt-in) ────────────────────────────────────
# When enabled, GraphQLer sends the full schema to an LLM and asks it to infer
# dependency relationships (hardDependsOn / softDependsOn / mutationType).
# This catches cases the classic ID-name-matching resolver misses:
#   - String inputs that semantically reference an object (e.g. userEmail → User)
#   - Unconventional mutation verb names (provision, wipe, spawn → CREATE/DELETE)
#   - Non-English or domain-specific naming
#
# Model string uses litellm format (provider/model):
#   OpenAI:         "gpt-4o-mini"                        + LLM_API_KEY or OPENAI_API_KEY env var
#   Anthropic:      "anthropic/claude-3-5-haiku-20241022" + LLM_API_KEY or ANTHROPIC_API_KEY env var
#   Ollama (local): "ollama/llama3"                      + LLM_BASE_URL = "http://localhost:11434"
#   LiteLLM proxy:  "openai/my-model"                   + LLM_BASE_URL = "http://my-proxy:4000"
# ──────────────────────────────────────────────────────────────────────────────
USE_LLM = false                       # master toggle
LLM_USE_FOR_COMPILATION = true        # when USE_LLM=true, apply LLM in compilation phase (dependency resolver, IDOR/UAF chain classifiers)
LLM_USE_FOR_FUZZING = true            # when USE_LLM=true, apply LLM in fuzzing phase (payload generation, error retry, endpoint classification, reporting)
LLM_MODEL = "gpt-4o-mini"            # litellm model string
LLM_API_KEY = ""                      # API key; if empty, reads from env (OPENAI_API_KEY, etc.)
LLM_BASE_URL = ""                     # custom base URL (required for Ollama / LiteLLM proxies)
LLM_RESOLVER_FALLBACK_TO_ID = true    # fall back to classic resolver if LLM call fails
LLM_RESOLVER_SAVE_COMPARISON = true   # save eval/resolver_comparison.json (LLM vs classic diff)
LLM_MAX_RETRIES = 2                   # retry attempts when LLM returns non-JSON (0 = no retries)

# For the linker
GRAPH_VISUALIZATION_OUTPUT = "dependency_graph.png"

# For materializers
MAX_OBJECT_CYCLES = 3
MAX_OUTPUT_SELECTOR_DEPTH = 3
HARD_CUTOFF_DEPTH = 20
MAX_INPUT_DEPTH = 20

# For using GraphQLer in different modes
USE_OBJECTS_BUCKET = true  # Ablation: set false to disable state tracking (objects bucket)
USE_DEPENDENCY_GRAPH = true  # Ablation: set false to run all nodes without chain ordering
NO_DATA_COUNT_AS_SUCCESS = false  # Count empty data responses as successes
DISABLE_MUTATIONS = false  # When true, only Query chains are generated — all Mutation nodes are excluded from fuzzing

# For fuzzing
ALLOW_DELETION_OF_OBJECTS = false  # Remove deleted objects from bucket after a successful DELETE mutation
MAX_FUZZING_ITERATIONS = 1  # Number of times to iterate through all chains (increase for more coverage)
MAX_TIME = 3600  # in seconds
SKIP_MAXIMAL_PAYLOADS = false # This mode is for when we want to skip the maximal payloads
SKIP_DOS_ATTACKS = true # This mode is for when we want to skip the DoS check
SKIP_INJECTION_ATTACKS = false # This mode is for when we want to skip the injection check
SKIP_MISC_ATTACKS = false # This mode is for when we want to skip the miscellaneous attacks
SKIP_SUBSCRIPTIONS = true         # Disable subscription fuzzing by default (requires WebSocket support); enable with --subscriptions
SUBSCRIPTION_TIMEOUT = 1          # Seconds to wait for events on each subscription
SUBSCRIPTION_PROTOCOL = "graphql-transport-ws"  # "graphql-transport-ws" (modern) or "subscriptions-transport-ws" (legacy Apollo)

# For stats output
SAVE_ENDPOINT_RESULTS = true  # Set false to skip writing per-endpoint result files (can be large)

# For each request
REQUEST_TIMEOUT = 120  # in seconds
TIME_BETWEEN_REQUESTS = 0.001  # in seconds

# ── Chain-based IDOR detection (cross-user access testing) ───────────────────
# When IDOR_SECONDARY_AUTH is set, the compiler generates IDOR candidate chains
# during compilation and saves them to chains.yml.  The fuzzer then runs the
# setup nodes with the primary token (victim) so that resources are created,
# and the test nodes with the secondary token (attacker) to check for IDOR.
#
# Usage:
#   Set IDOR_SECONDARY_AUTH to the attacker's Bearer token, OR pass it via the
#   --idor-auth CLI flag (which takes precedence).
#
# Heuristic scoring signals (0.0–1.0):
#   +0.5  CREATE mutation output type matches the test node's input type
#   +0.3  test node name contains private-resource keywords (user/order/profile…)
#   +0.2  test node accepts an ID/Int parameter
#   -0.2  test node name contains public-resource keywords (list/public/catalog…)
#
# Chains scoring below IDOR_HEURISTIC_CONFIDENCE_THRESHOLD are sent to the LLM
# classifier when IDOR_USE_LLM_FALLBACK = true (requires USE_LLM = true).
# ──────────────────────────────────────────────────────────────────────────────
IDOR_SECONDARY_AUTH = ""              # Attacker/secondary Bearer token; empty = IDOR phase skipped
SKIP_IDOR_CHAIN_FUZZING = false       # Set true to disable the IDOR phase even when a secondary token is configured
IDOR_HEURISTIC_CONFIDENCE_THRESHOLD = 0.5  # Chains below this score trigger LLM fallback (when enabled)
IDOR_USE_LLM_FALLBACK = false         # Use LLM classifier for low-confidence chains (requires USE_LLM = true)

# For custom skipping specific nodes"""
SKIP_NODES = []

# Put custom headers here
[CUSTOM_HEADERS]
Accept = "application/json"