
Research
/Security News
Critical Vulnerability in NestJS Devtools: Localhost RCE via Sandbox Escape
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
ble-mcp-test
Advanced tools
Complete BLE testing stack: WebSocket bridge server, MCP observability layer, and Web Bluetooth API mock. Test real BLE devices in Playwright/E2E tests without browser support.
Test Web Bluetooth apps on any machine - Bridge real BLE devices to your browser tests through WebSocket tunneling.
# Install
npm install -g ble-mcp-test
# Run the bridge server (on machine with BLE hardware)
ble-mcp-test
# Use in your tests
import { injectWebBluetoothMock } from 'ble-mcp-test';
injectWebBluetoothMock('ws://localhost:8080');
Web Bluetooth API only works in Chrome/Edge, requires user interaction, and can't be automated in headless browsers. This tool lets you:
sequenceDiagram
participant Test as Playwright Test
participant Browser as Browser (Mock)
participant Bridge as Bridge Server
participant BLE as BLE Device
Note over Test,Browser: 1. Test Setup
Test->>Browser: injectWebBluetoothMock('ws://localhost:8080')
Browser->>Browser: Replace navigator.bluetooth
Note over Test,BLE: 2. Device Connection
Test->>Browser: navigator.bluetooth.requestDevice()
Browser->>Bridge: WebSocket connect<br/>ws://localhost:8080?device=CS108&service=...
Bridge->>BLE: Noble scan for device
BLE-->>Bridge: Device found
Bridge->>BLE: Connect via Noble
BLE-->>Bridge: Connected
Bridge-->>Browser: {"type": "connected", "device": "CS108-123"}
Browser-->>Test: Return MockBluetoothDevice
Note over Test,BLE: 3. Data Exchange
Test->>Browser: characteristic.writeValue([0xA7, 0xB3, ...])
Browser->>Bridge: {"type": "data", "data": [167, 179, ...]}
Bridge->>BLE: Write via Noble
BLE->>Bridge: Notification data
Bridge->>Browser: {"type": "data", "data": [179, 167, ...]}
Browser->>Test: characteristicvaluechanged event
Note over Test,BLE: 4. Disconnection
Test->>Browser: device.gatt.disconnect()
Browser->>Bridge: WebSocket close
Bridge->>BLE: Disconnect via Noble
Bridge->>Bridge: Cleanup connection
// Your test file (Playwright, Puppeteer, etc)
import { injectWebBluetoothMock } from 'ble-mcp-test';
test('BLE device communication', async ({ page }) => {
// Inject the mock
await page.addScriptTag({
path: 'node_modules/ble-mcp-test/dist/web-ble-mock.bundle.js'
});
await page.evaluate(() => {
WebBleMock.injectWebBluetoothMock('ws://localhost:8080');
});
// Use Web Bluetooth API normally
const device = await page.evaluate(async () => {
const device = await navigator.bluetooth.requestDevice({
filters: [{ namePrefix: 'MyDevice' }]
});
await device.gatt.connect();
const service = await device.gatt.getPrimaryService('180f');
const characteristic = await service.getCharacteristic('2a19');
// Read battery level
const value = await characteristic.readValue();
return value.getUint8(0);
});
expect(device).toBe(75); // 75% battery
});
Sessions allow BLE connections to persist across WebSocket disconnects and prevent conflicts:
// Zero config - automatically creates unique session per browser/tool
injectWebBluetoothMock('ws://localhost:8080');
// Auto-generates: "192.168.1.100-chrome-A4B2" or "127.0.0.1-playwright-X9Z1"
// Advanced: Use explicit session ID
injectWebBluetoothMock('ws://localhost:8080', {
sessionId: 'my-custom-session'
});
// Session persists for 60 seconds after disconnect
// Different browsers/tools get different sessions automatically
// Sessions persist across page reloads using localStorage
// Test 1: Page loads
injectWebBluetoothMock('ws://localhost:8080');
// Session: "192.168.1.100-chrome-A4B2" (stored in localStorage)
// Test 2: Page reloads
injectWebBluetoothMock('ws://localhost:8080');
// Session: "192.168.1.100-chrome-A4B2" (reused from localStorage!)
// Clear stored session when needed
import { clearStoredSession } from 'ble-mcp-test';
clearStoredSession(); // Fresh session on next injection
// Playwright tests get automatic deterministic session IDs
test('inventory page', async ({ page }) => {
// Auto-detected: "localhost-tests/e2e/inventory-page"
// Same test always gets same session ID
});
test('scanning page', async ({ page }) => {
// Auto-detected: "localhost-tests/e2e/scanning-page"
// Different test gets different session ID
});
// Or use explicit session ID
import { setTestSessionId } from 'ble-mcp-test';
setTestSessionId('inventory-test-session');
// Or via environment variable
// BLE_TEST_SESSION_ID=ci-run-123 pnpm test
Hierarchical priority:
window.BLE_TEST_SESSION_ID
- Explicit test injectionprocess.env.BLE_TEST_SESSION_ID
- Environment variable✅ Complete Web Bluetooth API Mock - Drop-in replacement for navigator.bluetooth
✅ Real Device Communication - Tests use actual BLE hardware via bridge
✅ Any Browser/OS - No Chrome-only or platform restrictions
✅ CI/CD Ready - Run BLE tests in GitHub Actions, Docker, etc
✅ MCP Observability - AI-friendly debugging with Claude, Cursor, etc
✅ TypeScript - Full type safety and IntelliSense
✅ Session Persistence - BLE connections survive WebSocket disconnects
✅ Minimal - Core bridge under 600 lines, one connection at a time
See CHANGELOG for version history.
MIT © 2025 Mike Stankavich
FAQs
Complete BLE testing stack: WebSocket bridge server, MCP observability layer, and Web Bluetooth API mock. Test real BLE devices in Playwright/E2E tests without browser support.
The npm package ble-mcp-test receives a total of 834 weekly downloads. As such, ble-mcp-test popularity was classified as not popular.
We found that ble-mcp-test demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Product
Customize license detection with Socket’s new license overlays: gain control, reduce noise, and handle edge cases with precision.
Product
Socket now supports Rust and Cargo, offering package search for all users and experimental SBOM generation for enterprise projects.