Lost at Sea: Windows Path Traversal in Signal K Server
Feb 3, 2026·7 min read·7 visits
Executive Summary (TL;DR)
Signal K Server (marine data software) forgot that Windows uses backslashes (\) for paths. Authenticated attackers can use `..\` sequences to traverse out of the data directory and access sensitive system files on Windows hosts.
A classic 'Linux-brain' implementation error in Signal K Server exposes Windows installations to directory traversal. By failing to sanitize backslashes in the `applicationData` API, authenticated users can escape the application sandbox to read and write arbitrary files on the underlying filesystem.
The Hook: Hacking the High Seas
Boats aren't just wood and fiberglass anymore; they are floating data centers. The Signal K Server is the open-source heart of this modern marine ecosystem. It acts as a universal translator, taking data from GPS, wind sensors, AIS transponders, and engine diagnostics, and turning it into a beautiful JSON stream that modern apps can understand. It's the central nervous system of a smart vessel.
Now, imagine you are a crew member (or a guest with a login) on a superyacht running Signal K on a Windows server. You want to see what's happening below deck, but you also want to see what's happening in the captain's private configuration files. Usually, the server puts you in a sandbox. But thanks to CVE-2026-25228, that sandbox has a hole in it the size of a porthole.
This isn't a complex memory corruption bug involving heap feng shui. This is a classic logic error born from a developer forgetting that the world isn't just POSIX. It is the digital equivalent of locking the front door but leaving the window wide open because you assumed burglars only know how to use doorknobs.
The Flaw: A Tale of Two Slashes
The vulnerability lives in the applicationData API. This feature allows plugins or authorized users to store JSON data (settings, user preferences, etc.) on the server. To keep things tidy, the server creates a directory structure based on an appId.
Here is the logic: The server takes your appId, checks if it's safe, and then appends it to a base directory path. The safety check is supposed to prevent Path Traversal—the art of using ../ to climb out of the intended folder.
The developers implemented a blacklist approach. They explicitly looked for the forward slash /. If the appId contained a forward slash, the request was rejected. On Linux and macOS (where Signal K is most popular), this works perfectly. / is the only way to traverse directories.
But on Windows? Windows is the wild west of path separators. It accepts both / and \. The developers blocked the POSIX separator but forgot to block the Windows backslash. Node.js, being helpful and platform-agnostic, looks at a path like ..\..\windows\win.ini on a Windows machine and says, "I know exactly where that is!" and resolves it. The application security logic said "No forward slashes here, looks safe to me!" and handed the keys to the file system over to the attacker.
The Code: The Smoking Gun
Let's look at the code that sank the ship. This analysis is based on commit 9bcf61c8fe2cb8a40998b913a02fb64dff9e86c7.
The Vulnerable Code
Before the fix, the validateAppId function was blissfully ignorant of backslashes:
function validateAppId(appid) {
// Checks length and looks for forward slash
return appid.length < 30 &&
appid.indexOf('/') === -1
? appid
: null
}If you send ..\..\secrets, indexOf('/') returns -1, and the validation passes. The application then passes this string to path.join(), which on Windows constructs a valid relative path that traverses up the directory tree.
The Fix
The patch introduces defense-in-depth. First, they fixed the validation regex. Second, and more importantly, they added a canonical path check.
// 1. Better Input Validation
function validateAppId(appid) {
return appid.length < 30 &&
appid.indexOf('/') === -1 &&
appid.indexOf('\\') === -1 // NOW we check for backslashes
? appid
: null
}
// 2. Canonical Path Verification (The Real Shield)
function pathForApplicationData(req, appid, version, isUser) {
const filePath = path.normalize(
path.join(dirForApplicationData(req, appid, isUser), `${version}.json`)
)
// Resolve the config root to an absolute path
const configPath = path.resolve(app.config.configPath)
// Resolve the target file to an absolute path
const resolvedPath = path.resolve(filePath)
// CRITICAL: Does the target start with the config root?
if (!resolvedPath.startsWith(configPath)) {
throw new Error('Invalid path: outside configuration directory')
}
return filePath
}The second part of the fix is the gold standard for preventing traversal. Even if an attacker finds a way to sneak a traversal character past the validateAppId function, path.resolve converts the path to its absolute form (e.g., C:\Windows\...). The code then checks: "Does this absolute path start with C:\SignalK\Data?" If not, it throws an error. This renders the traversal useless.
The Exploit: Climbing the Ladder
Exploiting this on a Windows target is trivial once you have authentication. You don't need fancy tools; curl or Postman is enough. The goal is to reach sensitive files.
The Attack Chain
- Recon: Confirm the target is running Windows. This is often visible in HTTP headers or error messages.
- Auth: Log in to the Signal K dashboard to get your session cookie or bearer token.
- Traversal: Craft a request to the
applicationDataendpoint.
POST /signalk/v1/applicationData/global/..%5C..%5C..%5C..%5CWindows%5Cwin.ini HTTP/1.1
Host: target-boat-server.local
Content-Type: application/json
Cookie: connect.sid=s%3A...
{"value": "pwned"}> [!NOTE]
> In the URL above, %5C is the URL-encoded backslash \. We are asking the server to save data to global/../../../../Windows/win.ini.
The Result
On a vulnerable Windows server:
- Node.js receives the request.
validateAppIdchecks..\..\..\..\Windows\win.ini. It sees no/. It approves.path.joinconstructs the path.- The server attempts to write your JSON payload to that location.
If the server process (often running as Administrator or a user with broad permissions on Windows consumer installs) has write access, you've just corrupted a system file. If you use a GET request, you can read it.
The Impact: Mutiny on the Bounty
Why does this matter? It's just a boat server, right?
Confidentiality: The immediate impact is reading files. Signal K servers often store tokens for other services (NMEA 2000 gateways, cloud loggers like InfluxDB credentials) in their configuration files. An attacker could use ..\..\settings.json (or similar) to steal these credentials, pivoting to cloud infrastructure or deeper into the vessel's control network.
Integrity (The Hidden Danger): The official CVSS vector lists Integrity as None (I:N), but this is debatable. The vulnerability is in pathForApplicationData, which is used for both reading and writing. If an attacker can write a file, they can potentially achieve Remote Code Execution (RCE). For example, if they can traverse to the startup folder or overwrite a script that Node.js executes, they own the server. On Windows, permissions are often laxer than on Linux servers, increasing this risk.
Availability: Writing garbage data to critical configuration files (like security.json) could crash the server or lock out legitimate administrators, effectively blinding the captain to their navigation data.
The Fix: Plugging the Hole
If you are running Signal K Server on Windows, stop reading and update to version 2.20.3 immediately. This version includes the patch that validates backslashes and enforces directory boundaries.
For Developers: Lessons Learned
This CVE serves as a painful reminder of two golden rules in secure coding:
- Don't rely on Blacklists: Trying to list all "bad" characters is a losing game. You will forget one (like
\or null bytes%00). Use whitelists (e.g.,^[a-zA-Z0-9]+$) whenever possible. - Canonicalize First, Validate Second: Never perform security checks on a relative path. Always resolve the path to its absolute, canonical form using
path.resolve()(Node.js) orrealpath()(C/PHP), and then check if it sits inside your intended jail.
For those unable to patch immediately, firewall off the Signal K administrative port. Do not expose this server to the public internet—though honestly, if your boat's navigation server is on the public internet, you have bigger problems than this CVE.
Official Patches
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
Signal K Server Signal K | < 2.20.3 | 2.20.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 (Path Traversal) |
| CVSS v3.1 | 5.0 (Medium) |
| Attack Vector | Network (Authenticated) |
| Platform | Windows |
| Impact | File Read/Write outside web root |
| Fix Version | 2.20.3 |
MITRE ATT&CK Mapping
The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.