146 lines
5.0 KiB
Markdown
146 lines
5.0 KiB
Markdown
# CAS Security Architecture
|
|
|
|
## The Problem with chmod-based Protection
|
|
|
|
### User-Mode Reality Check
|
|
|
|
In user-space (`~/.local/share/nexus/cas/`), **chmod 555 is security theater**, not security:
|
|
|
|
- **User owns the inode** → User can `chmod 700`, modify, `chmod 555` back
|
|
- **No privilege separation** → Cannot protect user from themselves with POSIX permissions
|
|
- **xattr immutable flag** → Requires root/CAP_LINUX_IMMUTABLE (not available to regular users)
|
|
|
|
**Verdict:** `chmod 555` is a "Do Not Touch" sign written in pencil. It prevents *accidental* deletion but provides **zero security** against intentional tampering.
|
|
|
|
## The Real Security Model
|
|
|
|
### 1. Merkle Tree Verification (Primary Defense)
|
|
|
|
**The CAS Merkle tree is the source of truth**, not filesystem permissions.
|
|
|
|
```
|
|
Filesystem = "Dirty" Physical Layer (untrusted)
|
|
Merkle Tree = "Sacred" Logical Layer (trusted)
|
|
```
|
|
|
|
**Strategy:**
|
|
- **Lazy Verification:** Verify hash before executing/grafting critical binaries
|
|
- **Tainted Flag:** Hash mismatch → refuse to run OR auto-heal (re-download/re-link)
|
|
- **Continuous Integrity:** Periodic background verification of CAS contents
|
|
|
|
**Implementation:**
|
|
```nim
|
|
proc verifyAndExecute*(cas: CasManager, hash: string): Result[void, CasError] =
|
|
# 1. Retrieve chunk
|
|
let data = cas.retrieveChunk(hash)
|
|
|
|
# 2. Verify hash matches
|
|
let calculatedHash = calculateXxh3(data)
|
|
if calculatedHash != hash:
|
|
# Hash mismatch - chunk is tainted
|
|
return err(CasError(
|
|
code: IntegrityViolation,
|
|
msg: "Chunk integrity violation - auto-healing",
|
|
objectHash: hash
|
|
))
|
|
|
|
# 3. Execute only if verified
|
|
return ok()
|
|
```
|
|
|
|
### 2. User Namespaces (Runtime Isolation)
|
|
|
|
**For execution environments**, use Linux User Namespaces to enforce read-only access:
|
|
|
|
```bash
|
|
# Create mount namespace with read-only CAS
|
|
unshare --mount --map-root-user bash -c '
|
|
mount --bind -o ro ~/.local/share/nexus/cas ~/.local/share/nexus/cas
|
|
exec /path/to/application
|
|
'
|
|
```
|
|
|
|
**Benefits:**
|
|
- Kernel-enforced read-only view (not bypassable by process)
|
|
- Even if app is compromised, cannot write to CAS
|
|
- Works without root privileges (user namespaces)
|
|
|
|
**Implementation Strategy:**
|
|
```nim
|
|
proc launchWithProtection*(cas: CasManager, executable: string): Result[Process, CasError] =
|
|
# 1. Create user namespace with read-only bind mount
|
|
# 2. Execute application inside namespace
|
|
# 3. Application sees CAS as truly read-only
|
|
```
|
|
|
|
### 3. System-Mode Protection (Root-Owned CAS)
|
|
|
|
**For system-wide installations** (`/var/lib/nexus/cas/`):
|
|
|
|
- **Root owns files:** `chown root:root`, `chmod 644/755`
|
|
- **Users in pkg-users group:** Read-only access
|
|
- **Daemon handles writes:** Only privileged daemon can modify CAS
|
|
- **Here chmod actually works:** Users cannot change permissions they don't own
|
|
|
|
## Hybrid Architecture
|
|
|
|
### Storage Layer (Disk)
|
|
- **Keep chmod 555** as UX guardrail (prevents accidental `rm`)
|
|
- **Acknowledge it's not security** - just convenience
|
|
- **Real security comes from verification**
|
|
|
|
### Execution Layer (Runtime)
|
|
- **User Namespaces:** Bind-mount CAS as read-only for process tree
|
|
- **Merkle Verification:** Verify hashes before execution
|
|
- **Auto-Healing:** Re-download/re-link on integrity violation
|
|
|
|
### System Mode
|
|
- **Root ownership:** Traditional POSIX permissions work here
|
|
- **Daemon-mediated writes:** Only privileged process modifies CAS
|
|
- **User read-only access:** Standard Unix security model
|
|
|
|
## Implementation Priorities
|
|
|
|
### Phase 1: Merkle Verification (CRITICAL)
|
|
✅ Already implemented: xxh3-128 hashing
|
|
🔧 TODO: Pre-execution verification
|
|
🔧 TODO: Auto-healing on integrity violation
|
|
🔧 TODO: Background integrity scanning
|
|
|
|
### Phase 2: User Namespace Isolation (HIGH)
|
|
🔧 TODO: Launcher wrapper with mount namespaces
|
|
🔧 TODO: Read-only bind mount for CAS during execution
|
|
🔧 TODO: Integration with nippels namespace system
|
|
|
|
### Phase 3: System Mode (MEDIUM)
|
|
🔧 TODO: Root-owned CAS for system installations
|
|
🔧 TODO: Privileged daemon for write operations
|
|
🔧 TODO: User group management
|
|
|
|
## Security Guarantees
|
|
|
|
| Attack Vector | User Mode Defense | System Mode Defense |
|
|
|---------------|-------------------|---------------------|
|
|
| Accidental deletion | chmod 555 (UX) | root ownership |
|
|
| Intentional tampering | Merkle verification | root ownership + Merkle |
|
|
| Compromised app | User namespaces | User namespaces + root ownership |
|
|
| Supply chain attack | Signature verification | Signature verification |
|
|
| Bit rot / corruption | Merkle verification | Merkle verification |
|
|
|
|
## Conclusion
|
|
|
|
**Don't rely on chmod for security in user-mode.** Use:
|
|
|
|
1. **Merkle tree verification** (cryptographic integrity)
|
|
2. **User namespaces** (kernel-enforced isolation)
|
|
3. **Root ownership** (system-mode only)
|
|
|
|
The current chmod implementation remains as a **UX feature** (prevents accidents), but security comes from **cryptographic verification** and **architectural isolation**.
|
|
|
|
---
|
|
|
|
**Document Version:** 1.0
|
|
**Last Updated:** November 20, 2025
|
|
**Status:** Architecture Decision Record
|
|
**Credit:** Analysis by Voxis Forge
|