All results

Vulnerability disclosure

Server crash in CERT.LV’s Graphoscope when a user disconnects during an upload

Graphoscope (v2.6.1) – CERT.LV

OffSeq found a denial-of-service flaw in Graphoscope, the open-source platform CERT.LV publishes for querying many independent data sources from one interface and showing their relations as a graph. A user who uploaded an indicator list and closed the connection before processing finished made the server dereference a nil WebSocket and crash, signing out every user. Any self-registered account could trigger it reliably. OffSeq reported the issue to CERT.LV and contributed the fix, which CERT.LV merged.

OffSeq

3 min read

Severity: MediumCVSS 6.5cert-lv/graphoscope#9

Key facts

Class
NULL pointer dereference via a teardown race (CWE-476, CWE-362)
Severity
Medium
CVSS
6.5
Target
Graphoscope
Vendor
CERT.LV
Affected
v2.6.1 (a2a794e) – WebSocket send after /upload
Fixed in
cert-lv/graphoscope PR #9 (merged, commit 946ff7c)
Status
Fixed upstream
Role
Reporter and fix author

CVSS base score

6.5

/ 10Medium

Every score is built from eight plain questions about how an attack works and what it costs you.

How hard it is to exploit

What the attacker can do

Select a metric to see what it means

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

§ 01. Overview

Graphoscope is CERT.LV's open-source analysis platform. Analysts query many independent data sources – passive DNS, client databases, leaked-credential sets and others – from one web interface and see the results as a graph of related entities. A user can upload a list of indicators for batch processing; the server works through it in the background and notifies the user over WebSocket when the report is ready.

OffSeq found that this notification could crash the entire server. If the user disconnected before processing finished, the background job wrote to a WebSocket that had already been torn down, and the resulting panic terminated the Graphoscope process.

§ 02. Root cause

uploadHandler starts the processing in a goroutine (upload.go:253). When it finishes, processUploads calls a.send("upload-processed", …) (upload.go:413). Account.send guarded only against a.Session == nil – but when the client disconnects, the deferred teardown in listen() leaves the session in place and clears only the connection:

go
1defer func() {2    close(a.Session.Done)3    a.Session.Websocket.Close()4    a.Session.Websocket = nil5    delete(online, a.Username)6}()
Listing 1Pre-patch teardown in websocket.go: the session survives, its connection does not.

With a.Session non-nil and a.Session.Websocket nil, the guard passed and WriteMessage dereferenced a nil pointer. The teardown also cleared the field without holding WebsocketMutex, so a nil check in send() alone would still have raced with it. The goroutine had no recover(), so the panic was not contained:

1panic: runtime error: invalid memory address or nil pointer dereference2[signal SIGSEGV: segmentation violation code=0x2 addr=0x10 pc=0x104d606b4]34github.com/gorilla/websocket.(*Conn).WriteMessage(...)5        .../gorilla/websocket@v1.5.3/conn.go:760 +0x246main.(*Account).send(...)7        .../graphoscope/websocket.go:502 +0x1748main.(*Account).processUploads(...)9        .../graphoscope/upload.go:413 +0xaa8
Listing 2Pre-patch stack trace after an upload followed by a closed connection.

§ 03. Impact

One upload followed by a closed connection takes the whole service down, and every signed-in user loses their session. The crash does not depend on winning a narrow timing window: closing the connection at any point before processing finishes is enough, so the trigger works every time.

Graphoscope allows self-registration through /signup, so the attacker needs nothing beyond an account they create themselves. Repeating the request keeps the platform unavailable for as long as the attacker continues.

§ 04. The fix

OffSeq contributed a fix confined to websocket.go:

  • send() returns early when the session is nil, before reading any of its fields – the previous error path dereferenced a.Session.IP in a log line;
  • send() re-checks a.Session.Websocket for nil while holding WebsocketMutex, which is where the teardown writes it;
  • the teardown in listen() takes the same mutex around Close() and the nil assignment, so a writer never observes a half-closed connection.

On retest the same reproduction left the service running: the log showed the client closing the connection and the processed file being added to the downloads list, and /signin kept answering 200. Three related hardening items were raised as follow-ups – a lock around the shared online map, a top-level recover() in goroutines started from request handlers, and request-context cancellation for in-flight processing. CERT.LV merged the change as pull request #9.

§ 05. Disclosure timeline

  1. 2026-05-14OffSeq reports the WebSocket nil-dereference crash to CERT.LV and submits a fix upstream (PR #9)
  2. 2026-10-20Fix reviewed and merged by the CERT.LV maintainers

References

Credit

Discovered, reported, and fixed by Nils Putniņš (OffSeq Cybersecurity).

How we would test your environment

More results

Stored cross-site scripting in CERT.LV’s Graphoscope via upload filenames

OffSeq found a stored cross-site scripting flaw in Graphoscope, the open-source platform CERT.LV publishes for querying many independent data sources from one interface and showing their relations as a graph. The name of an uploaded file was stored unchanged and rendered with innerHTML, so an indicator file with a crafted name ran script in the session of the analyst who uploaded it. OffSeq reported the issue to CERT.LV and contributed the fix, which CERT.LV merged.

Vulnerability disclosure20263 min read

Cross-user report access in CERT.LV’s Graphoscope

OffSeq found a horizontal authorisation bypass in Graphoscope, the open-source platform CERT.LV publishes for querying many independent data sources from one interface and showing their relations as a graph. The report download endpoint checked that a user was signed in but not that the requested report was theirs, so any analyst could read another analyst's uploaded indicators and query results. OffSeq reported the issue to CERT.LV and contributed the fix, which CERT.LV merged.

Vulnerability disclosure20262 min read

Remote code execution in the OZOLS ERP via an abandoned update domain

CVE-2026-22306 is a critical remote-code-execution flaw OffSeq found in the OZOLS ERP system. Its automatic update channel fetched and ran program code from its2.lv – a domain the vendor had allowed to lapse, yet still hardcoded in every shipped client – over cleartext HTTP with no signature, hash or certificate check. A whois lookup showed the domain free to register, so anyone who took it could run code as the SQL Server service account on customer databases and, through OZOLS's own update-propagation table, on every workstation. OffSeq registered the abandoned domain defensively to prevent a malicious takeover.

Vulnerability disclosure20267 min read

Have similar exposure in your environment?

support@offseq.com+371 2256 5353