archipelagoandClaude Opus 5 0a1d314ffa feat(security): add LND macaroon rotation for the /lnd-connect-info leak
Operator tool for the fix in a05956c4. GET /lnd-connect-info answered
unauthenticated callers with the LND ADMIN MACAROON, the TLS cert, the
gRPC/REST ports and the node's onion address. Every macaroon on an
affected node must be treated as known to an attacker.

Rotation removes the macaroon root key from macaroons.db plus the issued
macaroon files; LND mints a fresh root key on unlock, so every
previously issued macaroon — including any the attacker holds — stops
verifying. Coins live in wallet.db and channel state in channel.db, and
macaroons are bearer tokens rather than keys, so neither database is
touched, opened or moved.

Safety properties, in the order they matter:

- Detect-only by DEFAULT. --apply additionally requires --yes.
- An ORDERING GUARD refuses to rotate on a node whose binary lacks the
  fix, because the new macaroon would leak through the same door within
  seconds and the operator would believe they were safe. Overridable
  only via an explicit --force-unpatched.
- It backs up the old material to a 0700 dir OUTSIDE the dir LND
  rescans, verifies the backup file count matches, and refuses to delete
  anything if it does not.
- It never reads, prints or copies a macaroon's CONTENT. Everything it
  reports is a SHA-256 digest, so the material is proven changed without
  disclosing it to the terminal or scrollback. lncli runs INSIDE the
  container and reads the macaroon off its own disk, so the secret never
  crosses into this script's output.
- It records the node identity pubkey and channel census BEFORE, and
  aborts loudly if the identity or the OPEN channel total changed.

Two deliberate non-assertions, both of which would otherwise produce
frightening false alarms on a completely healthy rotation:

- wallet.db is NOT asserted byte-identical. btcwallet records chain sync
  progress inside it, so it legitimately changes on every start.
- num_active_channels alone is NOT asserted. It counts channels whose
  peer is currently online and so legitimately dips after any restart
  while peers reconnect. The safety invariant is the ACTIVE+INACTIVE
  total, which is what gets asserted; a changed active count is reported
  as normal post-restart behaviour.

Enumeration runs under sudo rather than as a shell glob: the LND data
dir is 0700 owned by the container's mapped uid, so "$LND_DIR"/*.macaroon
does not expand in an unprivileged shell — it stays literal, which would
have made both the backup and the removal loop silent no-ops. Verified
on a live node: sudo find returns 9 files where the glob returns 0.

Exercised in detect mode against a real LND on a live node: correctly
reported the binary as unpatched, live-probed :18083 as LEAKING (200),
read both digests and the node identity, and exited 2 without changing
anything.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 16:28:09 -04:00
2026-03-17 00:03:08 +00:00

Archipelago

Self-sovereign Bitcoin node OS and manifest-driven app platform.

Archipelago is a bootable personal server OS for Bitcoin infrastructure, self-hosted apps, mesh communication, decentralized identity, and federation. Apps are packaged as declarative manifest.yml files and run as rootless Podman containers managed by the Rust backend.

Debian 13 License Rust Vue.js Version

What is here

  • core/ - Rust workspace: backend API, container runtime, security, OpenWrt helpers, and performance/resource management.
  • neode-ui/ - Vue 3 + TypeScript frontend.
  • apps/ - app manifests and custom app container sources.
  • docker/ - supporting container build contexts for UI companion surfaces.
  • image-recipe/ - bootable image/ISO build inputs.
  • Android/ - Android companion app.
  • scripts/ - development, release, deployment, and validation tooling.
  • docs/ - architecture, app packaging, operations, API, and roadmap docs.

Platform model

Archipelago is built as a developer-ready app platform, not a fixed appliance:

  • Apps are declared in apps/<app-id>/manifest.yml.
  • The Rust parser in core/container/src/manifest.rs is the canonical schema.
  • The orchestrator compiles manifests to rootless Podman/Quadlet runtime state.
  • App data lives under /var/lib/archipelago/<app-id>/.
  • Secrets are generated or read from /var/lib/archipelago/secrets/ and injected through Podman secrets rather than static environment values.
  • Release and app catalogs are signed and verified against a pinned trust anchor.

Start with:

Quick start

Frontend

cd neode-ui
npm install
npm start

The dev UI runs at http://localhost:8100 with a mock backend on :5959.

Backend

cd core
cargo build
cargo test --all-features

Linux is the supported backend runtime and release-build target. macOS is fine for frontend work and many Rust compile/test loops, but host integration tests that touch Podman, systemd, networking, or image build paths require Linux.

App manifests

./scripts/validate-app-manifest.sh apps/filebrowser/manifest.yml
python3 scripts/generate-app-catalog.py
python3 scripts/check-app-catalog-drift.py --release --strict

scripts/generate-app-catalog.py requires Python with PyYAML installed.

Documentation map

Doc Purpose
Architecture System layers, crates, data paths, security model
Developer Guide Local setup, code workflow, testing
API Reference JSON-RPC API overview
App Developer Guide How to package and test apps
App Manifest Spec Manifest schema and validation rules
Nostr Git Source Hosting Plan ngit/NIP-34 contribution workflow and maintainer model
Apps README Packaged app catalog overview
Image Recipe Bootable image build flow
Operations Runbook Production operations and recovery
Open Source Readiness Public-release cleanup checklist
Roadmap Shipped, in-progress, and planned work
Unified Task Tracker Launch hardening task list
Archive Historical plans, audits, and handoffs

Contributing

Read CONTRIBUTING.md before opening a pull request. For security issues, follow SECURITY.md and do not open a public issue.

License

Archipelago is licensed under the MIT License. Third-party notices are listed in NOTICE and generated license inventories in component release artifacts.

S
Description
No description provided
Readme MIT
3 GiB
2026-07-24 08:06:36 +00:00
Languages
Rust 45.6%
Vue 20%
TypeScript 10.3%
Shell 9.3%
JavaScript 5.7%
Other 9.1%