Initial project documentation and status

This commit is contained in:
Clawdia
2026-08-30 14:46:23 -04:00
commit 765f372c72
50 changed files with 12916 additions and 0 deletions
+376
View File
@@ -0,0 +1,376 @@
# Live Adapter Security Review
**Date:** 2026-08-25
**Scope:** `/home/ledadmin/projects/meshcentral-openclaw-bridge/implementation`
**Reviewer:** Subagent (depth 1/1)
**Status:** Independent security/protocol review
---
## Executive Summary
The MeshCentral ↔ OpenClaw bridge implementation demonstrates **good security hygiene in design intent**, but contains **multiple high-severity implementation gaps** that prevent safe live testing in its current state. The TLS security controls are correctly configured (no `rejectUnauthorized: false`), but the codebase lacks credential sanitization, output validation, and proper error masking—critical for production deployment.
**Recommendation:** Live testing is **NOT SAFE** in its current state. Address all high-severity findings before any live deployment.
---
## Overview of Reviewed Files
| File | Purpose | Reviewed |
|------|---------|----------|
| `research/INTEGRATION-RESEARCH.md` | Protocol analysis and threat model | ✅ |
| `SECURITY.md` | Security requirements and action classes | ✅ |
| `src/meshctrl-client.ts` | WebSocket client for MeshCentral protocol | ✅ |
| `src/adapter.ts` | Real adapter implementation | ✅ |
| `src/contracts.ts` | Zod schemas and type definitions | ✅ |
| `package.json` | Dependencies and scripts | ✅ |
---
## Test Results
The implementation has a robust test suite:
| Command | Result |
|---------|--------|
| `npm run build` | ✅ Pass (no errors) |
| `npm run lint` | ✅ Pass (no errors) |
| `npm test` | ✅ 52/52 tests pass (8 test suites) |
Tests cover:
- Device status handling
- Adapter factory patterns
- Contract validation (Zod schemas)
- Output truncation and limits
- Group filtering
- Integration workflows
---
## Security Findings by Severity
### 🔴 HIGH SEVERITY (Blocking live testing)
#### 1. **Credentials in Error Messages**
**Location:** `adapter.ts`, `_validateConfig()`
```typescript
if (hasUsername !== hasPassword) {
throw new BridgeError(
ErrorCodes.ConfigurationInvalid,
'Both username and password must be provided (or neither for mock mode)',
);
}
```
**Issue:** The error handling does not sanitize or mask credential-related information. If credentials are partially configured, the system should not reveal which component is missing.
**Risk:** Credential enumeration and configuration leakage in logs/monitoring.
**Remediation:**
- Use generic error messages for credential validation failures
- Log detailed errors only to secure audit logs (not user-facing responses)
- Never include credential field names in error messages
#### 2. **No Credential Sanitization Before Use**
**Location:** `meshctrl-client.ts`, `encodeAuthHeader()`
```typescript
export function encodeAuthHeader(credentials: AuthCredentials): string {
const { username, password, totpToken } = credentials;
if (totpToken) {
return Buffer.from(`${username}:${password}:${totpToken}`).toString('base64');
}
return Buffer.from(`${username}:${password}`).toString('base64');
}
```
**Issue:** Credentials are used directly without validation or sanitization. No check for special characters, empty strings, or malicious payloads in username/password.
**Risk:**
- Authentication bypass via malformed credentials
- Protocol injection via special characters in username/password
- TOTP token leakage if exposed
**Remediation:**
- Validate username/password meet minimum length requirements
- Sanitize/escape special characters before encoding
- Add explicit input validation before credential handling
#### 3. **Missing Certificate Validation Configuration**
**Location:** `meshctrl-client.ts`, `MeshCtrlClient.connect()`
```typescript
this.ws = new WebSocket(wsUrl, {
perMessageDeflate: false,
headers: {
'x-meshauth': authHeader,
},
// Important: no TLS bypass - use default certificate validation
});
```
**Issue:** While the code comments state "no TLS bypass", it does not explicitly configure certificate validation or support custom CA bundles. The `ws` library defaults may vary by environment.
**Risk:** Inconsistent certificate validation behavior across deployment environments.
**Remediation:**
- Explicitly set `rejectUnauthorized: true` (default, but make explicit)
- Add support for custom CA bundle via environment variable
- Document TLS configuration requirements
#### 4. **No Response Validation on WebSocket Messages**
**Location:** `meshctrl-client.ts`, `_sendRequestInternal()`
```typescript
const handleResponse = (data: Buffer | string): void => {
try {
clearTimeout(timeout);
const response = parseResponse(data.toString());
// ...
} catch (error) {
clearTimeout(timeout);
this._cleanup();
reject(error instanceof Error ? error : new Error('Unknown error'));
}
};
```
**Issue:** Responses are parsed without schema validation against the expected `MeshCtrlResponse` contract. Malformed or malicious responses could cause undefined behavior.
**Risk:** Protocol downgrade attacks, response injection, or memory exhaustion from oversized responses.
**Remediation:**
- Validate all responses against Zod schemas (already available in `contracts.ts`)
- Enforce `MAX_RESPONSE_SIZE` limit before parsing
- Reject responses with unexpected fields
---
### 🟡 MEDIUM SEVERITY (Should address before production)
#### 5. **No Rate Limiting or Concurrent Request Throttling**
**Location:** `meshctrl-client.ts`, `_sendWithRetry()`
```typescript
async _sendWithRetry(request: MeshCtrlRequest, maxRetries: number): Promise<MeshCtrlResponse> {
let lastError: Error | null = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await this._sendRequestInternal(request);
} catch (error) {
lastError = error instanceof Error ? error : new Error('Unknown error');
if (attempt < maxRetries) {
await new Promise((resolve) => setTimeout(resolve, 100 * attempt));
}
}
}
throw new Error(`Request failed after ${maxRetries} attempts: ${lastError?.message}`);
}
```
**Issue:** No global rate limiting. Multiple concurrent requests can flood the MeshCentral server, potentially triggering denial-of-service protections.
**Risk:** Collateral damage to other services, connection throttling, or account lockout.
**Remediation:**
- Implement per-adapter request rate limiting (e.g., 5 requests/second)
- Add circuit breaker for repeated failures
- Document rate limits in security configuration
#### 6. **No Input Validation on Device/Group IDs**
**Location:** `adapter.ts`, `_isDeviceAllowed()`
```typescript
private _isDeviceAllowed(deviceId: string): boolean {
const { deviceAllowlist, groupAllowlist } = this.config;
if (!deviceAllowlist && !groupAllowlist) {
return true;
}
if (deviceAllowlist && deviceAllowlist.includes(deviceId)) {
return true;
}
// ...
}
```
**Issue:** Device/group IDs are used directly in allowlist lookups without sanitization or regex validation.
**Risk:** Path traversal or injection via malicious device IDs in allowlist configuration.
**Remediation:**
- Validate IDs against allowed character set (alphanumeric, hyphens, underscores)
- Escape special regex characters if used in allowlist patterns
- Document allowed ID formats
#### 7. **Sensitive Data in Logs**
**Location:** Multiple places in `adapter.ts`
The code uses generic error handling but does not explicitly prevent credential or token leakage in logs.
**Risk:** Accidental credential exposure via logging systems.
**Remediation:**
- Implement structured logging with automatic secret redaction
- Add `secret` annotation to credential fields for automatic masking
- Review all error paths for potential leakage
---
### 🟢 LOW SEVERITY (Nice to have)
#### 8. **No Timeout Configuration for WebSocket Handshake**
**Location:** `meshctrl-client.ts`, `connect()`
```typescript
await new Promise<void>((resolve, reject) => {
const timeout = setTimeout(() => {
this._cleanup();
reject(new Error(`Connection timed out after ${this.timeoutMs}ms`));
}, this.timeoutMs);
// ...
});
```
**Issue:** The same timeout is used for both connection establishment and request/response cycles. Connection timeouts are typically shorter than request timeouts.
**Recommendation:** Separate `connectionTimeoutMs` from `requestTimeoutMs`.
#### 9. **No Session Renewal or Reconnection Strategy**
**Location:** `adapter.ts`, `_ensureConnected()`
```typescript
private async _ensureConnected(): Promise<void> {
if (this.connected) {
return;
}
// ...
await this.client!.connect(this.credentials);
this.connected = true;
}
```
**Issue:** If the WebSocket connection drops, there is no automatic reconnection logic. The adapter must be destroyed and recreated.
**Recommendation:** Implement exponential backoff reconnection with maximum retry count.
#### 10. **Missing Audit Logging**
**Location:** `adapter.ts`, all public methods
The code lacks structured audit logging for security events.
**Recommendation:**
- Log authentication successes/failures
- Log allowlist violations
- Log request IDs and timestamps for all operations
---
## Protocol Analysis Summary
### ✅ Correctly Implemented
| Feature | Status |
|---------|--------|
| TLS validation (no `rejectUnauthorized: false`) | ✅ Correct |
| WebSocket URL construction (`wss://` for HTTPS) | ✅ Correct |
| `x-meshauth` header encoding (base64 username:password) | ✅ Correct |
| Request/response ID matching | ✅ Correct |
| Typed contract schemas (Zod) | ✅ Correct |
| Allowlist-based filtering | ✅ Correct |
### ⚠️ Needs Hardening
| Feature | Issue |
|---------|-------|
| Credential validation | Missing input sanitization |
| Response validation | No schema enforcement |
| Error handling | Potential credential leakage |
| Rate limiting | Not implemented |
---
## Live Testing Safety Assessment
### ❌ Current State: **NOT SAFE**
**Blocking Issues:**
1. Credentials in error messages
2. No credential sanitization
3. Missing response validation
**Conditional Safety:**
- If deployed on an isolated, air-gapped management network with:
- Dedicated non-admin MeshCentral account
- Strict firewall rules (outbound only to MeshCentral)
- Audit logging enabled
- No public ingress
### ✅ After Remediation: **CONDITIONALLY SAFE**
The implementation can be made safe for live testing with the following changes:
1. **Input Validation:** Add sanitization for all credential and ID fields
2. **Response Validation:** Enforce Zod schema validation on all WebSocket responses
3. **Error Handling:** Remove credential-related details from user-facing errors
4. **Rate Limiting:** Implement request throttling to prevent abuse
---
## Recommendations Summary
| Priority | Action |
|----------|--------|
| 🔴 **HIGH** | Implement credential sanitization and validation |
| 🔴 **HIGH** | Add response schema validation (Zod) for all WebSocket responses |
| 🔴 **HIGH** | Sanitize error messages to prevent credential leakage |
| 🟡 **MEDIUM** | Add rate limiting for concurrent requests |
| 🟡 **MEDIUM** | Validate device/group IDs against allowed character set |
| 🟢 **LOW** | Implement structured audit logging |
| 🟢 **LOW** | Add separate connection/request timeout configuration |
---
## Appendices
### A. Test Coverage Summary
| Test Suite | Tests Passed | Status |
|-----------|-------------|--------|
| timeout.test.ts | 4/4 | ✅ |
| device-status.test.ts | 6/6 | ✅ |
| adapter-factory.test.ts | 3/3 | ✅ |
| contracts.test.ts | 5/5 | ✅ |
| group-filtering.test.ts | 4/4 | ✅ |
| mock-data-loader.test.ts | 2/2 | ✅ |
| integration.test.ts | 8/8 | ✅ |
| mock-adapter.test.ts | 20/20 | ✅ |
### B. Dependency Security
| Package | Version | Known Vulnerabilities |
|---------|---------|----------------------|
| `ws` | 8.21.3 | None reported (as of 2026-08-25) |
| `zod` | 3.24.2 | None reported (as of 2026-08-25) |
| `axios` | 1.8.1 | None reported (as of 2026-08-25) |
### C. Protocol References
- MeshCentral version: 1.2.5 (released 2026-08-12)
- Control endpoint: `/control.ashx` (WebSocket)
- Auth header: `x-meshauth` (base64 encoded credentials)
- Actions: `serverversion`, `userinfo`, `meshes`, `nodes`, `events`, `deviceinfo`
---
## Conclusion
The bridge implementation demonstrates a solid understanding of security principles in its design, particularly around TLS validation and allowlist enforcement. However, the current code contains critical gaps in credential handling, input validation, and error sanitization that must be addressed before any live deployment.
**Final Verdict:** **DO NOT ENABLE LIVE TESTING** until the three high-severity findings are remediated.
---
*Review completed: 2026-08-25 01:45 EDT*
*Subagent session: ca174557-cd3e-4d97-90a9-31efee68aebd*