Skip to content

Report

Attestation (Header)

agent_id: audit-orchestrator
timestamp: 2026-01-31T17:13:46Z
git_ref: e4bb0098264f90d3afc7b5d0f3b5e425d1825761
artefact: REPORT.md
status: COMPLETE
confidence: MEDIUM
contributing_agents:
- audit-mapper
- audit-dependencies
- audit-documentation
- audit-security
- audit-reliability
- audit-performance
- audit-database
- audit-configuration
- audit-compliance
- audit-accessibility
- audit-test-quality
- audit-api-contracts
- audit-concurrency
- audit-report-writer
total_findings: 17

Executive Summary

SuperDash is a compact Node.js monitoring service for broadcast playout devices with Ember+, TSL UMD, and OSC integrations. The primary risks are unauthenticated exposure of operational data over /health and WebSocket endpoints, and reliability issues in protocol handling (TSL UMD sender bind state and CasparCG shared listener multiplexing). Test coverage is limited and not hermetic, which increases regression risk.

Overall Risk Rating: MEDIUM

Immediate Actions Required:

  1. Restrict or authenticate /health and WebSocket access.
  2. Fix TSL UMD sender startup state handling.
  3. Address CasparCG shared listener multiplexing for multi-channel setups.

Audit Limitations:

  • CVE audit incomplete due to network restrictions.
  • Baseline tests failed in this environment due to watchman and socket permission errors.

1. Architecture Overview

CasparCG (OSC UDP) ─┐
HyperDeck (TCP) ────┼─> SuperDash server ──> WebSocket clients
vMix (HTTP XML) ────┘ └─> Ember+ provider
└─> TSL UMD sender

Key components:

  • server/server.js: HTTP + WebSocket server, state manager, protocol startup.
  • server/*-client.js: Protocol clients (HyperDeck, vMix, CasparCG).
  • server/emberplus-provider.js, server/tsl-umd-sender.js: Broadcast protocol outputs.
  • public/*.html: Static dashboards and control UI.

2. Findings Summary

By Severity

SeverityCountCategories
CRITICAL0-
HIGH0-
MEDIUM8Security, Reliability, Concurrency, Performance, Configuration, Testing, Documentation
LOW9Security, Reliability, Performance, Configuration, Accessibility, Documentation, Compliance
INFO8Compliance, Data flows, Test architecture, Baseline limits

By Category

CategoryCriticalHighMediumLow
Security0012
Reliability0011
Concurrency0010
Performance0011
Configuration0011
Documentation0011
Testing0020
Accessibility0002
Compliance0001

3. Critical & High Findings

None.


4. Medium & Low Findings

IDSeverityCategoryTitleLocation
F-001MEDIUMSecurityUnauthenticated /health + WebSocket expose device state/configserver/server.js:323
F-002MEDIUMReliabilityTSL UMD sender marks running before bind successserver/tsl-umd-sender.js:227
F-003MEDIUMConcurrencyCasparCG shared listener keyed by IP onlyserver/osc-casparcg.js:49
F-004MEDIUMPerformanceFixed-interval full-state broadcastsserver/server.js:481
F-005MEDIUMConfigurationMinimal config schema validationserver/server.js:33
F-006MEDIUMTestingTests rely on real socket bindingserver/__tests__/emberplus-provider.test.js:13
F-007MEDIUMTestingCore protocol clients lack testsserver/
F-008MEDIUMDocumentationControl panel claims live testing/simulation not implementedREADME.md:157
F-009LOWSecurityEmber+ provider binds to all interfaces by defaultserver/emberplus-provider.js:101
F-010LOWSecurityOSC listener accepts packets from any senderserver/osc-casparcg.js:116
F-011LOWReliabilityNo SIGTERM handler for systemd stopserver/server.js:584
F-012LOWPerformancevMix polling default 500ms could be heavy at scaleserver/vmix-client.js:108
F-013LOWConfigurationUnknown device types yield undefined portsserver/server.js:163
F-014LOWAccessibilityNo ARIA live regions for dynamic updatespublic/dashboard.html:238
F-015LOWAccessibilityPotential low-contrast text on dark UIpublic/dashboard.html:206
F-016LOWDocumentation”Up to 12 devices” not enforced in UIREADME.md:126
F-017LOWComplianceDual-license dependency (osc MIT/GPL-2.0)node_modules/osc/package.json

5. Test Coverage Matrix

AreaUnitIntegrationE2ECoverageNotes
Ember+ providerPartialPartialNoLowTests start real sockets
TSL UMD senderPartialPartialNoLowTests start real sockets
HyperDeck clientNoNoNoNoneNo tests present
vMix clientNoNoNoNoneNo tests present
CasparCG OSCNoNoNoNoneNo tests present
WebSocket serverNoNoNoNoneNo tests present
UI pagesNoNoNoNoneNo UI tests present

6. Change Proposals (Audit-Only)

CP-001: Add access control for /health and WebSocket

AttributeValue
Related FindingsF-001
PriorityMEDIUM
EffortMedium
RiskLow

Files Affected: server/server.js

Proposed Diff (conceptual):

const API_TOKEN = process.env.SUPERDASH_TOKEN;
function requireToken(req, res, next) {
if (!API_TOKEN) return next();
const auth = req.headers.authorization || '';
if (auth === `Bearer ${API_TOKEN}`) return next();
res.status(401).json({ error: 'unauthorized' });
}
app.use('/health', requireToken);
wss.on('connection', (socket, request) => {
if (API_TOKEN) {
const auth = request.headers['authorization'];
if (auth !== `Bearer ${API_TOKEN}`) {
socket.close();
return;
}
}
...
});

Test Case:

  • With token set, /health returns 401 without header and 200 with valid Authorization header.
  • WebSocket connection without token is closed; with token receives playoutStates.

CP-002: Fix TSL UMD sender startup state

AttributeValue
Related FindingsF-002
PriorityMEDIUM
EffortLow
RiskLow

Files Affected: server/tsl-umd-sender.js

Proposed Diff (conceptual):

this._socket.bind(() => {
if (this._socket) {
this._socket.setBroadcast(true);
}
});
this._isRunning = true;
this._socket.bind(() => {
if (this._socket) {
this._socket.setBroadcast(true);
this._isRunning = true;
this._scheduleRefresh();
}
});

Test Case:

  • Mock dgram.createSocket to emit error before listening; verify _isRunning remains false.

CP-003: Support multiple CasparCG devices per IP

AttributeValue
Related FindingsF-003
PriorityMEDIUM
EffortMedium
RiskMedium

Files Affected: server/osc-casparcg.js

Proposed Diff (conceptual):

clients: new Map(), // ip -> client
clients: new Map(), // ip -> [clients]
...
this.clients.set(client.ip, client);
const list = this.clients.get(client.ip) || [];
list.push(client);
this.clients.set(client.ip, list);
...
const client = this.clients.get(sourceIp);
if (client) client._handleOscMessage(...)
const list = this.clients.get(sourceIp) || [];
for (const client of list) client._handleOscMessage(...)

Test Case:

  • Register two clients with same IP/different channel; verify both receive relevant OSC updates.

7. Remaining Work

  • Complete CVE audit in an environment with registry access.
  • Rerun Jest tests where socket binding is permitted or mocked.
  • Add unit tests for HyperDeck/vMix/CasparCG protocol parsing.
  • Add basic WebSocket contract tests and JSON schema validation.

8. Appendices

  • docs/audit/REPO_MAP.md
  • docs/audit/ENDPOINTS.md
  • docs/audit/STATE_MODEL.md
  • docs/audit/SECURITY.md
  • docs/audit/RELIABILITY.md
  • docs/audit/PERFORMANCE.md
  • docs/audit/CONFIGURATION.md
  • docs/audit/TEST_QUALITY.md

Attestation

# Identity
agent_id: audit-orchestrator
agent_version: "1.0"
protocol_version: "2.0"
# Timing
timestamp: 2026-01-31T17:13:46Z
duration_seconds: 720
# Context
git_ref: e4bb0098264f90d3afc7b5d0f3b5e425d1825761
git_branch: main
working_directory: /Users/david/Documents/GitHub/superdash
# Artefact metadata
artefact: REPORT.md
phase: 7
status: COMPLETE
# Confidence assessment
confidence: MEDIUM
confidence_notes: "Findings synthesized from audit artefacts; no successful test baseline due to environment constraints."
# Inputs consumed (with integrity hashes)
inputs_consumed:
- path: docs/audit/EXECUTIVE_SUMMARY.md
type: file
- path: docs/audit/REMEDIATION_ROADMAP.md
type: file
- path: docs/audit/SECURITY.md
type: file
- path: docs/audit/RELIABILITY.md
type: file
- path: docs/audit/PERFORMANCE.md
type: file
- path: docs/audit/CONFIGURATION.md
type: file
- path: docs/audit/TEST_QUALITY.md
type: file
- path: docs/audit/DOCUMENTATION_DRIFT.md
type: file
# Commands executed
commands_executed:
- seq: 1
cmd: "ls docs/audit"
exit_code: 0
purpose: "Collect artefact inventory"
output_summary: "Report synthesized from all artefacts"
# Findings summary
findings:
critical: 0
high: 0
medium: 8
low: 9
info: 8
# Blocking issues
blocking_issues:
- "CVE audit incomplete due to network restrictions"
- "Baseline tests failed due to watchman/socket permission errors"
# Handoff
handoff:
ready: true
next_agents: []
dependencies_satisfied:
REPORT.md: COMPLETE
context_for_next: |
Final report produced for audit-only run.