git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
303 lines
7.9 KiB
Markdown
303 lines
7.9 KiB
Markdown
# Edge-Net Relay Security Quick Reference
|
|
|
|
**Last Updated**: 2026-01-03
|
|
**Component**: WebSocket Relay Server (`/relay/index.js`)
|
|
**Security Status**: ✅ SECURE (development) | ⚠️ NEEDS SIGNATURES (production)
|
|
|
|
---
|
|
|
|
## 🔒 Security Features Summary
|
|
|
|
| Feature | Status | Implementation |
|
|
|---------|--------|----------------|
|
|
| Task Assignment Verification | ✅ **SECURE** | Tracked in `assignedTasks` Map |
|
|
| Replay Attack Prevention | ✅ **SECURE** | `completedTasks` Set with pre-credit marking |
|
|
| Credit Self-Reporting Block | ✅ **SECURE** | `ledger_update` rejected, relay-only crediting |
|
|
| QDAG Ledger (Firestore) | ✅ **SECURE** | Server-side source of truth |
|
|
| Rate Limiting | ✅ **IMPLEMENTED** | 100 msg/min per node |
|
|
| Message Size Limits | ✅ **IMPLEMENTED** | 64KB max payload |
|
|
| Connection Limits | ✅ **IMPLEMENTED** | 5 per IP |
|
|
| Origin Validation | ✅ **IMPLEMENTED** | CORS whitelist |
|
|
| Signature Verification | ❌ **NOT IMPLEMENTED** | Placeholder only |
|
|
|
|
---
|
|
|
|
## 🎯 Attack Vector Status
|
|
|
|
### ✅ **PROTECTED**
|
|
|
|
1. **Task Completion Spoofing**
|
|
- Nodes cannot complete tasks not assigned to them
|
|
- Verified via `assignment.assignedTo === nodeId`
|
|
|
|
2. **Replay Attacks**
|
|
- Tasks cannot be completed twice
|
|
- `completedTasks` Set prevents duplicates
|
|
|
|
3. **Credit Self-Reporting**
|
|
- Clients cannot claim their own credits
|
|
- `ledger_update` messages rejected
|
|
|
|
### ⚠️ **PARTIALLY PROTECTED**
|
|
|
|
4. **Public Key Spoofing**
|
|
- ✅ Cannot steal credits (assigned at task time)
|
|
- ⚠️ Can check another user's balance (read-only spoofing)
|
|
- ❌ No cryptographic proof of key ownership
|
|
|
|
---
|
|
|
|
## 🚨 Critical Issues for Production
|
|
|
|
### 1. Missing Signature Verification (CRITICAL)
|
|
|
|
**Current Code** (Lines 281-286):
|
|
```javascript
|
|
function validateSignature(nodeId, message, signature, publicKey) {
|
|
// TODO: In production, verify Ed25519 signature from PiKey
|
|
return nodes.has(nodeId); // Placeholder
|
|
}
|
|
```
|
|
|
|
**Required Fix**:
|
|
```javascript
|
|
import { verify } from '@noble/ed25519';
|
|
|
|
async function validateSignature(message, signature, publicKey) {
|
|
try {
|
|
const msgHash = createHash('sha256').update(JSON.stringify(message)).digest();
|
|
return await verify(signature, msgHash, publicKey);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Require on sensitive operations
|
|
case 'task_complete':
|
|
if (!message.signature || !await validateSignature(message, message.signature, ws.publicKey)) {
|
|
ws.send(JSON.stringify({ type: 'error', message: 'Invalid signature' }));
|
|
break;
|
|
}
|
|
```
|
|
|
|
**Priority**: 🔴 **CRITICAL** - Must implement before production
|
|
|
|
### 2. Unbounded Memory Growth (MEDIUM)
|
|
|
|
**Issue**: `completedTasks` Set grows forever
|
|
|
|
**Fix**:
|
|
```javascript
|
|
// Add timestamp tracking
|
|
const completedTasks = new Map(); // taskId -> timestamp
|
|
|
|
// Cleanup old completed tasks
|
|
setInterval(() => {
|
|
const CLEANUP_AGE = 24 * 60 * 60 * 1000; // 24 hours
|
|
const cutoff = Date.now() - CLEANUP_AGE;
|
|
for (const [taskId, timestamp] of completedTasks) {
|
|
if (timestamp < cutoff) {
|
|
completedTasks.delete(taskId);
|
|
}
|
|
}
|
|
}, 60 * 60 * 1000); // Every hour
|
|
```
|
|
|
|
**Priority**: 🟡 **MEDIUM** - Implement before long-running deployment
|
|
|
|
---
|
|
|
|
## 🧪 Security Test Suite
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
cd /workspaces/ruvector/examples/edge-net/tests
|
|
npm install
|
|
npm test
|
|
```
|
|
|
|
### Test Coverage
|
|
|
|
- ✅ Task completion spoofing (2 tests)
|
|
- ✅ Replay attacks (1 test)
|
|
- ✅ Credit self-reporting (2 tests)
|
|
- ✅ Public key spoofing (2 tests)
|
|
- ✅ Rate limiting (1 test)
|
|
- ✅ Message size limits (1 test)
|
|
- ✅ Connection limits (1 test)
|
|
- ✅ Combined attack scenario (1 test)
|
|
|
|
**Total**: 12 security tests in `relay-security.test.ts`
|
|
|
|
---
|
|
|
|
## 📋 Security Checklist
|
|
|
|
### Before Development Deployment
|
|
|
|
- [x] Task assignment tracking
|
|
- [x] Replay attack prevention
|
|
- [x] Credit self-reporting blocked
|
|
- [x] QDAG Firestore ledger
|
|
- [x] Rate limiting
|
|
- [x] Message size limits
|
|
- [x] Connection limits
|
|
- [x] Origin validation
|
|
- [x] Security test suite
|
|
|
|
### Before Production Deployment
|
|
|
|
- [ ] **Ed25519 signature verification** (CRITICAL)
|
|
- [ ] **Challenge-response on registration** (CRITICAL)
|
|
- [ ] Completed tasks cleanup (MEDIUM)
|
|
- [ ] Global connection limit (MEDIUM)
|
|
- [ ] API key for non-browser clients (MEDIUM)
|
|
- [ ] Rate-limit balance queries (LOW)
|
|
- [ ] Generic error messages (LOW)
|
|
- [ ] Firestore security rules validation (LOW)
|
|
|
|
---
|
|
|
|
## 🔍 Code Review Findings
|
|
|
|
### Security Strengths
|
|
|
|
1. **QDAG Architecture** - Excellent design
|
|
- Firestore as single source of truth
|
|
- Credits keyed by public key (identity-based)
|
|
- Server-side only credit increases
|
|
- Persistent across sessions
|
|
|
|
2. **Task Assignment Security** - Well implemented
|
|
- Assignment tracked with metadata
|
|
- Node ID verification on completion
|
|
- Public key stored at assignment time
|
|
- Task expiration (5 minutes)
|
|
|
|
3. **Defense in Depth** - Multiple layers
|
|
- Origin validation (CORS)
|
|
- Connection limits (per IP)
|
|
- Rate limiting (per node)
|
|
- Message size limits
|
|
- Heartbeat timeout
|
|
|
|
### Security Weaknesses
|
|
|
|
1. **No Cryptographic Verification** - Major gap
|
|
- Public key ownership not proven
|
|
- Allows read-only spoofing
|
|
- Required for production
|
|
|
|
2. **Memory Leaks** - Minor issues
|
|
- `completedTasks` grows unbounded
|
|
- Easy to fix with periodic cleanup
|
|
|
|
3. **Distributed Attacks** - Missing protections
|
|
- No global connection limit
|
|
- Vulnerable to distributed DoS
|
|
- Can be mitigated with cloud-level protections
|
|
|
|
---
|
|
|
|
## 🛡️ Security Best Practices
|
|
|
|
### For Developers
|
|
|
|
1. **Never trust client input**
|
|
- All credits server-generated
|
|
- Task assignments server-controlled
|
|
- Ledger state from Firestore only
|
|
|
|
2. **Validate everything**
|
|
- Check task assignment before crediting
|
|
- Verify node registration before operations
|
|
- Rate-limit all message types
|
|
|
|
3. **Defense in depth**
|
|
- Multiple security layers
|
|
- Fail securely (default deny)
|
|
- Log security events
|
|
|
|
### For Operations
|
|
|
|
1. **Monitor security metrics**
|
|
- Failed authentication attempts
|
|
- Rate limit violations
|
|
- Connection flooding
|
|
- Unusual credit patterns
|
|
|
|
2. **Configure Firestore security**
|
|
- Validate security rules
|
|
- Restrict ledger write access
|
|
- Enable audit logging
|
|
|
|
3. **Network security**
|
|
- Use TLS/WSS in production
|
|
- Configure firewall rules
|
|
- Enable DDoS protection
|
|
|
|
---
|
|
|
|
## 📊 Security Metrics
|
|
|
|
### Current Implementation
|
|
|
|
| Metric | Value | Status |
|
|
|--------|-------|--------|
|
|
| Authentication | Public key (unverified) | ⚠️ Development only |
|
|
| Authorization | Task assignment tracking | ✅ Secure |
|
|
| Credit System | Firestore QDAG | ✅ Secure |
|
|
| Rate Limiting | 100 msg/min | ✅ Good |
|
|
| Max Message Size | 64KB | ✅ Good |
|
|
| Connections per IP | 5 | ✅ Good |
|
|
| Connection Timeout | 30s | ✅ Good |
|
|
| Task Expiration | 5 min | ✅ Good |
|
|
|
|
### Recommended Production Values
|
|
|
|
| Metric | Development | Production |
|
|
|--------|-------------|------------|
|
|
| Authentication | Public key | Ed25519 signature |
|
|
| Rate Limit | 100 msg/min | 50 msg/min + adaptive |
|
|
| Max Connections | 5 per IP | 3 per IP + global limit |
|
|
| Task Timeout | 5 min | 2 min |
|
|
| Completed Tasks TTL | None | 24 hours |
|
|
|
|
---
|
|
|
|
## 📚 Related Documentation
|
|
|
|
- **Full Audit Report**: `/docs/SECURITY_AUDIT_REPORT.md`
|
|
- **Test Suite**: `/tests/relay-security.test.ts`
|
|
- **Test README**: `/tests/README.md`
|
|
- **Relay Source**: `/relay/index.js`
|
|
|
|
---
|
|
|
|
## 🆘 Security Incident Response
|
|
|
|
### If you suspect an attack:
|
|
|
|
1. **Check relay logs** for suspicious patterns
|
|
2. **Query Firestore** for unexpected credit increases
|
|
3. **Review rate limit logs** for flooding attempts
|
|
4. **Audit task completions** for spoofing attempts
|
|
5. **Contact security team** if confirmed breach
|
|
|
|
### Emergency shutdown:
|
|
|
|
```bash
|
|
# Stop relay server
|
|
pkill -f "node.*relay/index.js"
|
|
|
|
# Or send SIGTERM for graceful shutdown
|
|
kill -TERM $(pgrep -f "node.*relay/index.js")
|
|
```
|
|
|
|
---
|
|
|
|
**Security Contact**: [Your security team contact]
|
|
**Last Security Audit**: 2026-01-03
|
|
**Next Scheduled Audit**: After signature verification implementation
|