Commit Graph

28 Commits

Author SHA1 Message Date
Shadowbroker 2e14e75a0e Fix #256: per-peer HMAC secrets defeat cross-peer impersonation (#281)
Before this change, every peer-push HMAC was derived from the single
fleet-shared MESH_PEER_PUSH_SECRET. The receiver could prove "this
request was signed by someone who knows the fleet secret" but it could
NOT prove which peer signed it. Any peer that knew the global secret
could compute the expected HMAC for any other peer URL and forge a
push pretending to be that peer.

Fix: introduce MESH_PEER_SECRETS, an optional comma-separated
url=secret map. When a peer URL appears in the map, only the listed
per-peer secret is accepted for it -- the global secret is ignored for
that specific URL. Peer A no longer knows peer B's secret, so peer A
cannot forge a push claiming to be peer B.

The new helper resolve_peer_key_for_url() in mesh_crypto.py wraps the
lookup and is called from every existing peer-push call site:

- backend/auth.py:_verify_peer_push_hmac (receiver)
- backend/main.py:_http_peer_push_loop (Infonet event push)
- backend/main.py:_http_gate_pull_loop (gate event pull)
- backend/main.py:_http_gate_push_loop (gate event push)
- backend/services/mesh/mesh_router.py (two transports, push)
- backend/services/mesh/mesh_hashchain.py (gate wire ref key)
- backend/services/mesh/mesh_wormhole_prekey.py (peer prekey lookup)

Zero hostility, by design:

- Single-peer installs leave MESH_PEER_SECRETS empty -> resolver falls
  back to MESH_PEER_PUSH_SECRET -> behavior is byte-for-byte unchanged.
- Multi-peer installs that haven't migrated yet behave exactly as
  before.
- Multi-peer installs that DO migrate set MESH_PEER_SECRETS on both
  ends of each peering and immediately close the impersonation surface
  for those URLs. Migration is incremental: unlisted peers keep using
  the global secret.

Tests in backend/tests/test_per_peer_secret_resolver.py:
- env parsing (default, override, whitespace, malformed entries, cache)
- precedence: per-peer beats global
- migration window: unlisted peer falls back to global
- IMPERSONATION REFUSAL: peer A with global-secret-only cannot forge
  HMAC for peer B that has a per-peer secret configured
- IMPERSONATION REFUSAL: peer A with its OWN per-peer secret cannot
  forge HMAC for peer B
- positive control: legitimate peer B request verifies
- zero-behavior-change: single-peer install produces the same key bytes
  as before the change

Credit: tg12 (external security audit, P1/High/High confidence)
2026-05-21 10:05:29 -06:00
Shadowbroker 9ef6213284 Fix #250: bind Docker bridge local-operator trust to frontend hostname (#278)
Tightens the bridge-trust check so a connection on the Docker bridge
is only granted local-operator status when its source IP matches a
configured frontend container hostname (default: `frontend` + the
shipped `container_name` `shadowbroker-frontend`). Previously, when
`SHADOWBROKER_TRUST_DOCKER_BRIDGE_LOCAL_OPERATOR=1` was set, ANY IP
in the 172.16.0.0/12 range was granted local-operator privileges —
on a shared Docker host that included any unrelated container on the
same bridge.

Operators with renamed services can list new hostnames via the new
`SHADOWBROKER_TRUSTED_FRONTEND_HOSTS` env var (comma-separated). DNS
resolution is cached for 30s; if Docker DNS can't resolve any of the
configured names we fail closed and refuse the bridge entirely.

Single-user installs see no behavior change — the default-named
frontend container still resolves and is still trusted.

Credit: tg12 (external security audit)
2026-05-21 02:06:11 -06:00
BigBodyCobain 11ea345518 Harden infonet control surfaces 2026-05-18 11:22:38 -06:00
BigBodyCobain b8ac0fb9e7 Harden v0.9.75 wormhole node sync and telemetry panels
Add Tor/onion runtime wiring and faster Infonet node status refresh.

Keep node bootstrap state clearer across Docker and local runtimes.

Use selected aircraft trail history for cumulative tracked-aircraft emissions.
2026-05-06 14:04:16 -06:00
BigBodyCobain 63043b32b5 Stabilize Docker startup and runtime proxy
Reduce cold-start stalls by raising the default backend memory limit, bounding heavy feed concurrency, preserving non-empty startup caches, and refreshing working news feeds. Fix the Next API proxy for Docker control-plane writes by stripping unsupported hop/body headers and forwarding small request bodies safely. Keep the dashboard dynamic so production users do not get stuck on a cached startup shell.
2026-05-04 12:37:23 -06:00
BigBodyCobain 1e34fa53b2 Make Docker backend port configurable 2026-05-03 21:13:31 -06:00
BigBodyCobain eb0288ee4e Fix Docker local controls and setup guidance
Allow the bundled Docker frontend proxy to reach local-operator endpoints through the private compose bridge without trusting LAN clients. This restores Time Machine, MeshChat key creation, AI pins/layers, and related local controls in Docker installs. Refresh first-run guidance so Docker users know to configure OpenSky and AIS keys through .env.
2026-05-02 20:18:46 -06:00
BigBodyCobain fa18c032e2 Fix Docker first-run startup data seeding
Seed safe static backend data into fresh Docker volumes, tighten Docker build-context exclusions, avoid optional env warnings, and make the frontend healthcheck use the IPv4 loopback path that works inside the container.
2026-05-02 19:27:59 -06:00
BigBodyCobain 28b3bd5ebf release: prepare v0.9.7 2026-05-01 22:56:50 -06:00
anoracleofra-code d419ee63e1 chore: revert docker-compose to GHCR registry
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 09:11:53 -06:00
anoracleofra-code a3e7a2bc6b feat: add Docker Hub as primary registry for anonymous pulls
GHCR requires authentication even for public packages on some systems.
CI now pushes to both GHCR and Docker Hub. docker-compose.yml and Helm
chart point to Docker Hub where anonymous pulls always work. Build
directives kept as fallback for source-based builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 08:13:14 -06:00
anoracleofra-code ae627a89d7 fix: align transport secret with cipher0 relay
Use cipher0's existing MESH_PEER_PUSH_SECRET so nodes connect
to the relay out of the box without configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 22:11:17 -06:00
anoracleofra-code 59b1723866 feat: fix gate message delivery + per-gate content encryption
Phase 1 — Transport layer fix:
- Bake in default MESH_PEER_PUSH_SECRET so peer push, real-time
  propagation, and pull-sync all work out of the box instead of
  silently no-oping on an empty secret.
- Pass secret through docker-compose.yml for container deployments.

Phase 2 — Per-gate content keys:
- Generate a cryptographically random 32-byte secret per gate on
  creation (and backfill existing gates on startup).
- Upgrade HKDF envelope encryption to use per-gate secret as IKM
  so knowing a gate name alone no longer decrypts messages.
- 3-tier decryption fallback (phase2 key → legacy name-only →
  legacy node-local) preserves backward compatibility.
- Expose gate_secret via list_gates API for authorized members.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 22:00:36 -06:00
anoracleofra-code c5d48aa636 feat: pass FINNHUB_API_KEY to Docker, update layer defaults, cluster APRS
- Add FINNHUB_API_KEY to docker-compose.yml so financial ticker works
  in Docker deployments
- Update default layer config: planes/ships ON, satellites only for
  space, no fire hotspots, military bases + internet outages for infra,
  all SIGINT except HF digital spots
- Add MapLibre native clustering to APRS markers (matches Meshtastic)
  with cluster radius 42, breaks apart at zoom 8
2026-03-26 20:16:40 -06:00
anoracleofra-code 3cbe8090a9 fix: add default relay peer so fresh installs can sync Infonet
On a fresh Docker (or local) install, MESH_RELAY_PEERS was empty and
no bootstrap manifest existed, leaving the Infonet node with zero
peers to sync from — causing perpetual "RETRYING" status.

Set cipher0.shadowbroker.info:8000 as the default relay peer in both
the config defaults and docker-compose.yml so new installations sync
immediately after activating the wormhole.
2026-03-26 17:31:16 -06:00
anoracleofra-code 165743e92d fix: remove build sections from docker-compose.yml so pull works
docker compose pull was skipping with "No image to be pulled" because
the build: sections made Compose treat local builds as authoritative.
Moved build config to docker-compose.build.yml for developers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 08:16:30 -06:00
anoracleofra-code 784405b808 fix: add GHCR image refs to docker-compose and increase health start period
Users pulling pre-built images need the image: field. Increased backend
health check start_period from 30s to 60s with 5 retries to handle
slower startup environments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 06:50:08 -06:00
anoracleofra-code 668ce16dc7 v0.9.6: InfoNet hashchain, Wormhole gate encryption, mesh reputation, 16 community contributors
Gate messages now propagate via the Infonet hashchain as encrypted blobs — every node syncs them
through normal chain sync while only Gate members with MLS keys can decrypt. Added mesh reputation
system, peer push workers, voluntary Wormhole opt-in for node participation, fork recovery,
killwormhole scripts, obfuscated terminology, and hardened the self-updater to protect encryption
keys and chain state during updates.

New features: Shodan search, train tracking, Sentinel Hub imagery, 8 new intelligence layers,
CCTV expansion to 11,000+ cameras across 6 countries, Mesh Terminal CLI, prediction markets,
desktop-shell scaffold, and comprehensive mesh test suite (215 frontend + backend tests passing).

Community contributors: @wa1id, @AlborzNazari, @adust09, @Xpirix, @imqdcr, @csysp, @suranyami,
@chr0n1x, @johan-martensson, @singularfailure, @smithbh, @OrfeoTerkuci, @deuza, @tm-const,
@Elhard1, @ttulttul
2026-03-26 05:58:04 -06:00
Shadowbroker 0c08c30cab Merge pull request #103 from smithbh/feature/makefile-local-lan-taskrunner
Adds makefile-based taskrunner with lan or local-only access options
2026-03-24 18:02:46 -06:00
Brandon Smith c918ca28dd Adds ability to run in lan or local-only access modes using make commands
Signed-off-by: Brandon Smith <smithbh@me.com>
2026-03-24 18:14:02 -05:00
Orfeo Terkuci 1034d95145 Update dockerfile to use UV
Change backend context from . to ./backend in docker-compose.
This is necessary for copying the pyproject.toml and uv.lock files from project root level
2026-03-22 15:39:23 +01:00
anoracleofra-code fc9eff865e v0.9.0: in-app auto-updater, ship toggle split, stable entity IDs, performance fixes
New features:
- In-app auto-updater with confirmation dialog, manual download fallback,
  restart polling, and protected file safety net
- Ship layers split into 4 independent toggles (Military/Carriers, Cargo/Tankers,
  Civilian, Cruise/Passenger) with per-category counts
- Stable entity IDs using MMSI/callsign instead of volatile array indices
- Dismissible threat alert bubbles (session-scoped, survives data refresh)

Performance:
- GDELT title fetching is now non-blocking (background enrichment)
- Removed duplicate startup fetch jobs
- Docker healthcheck start_period 15s → 90s

Bug fixes:
- Removed fake intelligence assessment generator (OSINT-only policy)
- Fixed carrier tracker GDELT 429/TypeError crash
- Fixed ETag collision (full payload hash)
- Added concurrent /api/refresh guard

Contributors: @imqdcr (ship split + stable IDs), @csysp (dismissible alerts, PR #48)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Former-commit-id: a2c4c67da54345393f70a9b33b52e7e4fd6c049f
2026-03-13 11:32:16 -06:00
David Parry 782225ff99 fix: resolve proxy gzip decoding and BACKEND_URL Docker override issues
Two bugs introduced by the Next.js proxy Route Handler:

1. ERR_CONTENT_DECODING_FAILED — Node.js fetch() automatically
   decompresses gzip/br responses from the backend, but the proxy was
   still forwarding Content-Encoding and Content-Length headers to the
   browser. The browser would then try to decompress already-decompressed
   data and fail. Fixed by stripping Content-Encoding and Content-Length
   from upstream response headers.

2. BACKEND_URL shell env leak into Docker Compose — docker-compose.yml
   used ${BACKEND_URL:-http://backend:8000}, which was being overridden
   by BACKEND_URL=http://localhost:8000 set in .mise.local.toml for local
   dev. Inside the frontend container, localhost:8000 does not exist,
   causing all proxied requests to return 502. Fixed by hardcoding
   http://backend:8000 in docker-compose.yml so the shell environment
   cannot override it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Former-commit-id: 036c62d2c0
2026-03-11 15:00:50 +11:00
David Parry 25262323f5 feat: proxy backend API through Next.js using runtime BACKEND_URL
Previously, NEXT_PUBLIC_API_URL was a build-time Next.js variable, making
it impossible to configure the backend URL in docker-compose `environment`
without rebuilding the image.

This change introduces a proper server-side proxy:
- next.config.ts: adds a rewrite rule that forwards all /api/* requests
  to BACKEND_URL (read at server startup, not baked at build time).
  Defaults to http://localhost:8000 so local dev works without config.
- api.ts: API_BASE is now an empty string — all fetch calls use relative
  /api/... paths, which the Next.js server proxies to the backend.
- docker-compose.yml: replaces NEXT_PUBLIC_API_URL build arg with a
  runtime BACKEND_URL env var defaulting to http://backend:8000, using
  Docker's internal networking. Port 8000 no longer needs to be exposed.
- README: updates Docker setup docs, standalone compose example, and
  environment variable reference to reflect BACKEND_URL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Former-commit-id: a3b18e23c1
2026-03-11 14:18:30 +11:00
anoracleofra-code 2ae104fca2 v0.6.0: custom news feeds, data center map layer, performance hardening
New features:
- Custom RSS Feed Manager: add/remove/prioritize up to 20 news sources
  from the Settings panel with weight levels 1-5. Persists across restarts.
- Global Data Center Map Layer: 2,000+ DCs plotted worldwide with clustering,
  server-rack icons, and automatic internet outage cross-referencing.
- Imperative map rendering: high-volume layers bypass React reconciliation
  via direct setData() calls with debounced updates on dense layers.
- Enhanced /api/health with per-source freshness timestamps and counts.

Fixes:
- Data center coordinates fixed for 187 Southern Hemisphere entries
- Docker CORS_ORIGINS passthrough in docker-compose.yml
- Start scripts warn on Python 3.13+ compatibility
- Settings panel redesigned with tabbed UI (API Keys / News Feeds)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Former-commit-id: 950c308f04
2026-03-10 15:27:20 -06:00
anoracleofra-code 19a0ef1c70 fix: resolve Next.js docker build endpoints and handle async map icons
Former-commit-id: 6241ea44db
2026-03-09 00:41:02 -06:00
anoracleofra-code ed5bc5a23b fix: improve API key security, add connection banner, and bump to v0.3.0
Former-commit-id: 0c7dc37d83
2026-03-08 19:52:07 -06:00
anoracleofra-code 362a6e2ceb Initial commit: ShadowBroker v0.1
Former-commit-id: 8ed321f2ba
2026-03-04 22:44:08 -07:00