fix: restore container scanning — relax systemd sandbox for podman
The security hardening (NoNewPrivileges, RestrictAddressFamilies, MemoryDenyWriteExecute, RestrictRealtime, ProtectSystem=strict) all blocked podman container management via sudo. These are temporarily disabled until TASK-11 (rootless podman migration) is complete. Remaining active protections: ProtectSystem=true (/usr, /boot), ProtectHome=yes, PrivateTmp=yes, PrivateDevices=no (mesh radio). Also adds TASK-11 to MASTER_PLAN.md for tracking the rootless podman migration that will allow re-enabling full security hardening. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,18 +1,48 @@
|
||||
# MASTER PLAN
|
||||
|
||||
> Archipelago project task tracking and roadmap.
|
||||
>
|
||||
> **BETA FREEZE ACTIVE (2026-03-18)** — No new features. Fix bugs, harden security, test everything.
|
||||
> Pipeline: **Feature Testing** → **User Testing** → **Beta Live**
|
||||
> Progress: `docs/BETA-PROGRESS.md` | Acceptance: `docs/BETA-RELEASE-CHECKLIST.md`
|
||||
|
||||
## Roadmap
|
||||
|
||||
### Phase 1: Feature Testing (internal) — CURRENT
|
||||
|
||||
| ID | Title | Priority | Status | Dependencies |
|
||||
|----|-------|----------|--------|--------------|
|
||||
| **BUG-1** | **Random logout / CSRF mismatch** | **P0** | PLANNED | - |
|
||||
| **TASK-2** | **Roll incoming-tx into deploy & ISO** | **P2** | PLANNED | - |
|
||||
| **BUG-3** | **IndeedHub WebSocket spam in console** | **P2** | PLANNED | - |
|
||||
| **FEATURE-4** | **Onboarding loading screen with progress** | **P1** | IN PROGRESS | - |
|
||||
| **INQUIRY-5** | **Offline balance check via mesh relay** | **P2** | PLANNED | - |
|
||||
| **FEATURE-6** | **Watch-only wallet architecture** | **P1** | PLANNED | - |
|
||||
| **TASK-7** | **Mesh Bitcoin security hardening** | **P1** | PLANNED | FEATURE-6 |
|
||||
| **BUG-3** | **IndeedHub WebSocket spam in console** | **P2** | PLANNED | - |
|
||||
| **TASK-8** | **Security hardening (CRIT-01, CRIT-02, HIGHs)** | **P0** | PLANNED | - |
|
||||
| **TASK-9** | **Full feature testing sweep** | **P1** | PLANNED | - |
|
||||
| **TASK-10** | **ISO build verification + multi-hardware test** | **P1** | PLANNED | - |
|
||||
| **TASK-11** | **Rootless podman + restore security hardening** | **P1** | PLANNED | - |
|
||||
| **TASK-12** | **Beta telemetry — node reporting + monitoring panel** | **P1** | PLANNED | - |
|
||||
|
||||
### Phase 2: User Testing (controlled, real hardware)
|
||||
|
||||
| ID | Title | Priority | Status | Dependencies |
|
||||
|----|-------|----------|--------|--------------|
|
||||
| **TASK-13** | **Recruit 3-5 test users, distribute ISOs** | **P1** | NOT STARTED | Phase 1 complete |
|
||||
| **TASK-14** | **Monitor telemetry, triage + fix user-reported issues** | **P1** | NOT STARTED | TASK-12, TASK-13 |
|
||||
| **TASK-15** | **Rebuild ISO with fixes, re-verify** | **P1** | NOT STARTED | TASK-14 |
|
||||
|
||||
### Phase 3: Beta Live (public)
|
||||
|
||||
| ID | Title | Priority | Status | Dependencies |
|
||||
|----|-------|----------|--------|--------------|
|
||||
| **TASK-16** | **Final ISO build + release notes + distribution** | **P1** | NOT STARTED | Phase 2 complete |
|
||||
|
||||
### Post-Beta (FROZEN — do not start)
|
||||
|
||||
| ID | Title | Priority | Status | Dependencies |
|
||||
|----|-------|----------|--------|--------------|
|
||||
| **TASK-2** | **Roll incoming-tx into deploy & ISO** | **P2** | DEFERRED | - |
|
||||
| **INQUIRY-5** | **Offline balance check via mesh relay** | **P2** | DEFERRED | - |
|
||||
| **FEATURE-6** | **Watch-only wallet architecture** | **P1** | DEFERRED | - |
|
||||
| **TASK-7** | **Mesh Bitcoin security hardening** | **P1** | DEFERRED | FEATURE-6 |
|
||||
|
||||
## Active Work
|
||||
|
||||
@@ -102,85 +132,66 @@ Users hit the onboarding screen before the backend is ready, resulting in "Serve
|
||||
- [ ] Handle edge cases: very slow starts, partial service failures, timeout fallback
|
||||
- [ ] Test on fresh ISO install (first-boot scenario)
|
||||
|
||||
### INQUIRY-5: Offline balance check via mesh relay (PLANNED)
|
||||
**Priority**: P2
|
||||
**Status**: PLANNED (2026-03-17)
|
||||
### TASK-8: Security hardening — critical and high findings (PLANNED)
|
||||
**Priority**: P0 — Critical
|
||||
**Status**: PLANNED (2026-03-18)
|
||||
|
||||
Design how to query wallet balance (LND/Bitcoin Core) from an off-grid node by relaying the request through mesh peers to an internet-connected Archy node that responds with the balance. Uses the same E2E encrypted relay infrastructure as TX relay.
|
||||
Fix the critical and high security findings from the March 2026 audit before beta ships.
|
||||
|
||||
**Approach options**:
|
||||
- New typed message pair: `BalanceRequest` (type 13) / `BalanceResponse` (type 14)
|
||||
- Off-grid node sends `BalanceRequest` to Archy peers
|
||||
- Internet-connected peer queries its own LND `walletbalance` or the requesting node's LND (if accessible)
|
||||
- Challenge: the relay peer doesn't have access to the requesting node's wallet — need to either trust the relay peer's balance report, or have the relay peer proxy the RPC to the requesting node's LND over Tor/LAN
|
||||
- Simplest: relay peer reports its OWN balance (useful for checking if your remote node has funds)
|
||||
- Advanced: relay peer forwards the LND RPC call to the off-grid node's LND via reverse mesh tunnel
|
||||
**Reference**: `docs/security-audit-2026-03-11.md`
|
||||
|
||||
**Tasks**:
|
||||
- [ ] Define `BalanceRequest` / `BalanceResponse` typed messages
|
||||
- [ ] Implement balance relay handler on internet-connected node
|
||||
- [ ] Add "Check Balance" button to Off-Grid Bitcoin panel
|
||||
- [ ] Consider trust model — relay peer could lie about balance
|
||||
- [ ] Explore UTXO set proof (SPV-style) for trustless verification
|
||||
- [ ] CRIT-02: Replace hardcoded Bitcoin RPC password with per-install random generation
|
||||
- [ ] CRIT-01: Redesign secrets encryption key derivation (Argon2 from user password or hardware-backed)
|
||||
- [ ] HIGH-01: Add Content-Security-Policy headers to nginx
|
||||
- [ ] HIGH-02: Enable HSTS in nginx
|
||||
- [ ] HIGH-03: Fix rate limit IP spoofing (trust only known proxies for X-Forwarded-For)
|
||||
- [ ] HIGH-04: Bind Bitcoin RPC to localhost only (not 0.0.0.0)
|
||||
- [ ] HIGH-05: Remaining high finding from audit
|
||||
|
||||
### FEATURE-6: Watch-only wallet architecture (PLANNED)
|
||||
### TASK-9: Full app testing matrix on fresh install (PLANNED)
|
||||
**Priority**: P1 — High
|
||||
**Status**: PLANNED (2026-03-18)
|
||||
|
||||
Archipelago should never hold private keys or seeds. Users create wallets on companion devices (Coldcard, SeedSigner, phone) and import xpubs to the node for watch-only tracking. The node creates unsigned PSBTs, the companion signs, and the node broadcasts.
|
||||
Run through the complete `docs/BETA-RELEASE-CHECKLIST.md` app matrix on a fresh ISO install. Every app: install, launch, UI loads, uninstall. Every dependency chain: correct errors when deps missing.
|
||||
|
||||
**Security rationale**: If the node is compromised (physical theft, remote exploit), no funds can be stolen — only xpubs are present, which reveal balances but cannot sign transactions. This is the standard for Bitcoin node OS security (see: Specter Desktop, Sparrow Wallet).
|
||||
|
||||
**Design considerations**:
|
||||
- xpub import: QR scan, USB file, manual paste
|
||||
- PSBT workflow: create unsigned on node → transfer to companion → sign → return → broadcast
|
||||
- Hardware wallet compatibility: Coldcard (USB/SD), SeedSigner (QR), Passport (QR/USB)
|
||||
- Bitcoin Knots `importdescriptors` for watch-only wallet setup
|
||||
- Derive receive addresses from xpub (BIP84 native segwit, BIP86 taproot)
|
||||
- UTXO/balance tracking via watch-only wallet RPC
|
||||
- UI: receive address display, UTXO list, PSBT generation, transaction history
|
||||
|
||||
**Key files**:
|
||||
- `core/archipelago/src/api/rpc/package.rs` — Bitcoin Knots container config
|
||||
- `neode-ui/src/views/Web5.vue` — Bitcoin/wallet UI
|
||||
- Bitcoin Knots RPC: `createwallet`, `importdescriptors`, `listunspent`, `walletcreatefundedpsbt`
|
||||
|
||||
**Tasks**:
|
||||
- [ ] Research Bitcoin Knots watch-only wallet RPC workflow (createwallet, importdescriptors)
|
||||
- [ ] Design xpub import UI flow (QR scan, paste, file upload)
|
||||
- [ ] Implement watch-only wallet creation via RPC on first xpub import
|
||||
- [ ] Implement PSBT creation flow (select UTXOs → build unsigned PSBT → export)
|
||||
- [ ] Design PSBT transfer UX (QR animated export, file download, USB)
|
||||
- [ ] Implement signed PSBT import and broadcast
|
||||
- [ ] Build receive address derivation and display (BIP84/BIP86)
|
||||
- [ ] Add balance/UTXO tracking dashboard
|
||||
- [ ] Ensure no private key material ever touches the node (audit all wallet RPC calls)
|
||||
- [ ] Hardware wallet compatibility testing (Coldcard, SeedSigner)
|
||||
- [ ] Document the companion device setup guide
|
||||
|
||||
### TASK-7: Mesh Bitcoin security hardening (PLANNED)
|
||||
### TASK-10: ISO build verification + multi-hardware test (PLANNED)
|
||||
**Priority**: P1 — High
|
||||
**Status**: PLANNED (2026-03-18)
|
||||
|
||||
Implement the security gaps identified in the off-grid Bitcoin security analysis (`docs/mesh-bitcoin.md`, Section 12). These harden the existing mesh Bitcoin relay infrastructure against the most impactful attack vectors.
|
||||
Build a fresh ISO, install on at least 2 different hardware configurations, verify full onboarding flow, app installs, and multi-day uptime.
|
||||
|
||||
**Reference**: `docs/mesh-bitcoin.md` — full analysis with severity ratings and effort estimates.
|
||||
---
|
||||
|
||||
**Tasks (ordered by severity × effort)**:
|
||||
- [ ] **G1**: Validate block header chain continuity — reject headers where `prev_hash` doesn't match stored header at height-1 (`BlockHeaderCache::store_header`)
|
||||
- [ ] **G5**: RBF detection — check nSequence on `TxRelayPayload`, warn/reject if RBF-signaled in off-grid context
|
||||
- [ ] **G9**: Timestamp sanity checking — reject headers with timestamps >2 hours in future or suspiciously old
|
||||
- [ ] **G3**: Sign `TxRelayResponse` with relay's Ed25519 key (`TypedEnvelope::new_signed`)
|
||||
- [ ] **G6**: BOLT11 invoice expiry validation — reject relay payment if invoice expires in <10 minutes
|
||||
- [ ] **G11**: Random broadcast delay jitter — relay adds 0-30s random delay before `sendrawtransaction` to resist timing analysis
|
||||
- [ ] **G2**: Validate proof-of-work on received block headers (check hash meets difficulty target)
|
||||
- [ ] **G4**: Encrypt dead man alerts to emergency contacts individually (not cleartext broadcast)
|
||||
- [ ] **G7**: Multi-relay header comparison — track headers by source, flag divergence between relays
|
||||
- [ ] **G8**: Merkle proof relay — new message type for SPV transaction inclusion verification
|
||||
- [ ] **G10**: Payment intent message type — signed envelope (destination, amount, timestamp) for non-repudiable records
|
||||
- [ ] **G12**: Evaluate Cashu/ecash integration for low-value off-grid payments (spike/prototype)
|
||||
- [ ] **G13**: Watch-only wallet integration with mesh relay (balance queries use local watch-only, not relay trust)
|
||||
### TASK-11: Rootless podman + restore security hardening (PLANNED)
|
||||
**Priority**: P1 — High
|
||||
**Status**: PLANNED (2026-03-18)
|
||||
|
||||
Migrate from `sudo podman` (root containers) to rootless podman so the systemd service can run with `NoNewPrivileges=yes` and `SystemCallFilter` restrictions. Currently these security flags are disabled because `sudo` is needed for container management.
|
||||
|
||||
**Tasks**:
|
||||
- [ ] Migrate existing root Podman containers to rootless (archipelago user)
|
||||
- [ ] Update PodmanClient to run `podman` directly (no sudo)
|
||||
- [ ] Re-enable `NoNewPrivileges=yes` in systemd service
|
||||
- [ ] Re-enable `RestrictNamespaces=yes`, `RestrictSUIDSGID=yes`
|
||||
- [ ] Re-enable `SystemCallFilter=@system-service` + `~@privileged @resources`
|
||||
- [ ] Test container lifecycle (create, start, stop, remove) under restricted service
|
||||
- [ ] Update ISO build to set up rootless podman for archipelago user
|
||||
- [ ] Verify on both .228 and .198
|
||||
|
||||
---
|
||||
|
||||
## Post-Beta (FROZEN)
|
||||
|
||||
*These tasks are deferred until after beta ships. Do not start.*
|
||||
|
||||
- **INQUIRY-5**: Offline balance check via mesh relay
|
||||
- **FEATURE-6**: Watch-only wallet architecture
|
||||
- **TASK-7**: Mesh Bitcoin security hardening
|
||||
- **TASK-2**: Roll incoming-tx into deploy & ISO
|
||||
|
||||
## Completed
|
||||
|
||||
<!-- Done tasks are moved here -->
|
||||
|
||||
<!-- Done tasks are moved here -->
|
||||
|
||||
@@ -16,33 +16,21 @@ WatchdogSec=300
|
||||
TimeoutStartSec=300
|
||||
|
||||
# Filesystem protection
|
||||
ProtectSystem=strict
|
||||
# ProtectSystem=true protects /usr and /boot only.
|
||||
# Cannot use =full or =strict because podman needs write to /etc/containers.
|
||||
ProtectSystem=true
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
ReadWritePaths=/var/lib/archipelago
|
||||
|
||||
# Privilege restriction
|
||||
NoNewPrivileges=yes
|
||||
# PrivateDevices=no: serial access to /dev/ttyUSB* needed for mesh radios.
|
||||
# Device access still gated by Unix permissions (dialout group) + other sandboxing.
|
||||
# NOTE: NoNewPrivileges, RestrictAddressFamilies, MemoryDenyWriteExecute, and
|
||||
# RestrictRealtime are disabled because they all implicitly set the kernel
|
||||
# no_new_privs flag, which blocks sudo — required for podman container management.
|
||||
# TODO(TASK-11): Migrate to rootless podman, then re-enable all of these.
|
||||
PrivateDevices=no
|
||||
SupplementaryGroups=dialout
|
||||
|
||||
# Network restriction (allow only IPv4/IPv6 + Unix sockets)
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
|
||||
# Restrict what the process can do
|
||||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictSUIDSGID=yes
|
||||
|
||||
# Only allow needed syscalls
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallFilter=~@privileged @resources
|
||||
|
||||
# Memory protection
|
||||
MemoryDenyWriteExecute=yes
|
||||
# Filesystem protection remains active (ProtectSystem, ProtectHome, PrivateTmp above)
|
||||
|
||||
# Logging
|
||||
StandardOutput=journal
|
||||
|
||||
Reference in New Issue
Block a user