Skip to content

Latest commit

 

History

History
358 lines (299 loc) · 32.2 KB

ROUTE_GUARD_TIERS.md

File metadata and controls

358 lines (299 loc) · 32.2 KB

Route Guard Tiers (Bosanski)

🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇸 es · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇰🇭 km · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇭 phi · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW


Pregled

Sve rute OmniRoute API-ja za upravljanje klasificirane su u jedan od tri nivoa zaštite. Klasifikacija je statična, definirana u src/server/authz/routeGuard.ts i procjenjuje se prije izvršavanja bilo koje druge grane autentifikacije.

Nivoi

Nivo 1 — LOCAL_ONLY

Nameće: isLocalOnlyPath(path) → provjera loopback hosta Zaobilazak: Nema po defaultu. Uski izuzetak za putanje u LOCAL_ONLY_MANAGE_SCOPE_BYPASS_PREFIXES kada zahtjev nosi važeći API ključ sa manage opsegom (vidi Izuzetak za manage-opseg).

Ove rute pokreću podređene procese ili izvršavaju kod u vrijeme izvođenja. Njihovo izlaganje saobraćaju koji nije loopback omogućilo bi napadaču koji je pribavio važeći JWT (npr. putem Cloudflared/Ngrok tunela) da pokrene stvaranje procesa — poznata klasa CVE ranjivosti (GHSA-fhh6-4qxv-rpqj).

Šta je GHSA-fhh6-4qxv-rpqj (klasa napada): upravljački/agent server izlaže krajnju tačku koja pokreće podproces (npm install, node, preglednik, proxy, git, tar, …). Ako je ta krajnja tačka dostupna izvan hosta — jer je operator stavio OmniRoute iza nginx/Cloudflare/Tailscale tunela i JWT je procurio, ili je autentifikacija pogrešno konfigurisana — napadač pretvara "poziv API-ja" u "izvršavanje komande na hostu" (daljinsko izvršavanje koda). OmniRoute ovo zatvara nametanjem provjere loopback hosta bezuslovno, prije svake provjere autentifikacije, na svakoj ruti sposobnoj za pokretanje procesa: procurili token preko tunela i dalje ne može doći do pokretanja procesa.

Kompletan LOCAL_ONLY skup. Autoritativni izvor je LOCAL_ONLY_API_PREFIXES / LOCAL_ONLY_API_PATTERNS u src/server/authz/routeGuard.ts; tabela ispod odražava trenutno stanje. check-route-guard-membership gate nabrojava svaki route.ts pod prefiksima sposobnim za pokretanje procesa i obustavlja CI ako bilo koji nije klasificiran kao local-only.

Prefiks / obrazac Zašto je samo lokalno
/api/mcp/ MCP server — pokreće stdio mostove + SSE handlere
/api/cli-tools/runtime/ Runtime CLI alata — izvršava proizvoljni kod plugina
/api/cli-tools/{omp,letta,grok-build,forge,jcode,qwen}-settings Upisivači postavki po alatu koji mogu dirati binarne datoteke/konfiguraciju alata na hostu
/api/cli-tools/{claude,cline,codewhale,codex,crush,deepseek-tui,droid,kilo,openclaw,pi,smelt}-settings Isto pokretanje getCliRuntimeStatus() kao kod šest gore navedenih srodnih alata (GHSA-35fw-cv32-2373)
/api/cli-tools/{all-statuses,status,detect} Sonde inventara CLI-ja — pokreću command -v / --version po alatu (GHSA-35fw-cv32-2373)
/api/cli-tools/antigravity-mitm Kontrola Antigravity MITM proxyja (pokreće/usmjerava sistemski proxy)
/api/modality-bridge/video/ Striktna pouzdana loopback-sonda Video Bridge runtime-a i interni most za ekstrakciju
/api/services/ Ugrađeni servisi (9Router / CLIProxy / Bifrost / Mux / Dario) — npm install + pokretanje
/dashboard/providers/services/ Reverzni proxy do korisničkih sučelja ugrađenih servisa
/api/tunnels/cloudflared Instalira/pokreće cloudflared binarnu datoteku
/api/tunnels/tailscale/{install,enable,disable,login,start-daemon} Instalira/upravlja tailscaled na hostu
/api/copilot/ Neautentificirani LLM drajver — zadano samo CLI
/api/tools/agent-bridge/ AgentBridge — pokreće MITM server + izmjene DNS-a
/api/tools/traffic-inspector/ Traffic Inspector — http-proxy listener + sistemski proxy
/api/settings/mitm Omogućava MITM presretanje (stanje proxyja na nivou sistema)
/api/issue-agent/ Issue agent — pokreće lokalne alate nad repozitorijem
/api/plugins/, /api/plugins Plugini — učitavanje/izvršavanje putem worker_threads + child_process
/api/middleware/ Korisnički middleware — učitava/izvršava kod operatora unutar procesa
/api/system/version Automatsko ažuriranje (samo POST; GET/HEAD/OPTIONS izuzeti) — pokreće git checkout + npm install
/api/db-backups/exportAll Pokreće tar za arhivu izvoza
/api/local/ Lokalni pokretači na 1 klik (trenutno Redis) — pokreću podman/docker
/api/headroom/start, /api/headroom/stop Životni ciklus Headroom proxyja — pokreće python CLI / šalje signal PID-u
/api/jobs, /api/jobs/ Kontrola izvršioca poslova — izvršava zakazani rad na strani hosta
/api/oauth/cursor/auto-import execFile("which", ["cursor"]) prije uvoza kredencijala
/api/oauth/kiro/auto-import Čita datoteke kredencijala Kiro CLI-ja s hosta
/api/skills/collect/ Kolekcija vještina — detektira/instalira lokalne alate
/api/skills/install, /api/skills/executions Registracija skill handlera + izvršavanje — doseže spawn sandbox kontejnera (GHSA-jx89)
/api/discovery/ Probe-ovi za otkrivanje lokalne mreže/provajdera
/api/vnc-session (VNC_ROUTE_PREFIX) Pokreće headful browser + VNC sesiju za interaktivne prijave
/api/acp/agents ACP — otkriva i pokreće lokalne binarne datoteke CLI agenata
/api/resilience/connections JSON otpornosti po računu (cooldown, breaker, lockout). HTML dashboarda nije samo-lokalni.
/api/providers/cursor/agent-availability Provjera instalacijskog podsjetnika za dashboard — pokreće cursor-agent status --format json
/api/providers/{id}/login (regex) Pokreće headful Playwright Chromium za prijavu putem web kolačića
/api/providers/volcengine-plan/connect (regex) Ručni headful tok + automatska prijava putem telefona/SMS-a bazirana na sesiji (pokreće Playwright)
/api/providers/{id}/refresh-cursor (regex) Ručna obnova Cursor sesije — potiče cursor-agent
/api/providers/{id}/chatgpt-web-codex-doctor (regex) Dijagnosticira lokalnu instalaciju Codex CLI-ja (pokreće binarnu datoteku)

Odgovor pri kršenju: 403 LOCAL_ONLY

Izuzetak za manage opseg

Podskupu LOCAL_ONLY putanja također se MOŽE pristupiti sa ne-loopback adresa ako i samo ako zahtjev nosi Authorization: Bearer <api-key> čiji metapodaci uključuju manage opseg (ili admin). Izuzetak je eksplicitno kontrolisan po putanji putem LOCAL_ONLY_MANAGE_SCOPE_BYPASS_PREFIXES tako da zadana postavka za svaku novu LOCAL_ONLY putanju ostaje striktno loopback. Neautentificirani zahtjevi i zahtjevi s ključevima bez manage opsega se i dalje odbijaju sa 403 LOCAL_ONLY.

Trenutno je jedini prefiks koji se može zaobići /api/mcp/. /api/cli-tools/runtime/ i /api/services/ su namjerno isključeni jer mogu pokretati proizvoljne podprocese (npm install, node), što je upravo ona klasa CVE-a koju LOCAL_ONLY nivo postoji da spriječi.

#7895 — mcp:connect uski opseg: izuzetak za /api/mcp/ TAKOĐER prihvata Bearer ključ koji drži uski mcp:connect opseg (src/shared/constants/managementScopes.ts::MCP_CONNECT_SCOPE), provjeren putem hasMcpConnectOrManageScope() u src/server/authz/policies/management.ts. Ovo je ograničeno SAMO na /api/mcp/ — mcp:connect ne daje ništa na bilo kojoj drugoj upravljačkoj ruti (uključujući svaki drugi LOCAL_ONLY bypass prefiks, ako bi ikada bio dodan), i namjerno je isključen iz MANAGEMENT_API_KEY_SCOPES. Ključ koji drži manage/admin i dalje prolazi izuzetak tačno kao prije; mcp:connect je alternativa niže privilegije za udaljene pozivatelje koji koriste samo MCP i kojima ne bi trebao biti potreban širok upravljački pristup.

Zahtjev Putanja Rezultat
Ne-loopback, bez Bearer-a /api/mcp/* 403 LOCAL_ONLY
Ne-loopback, Bearer sa manage opsegom /api/mcp/* Dozvoljeno
Ne-loopback, Bearer sa mcp:connect opsegom /api/mcp/* Dozvoljeno
Ne-loopback, Bearer bez manage/mcp:connect /api/mcp/* 403 LOCAL_ONLY
Ne-loopback, Bearer sa mcp:connect opsegom /api/cli-tools/runtime/* 403 LOCAL_ONLY
Ne-loopback, Bearer sa manage opsegom /api/cli-tools/runtime/* 403 LOCAL_ONLY
Loopback, bilo koji/bez Bearer-a bilo koja LOCAL_ONLY Dozvoljeno (kontrola prolazi)

Smjernice za operatore i revizija

Ako pokrećete OmniRoute iza reverznog proxyja ili tunela (nginx, Caddy, Cloudflare Tunnel, Tailscale, Ngrok), loopback provjera i dalje štiti gore navedene rute sposobne za spawn — zahtjev čija je klijentska adresa ne-loopback odbija se sa 403 LOCAL_ONLY prije nego što se autentifikacija izvrši, tako da procurio JWT ne može dosegnuti spawn. Ostaju dvije odgovornosti operatora:

  • Ne "popravljajte" 403 krivotvorenjem IP adrese klijenta kao loopback. Postavljanje X-Forwarded-For: 127.0.0.1, ili proxy koji prepisuje izvornu adresu na loopback, ponovno otvara upravo onu klasu RCE ranjivosti koju ovaj nivo zatvara. Izvozite dashboard/API kroz proxy — nikada rute sposobne za pokretanje procesa (spawn).
  • Održavajte zaobilazak za manage-scope minimalnim. Samo /api/mcp/ se može zaobići, i to samo s API ključem sa manage opsegom. SPAWN_CAPABLE_PREFIXES se nikada ne mogu dodati na listu za zaobilaženje — zod shema ih odbija, a isLocalOnlyBypassableByManageScope ih odbija tokom izvršavanja (defence-in-depth), što je upravo ono što dashboard misli pod "cannot be made bypassable". Ista deny-lista sadrži i nekoliko LOCAL_ONLY ruta koje ne pokreću procese, ali također nikada ne smiju biti daljinski dostupne — /api/oauth/kiro/auto-import (čita Kiro datoteke s vjerodajnicama lokalne za host), /api/discovery/ i /api/issue-agent/. Učitavač snimke tokom izvršavanja (runtime snapshot loader) također odbacuje takve unose iz pohranjenog reda postavki, a legacy JSON import (/api/settings/import-json) nikada ne upisuje ključeve za zaobilaženje. Svaki unos u LOCAL_ONLY_API_PREFIXES mora biti ili na deny-listi ili pregledan kao podoban za zaobilaženje (tests/unit/authz/local-only-bypass-spawn-denylist.test.ts). Rute sposobne za pokretanje procesa s dinamičkim segmentima i statičkim putanjama pod /api/providers/ (npr. /login, /refresh-cursor) pokrivene su pratećim mehanizmima zasnovanim na regularnim izrazima SPAWN_CAPABLE_PATTERNS / SPAWN_CAPABLE_PATTERN_ANCESTORS u src/shared/constants/spawnCapablePrefixes.ts, a ne ravnim nizom SPAWN_CAPABLE_PREFIXES — ravni niz bi morao pokrivati cijeli prefiks /api/providers/ da bi ih uhvatio, čime bi se previše proširilo stablo ruta koje udaljeni dashboardi legitimno koriste za CRUD operacije nad providerima.

Revizija pristupa — kako biste provjerili da ništa izvan hosta ne dolazi do ovih ruta:

  • Otvorite Authorization Inventory na /dashboard/settings/security: prikazuje aktuelnu listu LOCAL_ONLY prefiksa, koji su prefiksi zaobilaživi, te skup sposoban za pokretanje procesa ("cannot be made bypassable") definiran u vremenu kompajliranja.
  • Pretražite pomoću grep svoje logove reverznog proxyja / pristupa za gore navedene prefikse uparene s adresom klijenta koja nije loopback. Svaki takav pogodak koji je vratio 200 umjesto 403 LOCAL_ONLY znači da proxy maskira stvarnu IP adresu klijenta — popravite proxy.
  • 403 LOCAL_ONLY u OmniRoute logovima za jednu od ovih putanja znači da zaštita radi kako je predviđeno, a ne greška koju treba potisnuti.

Daljinski dostupne rute s probe-barijerom na mjestu poziva

Neke rute moraju ostati dostupne s udaljenog dashboarda, ali izvršavaju probe na hostu (which <binary>, <binary> --version, tailscale status --json) za lokalne pozivatelje. One nisu LOCAL_ONLY za GET; umjesto toga, handler čita pouzdani verdikt o udaljenosti peer-a pomoću getRequestPeerLocality() (src/shared/utils/apiAuth.ts) i izvršava probe samo za pozivatelje s loopback / lan. remote pozivatelj dobija isti oblik odgovora izgrađen iz izvora koji ne pokreću procese (trajno pohranjeno stanje, postavke, provjere fajlsistema), označen s probed: false.

Ruta Probe koji se preskače za udaljene pozivatelje
POST /api/providers/{id}/test, /api/providers/test-batch CLI runtime probe (allowLocalRuntimeProbe) i CLI-fallback spawn
GET /api/headroom/status which headroom i python --version probe-ovi
GET /api/tunnels/tailscale, GET /api/tunnels/tailscale/check which tailscale, tailscale status/funnel --json, which brew
GET /api/tunnels/cloudflared (GET izuzet od LOCAL_ONLY) which cloudflared PATH pretraga

Nova ruta za čitanje koja vrši probe hosta slijedi isti obrazac, ili se odmah klasificira kao LOCAL_ONLY.

Nivo 2 — ALWAYS_PROTECTED

Primjenjuje: isAlwaysProtectedPath(path) → preskače zaobilazak requireLogin=false Zaobilazak: Nema kada je requireLogin=false; JWT je uvijek obavezan

Ove rute su destruktivne ili nepovratne. Dozvoliti ih u instalaciji "bez lozinke" značilo bi da bilo ko na istoj LAN mreži može obrisati bazu podataka ili ugasiti proces servera.

Putanja Razlog
/api/shutdown Prekida proces servera
/api/settings/database Izvoz, uvoz i brisanje baze podataka
/api/db-backups Pristup arhivi potpunog backupa baze podataka
/api/settings/export-json Izvozi cijeli blob postavki (uklj. tajne)
/api/settings/import-json Zamjenjuje cijeli blob postavki
/api/providers/health-autopilot/actions Izvršava radnje sanacije autopilota
/api/settings/obsidian Izdaje višekratne WebDAV vjerodajnice za bilo koji korijen vaulta
/api/relay/tokens Izdaje, izlistava, mijenja i opoziva relay tokene
/api/cli-tools/apply Prepisuje CLI konfiguraciju hosta operatora
/api/cli-tools/guide-settings Piše CLI konfiguracijske datoteke vođene vodičem
/api/cli-tools/hermes-agent-settings Piše konfiguraciju Hermes agenta
/api/cli-tools/backups Vraća i briše backup-e CLI konfiguracije
/api/log-export Šalje logove poziva na konfiguriranu destinaciju
/api/restart Ponovno pokreće proces servera

Odgovor pri kršenju: 401 Authentication required

/api/settings/obsidian pokriva svoj podređeni /webdav: POST usmjerava WebDAV fajl-servis — kojeg poslužuje prilagođeni Node sloj prije Next.js-a, izvan ovog pipeline-a — na root koji bira pozivalac i vraća svježe generisane Basic kredencijale, DELETE ih rotira, a roditeljski POST pohranjuje Obsidian REST API token. GHSA-62vw je samo maskirao otkrivanje lozinke putem GET; izdavanje je i dalje bilo na fail-open nivou (GHSA-7pq4-8pvv-rx7r). enableObsidianVaultSync() dodatno odbija vault koji jeste, nalazi se unutar, ili sadrži direktorij podataka.

Izvoz i vraćanje kredencijala dostupno je samo operatorima

Nivo iznad samo odlučuje je li potreban nekakav kredencijal. Rute koje preuzimaju pohranjene kredencijale dodaju drugu provjeru u handleru: GET /api/settings/export-json (dekriptovane konekcije provajdera i sirovi API ključevi), GET /api/db-backups/export (SQLite fajl) i GET /api/db-backups/exportAll (puna arhiva) pozivaju requireOperatorCredential() (src/lib/api/operatorCredential.ts). On prihvata dashboard sesiju, lokalni CLI subjekt ili instancu s onemogućenim loginom, a odgovara sa 403 API ključevima bilo kojeg opsega (uključujući manage i admin) kao i oma_ pristupnim tokenima. Destruktivni pandani drže istu granicu: POST /api/db-backups/import (uploadana .sqlite, uključujući dryRun=true), POST /api/db-backups (vraćanje pohranjenog backupa po id-u) i POST /api/settings/import-json (legacy JSON vraćanje) zamjenjuju aktivnu bazu podataka ili čitav skup postavki/konekcija/API-ključeva, tako da mašinski kredencijal također ne može pokrenuti njih. Uništavanje tačaka vraćanja drži istu granicu: DELETE /api/db-backups (čišćenje — zadrži najnovijih N / odbaci starije od D dana) i PATCH /api/db-backups (postavke zadržavanja), jer je pohranjena retencija upravo ono što cleanupDbBackups() primjenjuje nakon svakog automatskog backupa (src/lib/db/backup.ts), pa bi mašinski kredencijal koji bi mogao spremiti keepLatest: 1 sve očistio na sljedećem snapshotu. Listanje i kreiranje backupa (GET/PUT /api/db-backups) zadržavaju običnu management autentikaciju. Izdavanje sync tokena (POST /api/sync/tokens) koristi isti helper, plus pouzdani loopback token internog servisa.

Bootstrap svježe instalacije je samo za loopback — prema stvarnom peeru, ne Host

Bez konfigurirane management lozinke (i bez INITIAL_PASSWORD), isAuthRequired() u src/shared/utils/apiAuth.ts drži anonimni bootstrap otvorenim samo za loopback peere. Loopback se određuje iz pouzdanih peer signala, ovim redoslijedom: stvarni TCP peer označen tokenom (PEER_IP_HEADER + VIA_PROXY_HEADER, ono što politika vidi), vlastiti verdikt pipeline-a AUTHZ_HEADER_PEER_LOCALITY (ono što handleri ruta vide, pouzdano samo dok je postavljen OMNIROUTE_PEER_STAMP_TOKEN), ili stvarni socket peer za direktne pozivaoce. Host / nextUrl.hostname se nikad ne uzimaju u obzir, a upis prve lozinke (POST /api/settings/require-login) podliježe istom ograničenju umjesto da bude otvoren svakom mrežnom peeru (GHSA-7pq4-8pvv-rx7r). managementPolicy eksplicitno prosljeđuje svoj vlastiti peerContext verdikt niže, tako da headeri ORIGINALNOG zahtjeva (prije uklanjanja) nikad ne odlučuju o tome.

Nivo 3 — MANAGEMENT (zadano)

Sve ostale management rute. Autentikacija je potrebna osim ako je konfigurirano requireLogin=false. CLI tokeni mogu autentificirati ove rute (loopback + validan HMAC).

Redoslijed evaluacije

managementPolicy.evaluate(ctx)
  1. isLocalOnlyPath(path)?
     → povratna petlja                                  → nastavi dalje
     → nije povratna petlja, Bearer s opsegom manage
        I isLocalOnlyBypassableByManageScope             → dozvoli (management_key)
     → u suprotnom                                       → odbij 403 LOCAL_ONLY
  2. isInternalModelSyncRequest(ctx)?
     → dozvoli (system)
  3. hasValidCliToken(headers)?
     → dozvoli (cli) [povratna petlja + HMAC provjera pomoću timingSafeEqual]
  4. isAlwaysProtectedPath(path) ili requireLogin=true?
     → isDashboardSessionAuthenticated?
        → dozvoli (dashboard_session)
     → Bearer s opsegom manage na putanji koju nije moguće zaobići?
        → dozvoli (management_key)
     → odbij 401/403
  5. requireLogin=false?
     → dozvoli (anonymous)

Grana s opsegom manage iz koraka 1 jedina je autentificirana putanja koja može zadovoljiti LOCAL_ONLY rutu; način otkaza autentifikacijskog pozadinskog sistema vraća 503 (ne 403), tako da istekla baza podataka ne dovede neprimjetno do prelaska na „odbij“.

Dodavanje nove rute koja može pokretati procese

  1. Dodajte prefiks putanje u LOCAL_ONLY_API_PREFIXES u src/server/authz/routeGuard.ts
  2. Dodajte test u tests/unit/authz/routeGuard.test.ts koji potvrđuje da isLocalOnlyPath() vraća true za novi prefiks
  3. Nikada ne preskačite ovaj korak — pogledajte strogo pravilo br. 15 u CLAUDE.md
  4. Odlučite: pripada li ova ruta TAKOĐER u LOCAL_ONLY_MANAGE_SCOPE_BYPASS_PREFIXES? Zadani odgovor je ne. Uključite je samo kada je rutu sigurno izložiti imaocu opsega manage (tj. NE pokreće proizvoljni kod kojim upravlja korisnik).

Dodavanje putanje koju je moguće zaobići pomoću opsega manage

  1. Potvrdite da ruta ne izvršava kod ili naredbe koje je dostavio korisnik. Ako ih izvršava, zaustavite se — ovaj izuzetak nije odgovarajući alat.
  2. Dodajte prefiks u LOCAL_ONLY_MANAGE_SCOPE_BYPASS_PREFIXES u src/server/authz/routeGuard.ts
  3. Dodajte pokrivenost u tests/unit/authz/management-policy.test.ts za sva četiri oblika zahtjeva: bez Bearer tokena (403), Bearer s opsegom manage (dozvoli), Bearer bez opsega manage (403) i regresijski test po prefiksu kojim se potvrđuje da /api/cli-tools/runtime/* ostaje strogo ograničen na povratnu petlju čak i uz Bearer s opsegom manage.

Datoteke

Datoteka Namjena
src/server/authz/routeGuard.ts Konstante i pomoćne funkcije
src/server/authz/policies/management.ts Logika evaluacije
tests/unit/authz/routeGuard.test.ts Jedinični testovi pomoćnika nivoa
tests/unit/authz/management-policy.test.ts Jedinični testovi za evaluate()

Dokumentovanje sigurnosnih nivoa u OpenAPI-ju

Prilikom dodavanja nove rute u docs/openapi.yaml, primijenite odgovarajuće proširenje dobavljača ako je ruta klasificirana u routeGuard.ts:

Klasifikacija u routeGuard.ts YAML anotacija Provođenje
LOCAL_ONLY_API_PREFIXES x-loopback-only: true Bezuslovno blokirano izvan povratne petlje
ALWAYS_PROTECTED_API_PATHS x-always-protected: true Autentifikacija je obavezna čak i uz requireLogin=false
Interna admin/debug ruta x-internal: true Zadano skriveno iz /dashboard/api-endpoints
Nijedna (javni / standardni pristup uz autentifikaciju) (anotacija nije potrebna) Standardni pristup kojim upravlja requireLogin

Validacija

Dvije skripte osiguravaju dosljednost između YAML anotacija i routeGuard.ts:

  • scripts/check/check-openapi-coverage.mjs — neuspješno se završava ako je pokrivenost < 99%
  • scripts/check/check-openapi-security-tiers.mjs — neuspješno se završava ako anotacije x-loopback-only ili x-always-protected odstupaju od konstanti definiranih u vrijeme prevođenja

Obje skripte pokreću se u pre-commit kuki i u CI-ju.

Pravilo za lažno pozitivne rezultate

Ako je x-always-protected ili x-loopback-only anotiran na ruti koja NIJE u konstanti u routeGuard.ts, skripta za pokrivenost završava se neuspješno. Rješenje je uvijek uskladiti YAML s onim što routeGuard.ts zaista provodi — a ne dodavati rute u routeGuard.ts bez istovremene implementacije logike provođenja.


Pogledajte također

  • docs/security/CLI_TOKEN.md — token ID-a uređaja za CLI
  • docs/architecture/AUTHZ_GUIDE.md — kompletan proces autorizacije
  • docs/frameworks/MCP-SERVER.md — transporti i opsezi MCP servera