git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
7.9 KiB
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
-
Task Completion Spoofing
- Nodes cannot complete tasks not assigned to them
- Verified via
assignment.assignedTo === nodeId
-
Replay Attacks
- Tasks cannot be completed twice
completedTasksSet prevents duplicates
-
Credit Self-Reporting
- Clients cannot claim their own credits
ledger_updatemessages rejected
⚠️ PARTIALLY PROTECTED
- 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):
function validateSignature(nodeId, message, signature, publicKey) {
// TODO: In production, verify Ed25519 signature from PiKey
return nodes.has(nodeId); // Placeholder
}
Required Fix:
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:
// 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
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
- Task assignment tracking
- Replay attack prevention
- Credit self-reporting blocked
- QDAG Firestore ledger
- Rate limiting
- Message size limits
- Connection limits
- Origin validation
- 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
-
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
-
Task Assignment Security - Well implemented
- Assignment tracked with metadata
- Node ID verification on completion
- Public key stored at assignment time
- Task expiration (5 minutes)
-
Defense in Depth - Multiple layers
- Origin validation (CORS)
- Connection limits (per IP)
- Rate limiting (per node)
- Message size limits
- Heartbeat timeout
Security Weaknesses
-
No Cryptographic Verification - Major gap
- Public key ownership not proven
- Allows read-only spoofing
- Required for production
-
Memory Leaks - Minor issues
completedTasksgrows unbounded- Easy to fix with periodic cleanup
-
Distributed Attacks - Missing protections
- No global connection limit
- Vulnerable to distributed DoS
- Can be mitigated with cloud-level protections
🛡️ Security Best Practices
For Developers
-
Never trust client input
- All credits server-generated
- Task assignments server-controlled
- Ledger state from Firestore only
-
Validate everything
- Check task assignment before crediting
- Verify node registration before operations
- Rate-limit all message types
-
Defense in depth
- Multiple security layers
- Fail securely (default deny)
- Log security events
For Operations
-
Monitor security metrics
- Failed authentication attempts
- Rate limit violations
- Connection flooding
- Unusual credit patterns
-
Configure Firestore security
- Validate security rules
- Restrict ledger write access
- Enable audit logging
-
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:
- Check relay logs for suspicious patterns
- Query Firestore for unexpected credit increases
- Review rate limit logs for flooding attempts
- Audit task completions for spoofing attempts
- Contact security team if confirmed breach
Emergency shutdown:
# 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