VYPR
Moderate severityNVD Advisory· Published Mar 19, 2026· Updated Mar 20, 2026

SiYuan: Cross-Origin WebSocket Hijacking via Authentication Bypass — Unauthenticated Information Disclosure

CVE-2026-32815

Description

SiYuan is a personal knowledge management system. In versions 3.6.0 and below, the WebSocket endpoint (/ws) allows unauthenticated connections when specific URL parameters are provided (?app=siyuan&id=auth&type=auth). This bypass, intended for the login page to keep the kernel alive, allows any external client — including malicious websites via cross-origin WebSocket — to connect and receive all server push events in real-time. These events leak sensitive document metadata including document titles, notebook names, file paths, and all CRUD operations performed by authenticated users. Combined with the absence of Origin header validation, a malicious website can silently connect to a victim's local SiYuan instance and monitor their note-taking activity. This issue has been fixed in version 3.6.1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/siyuan-note/siyuan/kernelGo
<= 0.0.0-20260313024916-fd6526133bb3

Affected products

1

Patches

1
1e370e373597

:lock: https://github.com/siyuan-note/siyuan/security/advisories/GHSA-xp2m-98x8-rpj6

https://github.com/siyuan-note/siyuanDanielMar 14, 2026via ghsa
1 file changed · +38 12
  • kernel/util/websocket.go+38 12 modified
    @@ -29,7 +29,8 @@ var (
     	WebSocketServer *melody.Melody
     
     	// map[string]map[string]*melody.Session{}
    -	sessions = sync.Map{} // {appId, {sessionId, session}}
    +	sessions     = sync.Map{} // {appId, {sessionId, session}}
    +	authSessions = sync.Map{}
     )
     
     func BroadcastByTypeAndExcludeApp(excludeApp, typ, cmd string, code int, msg string, data interface{}) {
    @@ -113,12 +114,22 @@ func AddPushChan(session *melody.Session) {
     	typ := session.Request.URL.Query().Get("type")
     	session.Set("type", typ)
     
    -	if appSessions, ok := sessions.Load(appID); !ok {
    -		appSess := &sync.Map{}
    -		appSess.Store(id, session)
    -		sessions.Store(appID, appSess)
    +	if "auth" == id {
    +		if appSessions, ok := authSessions.Load(appID); !ok {
    +			appSess := &sync.Map{}
    +			appSess.Store(id, session)
    +			authSessions.Store(appID, appSess)
    +		} else {
    +			(appSessions.(*sync.Map)).Store(id, session)
    +		}
     	} else {
    -		(appSessions.(*sync.Map)).Store(id, session)
    +		if appSessions, ok := sessions.Load(appID); !ok {
    +			appSess := &sync.Map{}
    +			appSess.Store(id, session)
    +			sessions.Store(appID, appSess)
    +		} else {
    +			(appSessions.(*sync.Map)).Store(id, session)
    +		}
     	}
     }
     
    @@ -130,12 +141,23 @@ func RemovePushChan(session *melody.Session) {
     		return
     	}
     
    -	appSess, _ := sessions.Load(app)
    -	if nil != appSess {
    -		appSessions := appSess.(*sync.Map)
    -		appSessions.Delete(id)
    -		if 1 > lenOfSyncMap(appSessions) {
    -			sessions.Delete(app)
    +	if "auth" == id {
    +		appSess, _ := authSessions.Load(app)
    +		if nil != appSess {
    +			appSessions := appSess.(*sync.Map)
    +			appSessions.Delete(id)
    +			if 1 > lenOfSyncMap(appSessions) {
    +				authSessions.Delete(app)
    +			}
    +		}
    +	} else {
    +		appSess, _ := sessions.Load(app)
    +		if nil != appSess {
    +			appSessions := appSess.(*sync.Map)
    +			appSessions.Delete(id)
    +			if 1 > lenOfSyncMap(appSessions) {
    +				sessions.Delete(app)
    +			}
     		}
     	}
     }
    @@ -451,6 +473,10 @@ func CountSessions() (ret int) {
     		ret++
     		return true
     	})
    +	authSessions.Range(func(key, value interface{}) bool {
    +		ret++
    +		return true
    +	})
     	return
     }
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.