GHSA-3G9H-9HP4-654V
Vulnerability from github – Published: 2026-03-18 20:11 – Updated: 2026-03-25 18:12Summary
The SiYuan kernel WebSocket server accepts unauthenticated connections when a specific “auth keepalive” query parameter is present. After connection, incoming messages are parsed using unchecked type assertions on attacker-controlled JSON.
A remote attacker can send malformed messages that trigger a runtime panic, potentially crashing the kernel process and causing denial of service.
Details
1. Authentication Bypass via Keepalive Query
Unauthenticated connections are accepted if the request URI matches a specific pattern intended for an authentication page keepalive.
File: kernel/server/serve.go
if !authOk {
authOk = strings.Contains(s.Request.RequestURI, "/ws?app=siyuan") &&
strings.Contains(s.Request.RequestURI, "&id=auth&type=auth")
}
2. Unsafe Type Assertions on Untrusted Input
Incoming JSON messages are parsed into a generic map and fields are accessed without validation.
File: kernel/server/serve.go
cmdStr := request["cmd"].(string)
cmdId := request["reqId"].(float64)
param := request["param"].(map[string]interface{})
Malformed or missing fields trigger a runtime panic. The handler does not implement local panic recovery, allowing crashes to propagate.
PoC
Step 1 — Prepare workspace directory
mkdir -p ./workspace
Step 2 — Run SiYuan container
docker run -d \
-p 6806:6806 \
-e SIYUAN_ACCESS_AUTH_CODE_BYPASS=true \
-v $(pwd)/workspace:/siyuan/workspace \
b3log/siyuan \
--workspace=/siyuan/workspace
Service becomes reachable at http://127.0.0.1:6806
Step 3 — Confirm service availability
Open in browser:
http://127.0.0.1:6806
Step 4 — Connect to unauthenticated WebSocket endpoint
ws://127.0.0.1:6806/ws?app=siyuan&id=auth&type=auth
This connection is accepted without credentials.
Step 5 — Send malformed payload
Payload:
{}
Step 6 — Observe behavior
Monitor container logs:
docker logs -f <container_id>
Impact
An unauthenticated attacker with network access can repeatedly crash the kernel, causing persistent denial of service.
Impact is highest when the service is exposed beyond localhost (e.g., Docker deployments, reverse proxies, LAN access, or public hosting).
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.6.1"
},
"package": {
"ecosystem": "Go",
"name": "github.com/siyuan-note/siyuan/kernel"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.6.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-33203"
],
"database_specific": {
"cwe_ids": [
"CWE-248",
"CWE-306"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-18T20:11:00Z",
"nvd_published_at": "2026-03-20T23:16:45Z",
"severity": "HIGH"
},
"details": "## Summary\nThe SiYuan kernel WebSocket server accepts unauthenticated connections when a specific \u201cauth keepalive\u201d query parameter is present. After connection, incoming messages are parsed using unchecked type assertions on attacker-controlled JSON.\n\nA remote attacker can send malformed messages that trigger a runtime panic, potentially crashing the kernel process and causing denial of service.\n\n## Details\n**1. Authentication Bypass via Keepalive Query**\n\nUnauthenticated connections are accepted if the request URI matches a specific pattern intended for an authentication page keepalive.\n\n**File: kernel/server/serve.go**\n\n```\nif !authOk {\n authOk = strings.Contains(s.Request.RequestURI, \"/ws?app=siyuan\") \u0026\u0026\n strings.Contains(s.Request.RequestURI, \"\u0026id=auth\u0026type=auth\")\n}\n\n```\n\n**2. Unsafe Type Assertions on Untrusted Input**\n\nIncoming JSON messages are parsed into a generic map and fields are accessed without validation.\n\n**File: kernel/server/serve.go**\n\n```\ncmdStr := request[\"cmd\"].(string)\ncmdId := request[\"reqId\"].(float64)\nparam := request[\"param\"].(map[string]interface{})\n\n```\nMalformed or missing fields trigger a runtime panic.\nThe handler does not implement local panic recovery, allowing crashes to propagate.\n\n## PoC\n**Step 1 \u2014 Prepare workspace directory**\n\n```sh\nmkdir -p ./workspace\n```\n\n**Step 2 \u2014 Run SiYuan container**\n\n```\ndocker run -d \\\n -p 6806:6806 \\\n -e SIYUAN_ACCESS_AUTH_CODE_BYPASS=true \\\n -v $(pwd)/workspace:/siyuan/workspace \\\n b3log/siyuan \\\n --workspace=/siyuan/workspace\n```\n\nService becomes reachable at http://127.0.0.1:6806\n\n**Step 3 \u2014 Confirm service availability**\n\nOpen in browser:\n\n```sh\nhttp://127.0.0.1:6806\n```\n\n**Step 4 \u2014 Connect to unauthenticated WebSocket endpoint**\n\n```sh\nws://127.0.0.1:6806/ws?app=siyuan\u0026id=auth\u0026type=auth\n```\n\nThis connection is accepted without credentials.\n\n**Step 5 \u2014 Send malformed payload**\n\nPayload:\n\n```sh\n\n{}\n\n```\n\n**Step 6 \u2014 Observe behavior**\n\nMonitor container logs:\n\n```sh\n\ndocker logs -f \u003ccontainer_id\u003e\n\n```\n## Impact\nAn unauthenticated attacker with network access can repeatedly crash the kernel, causing persistent denial of service.\n\nImpact is highest when the service is exposed beyond localhost (e.g., Docker deployments, reverse proxies, LAN access, or public hosting).",
"id": "GHSA-3g9h-9hp4-654v",
"modified": "2026-03-25T18:12:26Z",
"published": "2026-03-18T20:11:00Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-3g9h-9hp4-654v"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33203"
},
{
"type": "PACKAGE",
"url": "https://github.com/siyuan-note/siyuan"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "SiYuan has an Unauthenticated WebSocket DoS via Auth Keepalive Bypass"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.