Přeskočit na obsah

Tato stránka byla automaticky přeložena z angličtiny, jediného jazyka, ve kterém se tento web píše. Číst originál.

Volající mimo loopback čte a nemění nic, co nedokáže ověřit

Volající mimo loopback čte a nemění nic, co nedokáže ověřit

majordomus://adr/adr-0126navrženo bezpečnostmeshmcphttp

odkazuje na

  • put_in_force apps/majordomus-cli/src/capability/model.rs (soubor)
  • put_in_force apps/majordomus-cli/src/http/router.rs (soubor)
  • put_in_force apps/majordomus-cli/src/mcp/surface.rs (soubor)
  • put_in_force adr-0003
  • put_in_force adr-0040
  • put_in_force adr-0067
  • put_in_force project.mesh-cooperation-is-authenticated@1
  • put_in_force test/cases/1086_a_remote_caller_cannot_write.sh (test)
  • put_in_force apps/majordomus-cli/tests/remote_callers.rs (test)

odkazuje na něj

126. Volající mimo loopback čte a nemění nic, co nedokáže autentizovat

Kontext

HTTP server nemá účty ani tokeny. Jeho jediná ochrana požadavku měnícího stav byla kontrola Origin (http/router.rs), která odmítá stránku prohlížeče z jiného originu a nic víc: program Origin neposílá a prošel. Dokud každý server naslouchal na loopbacku, bylo to neškodné. Přestalo to být neškodné, když mesh potřeboval servery dosažitelné z jiných strojů (docs/MESH.md, „Mesh tohoto repozitáře“) a když MAJORDOMUS_HTTP_HOST umožnil vývojáři navázat se na všechna rozhraní.

Dne 2026-10-09 naslouchaly na stroji vlastníka tři servery na všech rozhraních: hub mesh na 8791 a dva servery primárního checkoutu. Čtení kódu (audit základního stavu balíčku runtime, M01) zjistilo, že jakýkoli hostitel na LAN nebo tailnetu mohl:

  • převést sledovaný záznam plánu (plan.transition), publikovat nebo obnovit kontinuitu a uklidit osiřelé: schopnosti, jejichž efekt je repository_mutation;
  • spustit jakoukoli schopnost, včetně zapisovačů, přes executions.start;
  • zveřejnit relaci meshe, nárok, uvolnění, publikaci nebo převzetí předávky, nebo review, což tento uzel pak podepsal svým vlastním důvěryhodným klíčem a replikoval na každý runtime repozitáře. Peer nedokáže takovou událost odlišit od té, kterou napsal její vlastník: uzel se stal podpisovou věštírnou a záruka z project.mesh-cooperation-is-authenticated platila jen pro síťový hop, ne pro autora.

Varování při bindu říkalo, že vzdálený hostitel může „číst“. Dokumentace uváděla, že neexistuje autentizace a že zapisovatelé jsou vystaveni; nikdo podle té věty nejednal, protože bezpečnostní model v dokumentaci mesh o tom nemluvil.

Rozhodnutí

Požadavek se posuzuje podle adresy, odkud přišel, protože to je jediný fakt, který server má. Požadavek z adresy, která není loopback — v obou rodinách, včetně IPv4-mapped tvaru, který hlásí dual-stack socket — spustí schopnost jen tehdy, když:

  1. schopnost čte (effect: read), nebo
  2. vstupem schopnosti je podepsaná zpráva, kterou její handler ověří proti politice důvěry, než se cokoli změní. To se deklaruje na schopnosti jako třetí zdokumentovaný dodatek k její politice provádění (ExecutionPolicy::authenticates_its_input, serializováno jako signed_input) a smí ho deklarovat jen příkaz, jehož efekt je process_state: podpis dokazuje, kdo zprávu poslal, ne že její odesílatel smí zde měnit sledované soubory. Dnes ho deklarují přesně tři schopnosti: mesh.link.hello, mesh.link.sync a mesh.register.

Vše ostatní je odmítnuto dřív, než se spustí jeho handler, s jednou novou kategorií chyby, forbidden (HTTP 403), která na každém transportu nese jednu větu (CapabilityError::remote). Otázka se klade na jednom místě, ExecutionPolicy::admits_remote, a ptá se každý transport, který zná adresu volajícího:

  • HTTP router pro každou routu schopnosti;
  • koncový bod MCP přes HTTP, po zprávě a ne po relaci: id relace je jméno, ne důkaz, a další zpráva relace otevřené z loopbacku může přijít odjinud.

Požadavek sestavený uvnitř procesu (Cockpit skládající čtení, test) nenese žádnou adresu a je tohoto stroje. Most stdio dosahuje sdílený server přes loopback a je tohoto stroje. executions.start je příkaz, takže vzdálený volající jej nemůže použít k dosažení zapisovatele. Lokální by mohl, pod nástrojem oznámeným jako měnícím jen paměť tohoto procesu; executions.start proto deklaruje nejsilnější efekt toho, co může spustit, repository_mutation, a klient, který se před spuštěním zapisovatele ptá, se ptá i před ním.

Důsledky

  • Mesh dál funguje: ostatní runtime se k tomuto uzlu dostanou jen třemi podepsanými trasami, které se nemění.
  • Vzdálený klient MCP (telefon, jiný stroj) stále čte každý nástroj a zdroj, ale už se nemůže přihlásit na nástěnce peerů ani otevřít relaci meshe přes tento uzel. Zápis z jiného stroje jde přes SSH tunel, který končí na loopbacku, tedy cestou, kterou už doporučoval docs/MCP.md.
  • Čtení jsou stále servírována celé síti, nešifrovaně. Toto rozhodnutí neudělá z navázání mimo loopback soukromé; udělá z něj navázání, které nic nemůže změnit.
  • Schopnost přidaná později je vzdáleným volajícím ve výchozím stavu odepřena, pokud nečte. Nikdo si nemusí pamatovat, že ji má přidat do seznamu, a tests/remote_callers.rs prochází registr.
  • Schéma OpenAPI ExecutionPolicy získává pole signed_input; je-li nepravdivé, vynechává se, takže serializace každé další schopnosti je beze změny.

Zde nerozhodnuto a zaznamenáno jako další kroky balíku místo tvrzení: autorizace pomocí tokenu nebo klíče, která by ověřenému vzdálenému klientovi umožnila zapisovat; podepisování autora události meshe odděleně od uzlu, který ji předává; šifrování transportu.

Zamítnuté alternativy

  • Odmítnout každý požadavek jiný než GET ze vzdálené adresy. Jednodušší a dvakrát špatně: podepsané routy meshe jsou POST a stejně tak každá zpráva MCP, včetně čtení.
  • Navázat huby mesh na loopback. Odstraní spolupráci mezi stroji, což je účel hubů, a každé jiné navázání mimo loopback ponechá odkryté.
  • Seznam chráněných tras. Seznam zastará den po napsání; efekt už nese každá schopnost a nový zapisovatel musí být odmítnut, aniž by si to kdo pamatoval.
  • Rozhodnout jednou za relaci MCP, při initialize. Id relace lze uhodnout (nese pid a čítač) a není vázáno na adresu; vzdálený host by mohl převzít relaci otevřenou z loopbacku.

Odkud to pochází

kanonický soubor
.ai/repo/adrs/0126-a-caller-beyond-loopback-reads-and-changes-nothing-it-cannot-authenticate.md
identity
adr-0126
dostupné také jako
Zdroj MCP majordomus://adr/adr-0126 · majordomus entity show adr/adr-0126 · GET /api/v1/entity?uri=majordomus://adr/adr-0126
v Cockpitu
/cockpit/objects/adr/adr-0126

Tato stránka je generována z výše uvedeného souboru pomocí scripts/generate-site-data; úprava stránky nic nemění, úprava souboru změní všechna rozhraní. Výše uvedené vztahy jsou hrany docs/generated/graph.json, které spustitelný program zapisuje ze stejného indexu.

Prohledává názvy a popisy všech stránek, které tento web publikuje.