Skip to content

[TS-03] WebSocket boundary casts Signal K frames without runtime validation #24

Description

@mairas

Severity: medium | Confidence: confirmed | Area: type-safety | Source: codebase review 2026-06-30, finding TS-03

Problem

The Signal K WebSocket connection in signalk-delta.service.ts is typed as WebSocketSubject<object> (line 62). Raw frames from the socket are passed directly into processWebsocketMessage(message: ISignalKDeltaMessage) (line 221) with no runtime guard in between. Because every field of ISignalKDeltaMessage is optional, TypeScript's structural type system accepts an object value as a valid argument — this is a compile-time coincidence, not a validation step. The downstream parsers then unconditionally trust the shape: parseUpdates calls item.path.startsWith(...) without checking that path is a non-null string, and parseSkMeta dereferences metadata.value.properties[key] where properties is typed object with no null guard. Malformed or hostile delta frames therefore produce uncaught runtime exceptions rather than explicit, recoverable failures.

Impact

Any deviation from the expected Signal K delta shape — a buggy server plugin, a protocol version mismatch, or a network interception attack — can throw an unhandled TypeError deep inside the service. In a marine instrument panel context this means silent widget failures or a blank display at sea with no actionable error surfaced to the user. The project already ships @signalk/server-api as a dependency but does not use its validated delta types at this boundary, so stronger typing is available at no extra cost.

Affected code

  • src/app/core/services/signalk-delta.service.ts:62 — socket typed WebSocketSubject<object>
  • src/app/core/services/signalk-delta.service.ts:221 — raw frame passed to processWebsocketMessage with no guard
  • src/app/core/services/signalk-delta.service.ts:333-357processWebsocketMessage(message: ISignalKDeltaMessage) entry point
  • src/app/core/services/signalk-delta.service.ts:479-495parseSkMeta dereferences metadata.value.properties[key] without null check
  • src/app/core/interfaces/signalk-interfaces.ts:67-103ISignalKDeltaMessage has every field optional, making it structurally equivalent to object
  • src/app/core/interfaces/signalk-interfaces.ts:186properties typed as bare object inside ISkMetadata

Suggested direction

Add a type guard at the WebSocket boundary before dispatching to processWebsocketMessage. The discriminator fields already present on valid deltas — updates, requestId, self, errorMessage — are sufficient to narrow the type without a heavy schema library. At minimum, guard that item.path is a non-null string before calling .startsWith. Consider adopting the delta types from @signalk/server-api (already a declared dependency) in place of the hand-rolled ISignalKDeltaMessage to benefit from any upstream validation improvements. The change is self-contained and does not require restructuring the service.

Verification

Verified against the codebase at commit HEAD of the SKip fork (confidence: confirmed). All cited file paths and line references were confirmed to exist and match the described code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:type-safetyType safety & maintainabilitybugSomething isn't workingkip-reviewFrom the 2026-06-30 Kip/SKip codebase reviewseverity:mediumReview finding: medium severity

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions