Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions defaults/webserver/_bpp-locations.conf
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,24 @@ location = /netdata {
# SECURITY BLOCKS
# ============================================================================

# WYJATEK PRZED blokada plikow ukrytych: /.well-known/ (RFC 8615).
# To standardowa przestrzen metadanych serwisu, a nie "plik ukryty" — leza tam
# m.in. metadane serwera autoryzacji OAuth (RFC 8414,
# /.well-known/oauth-authorization-server), po ktore siega kazdy klient MCP
# przed logowaniem, a takze security.txt.
#
# UWAGA na kolejnosc matchowania location w nginksie: regex `~` ma
# pierwszenstwo przed zwyklym prefiksem, wiec blok `location ~ /\.` ponizej
# przechwytywal ZADANIA do /.well-known/ i zwracal 403 (discovery OAuth padalo,
# `bpp-mcp login` nie mial skad wziac authorization_endpoint). Modyfikator `^~`
# stawia ten prefiks PONAD regexami i przywraca poprawne zachowanie.
# Django odpowiada 404 na nieznane sciezki .well-known, wiec nic sie nie
# odslania; .git/.env dalej lapie regex ponizej.
location ^~ /.well-known/ {
limit_req zone=bpp_general burst=100 nodelay;
try_files $uri @proxy_to_app;
}

# Block access to hidden files and directories
# Prevents access to .git, .env, and other hidden files
location ~ /\. {
Expand Down
43 changes: 43 additions & 0 deletions tests/test_makefile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,49 @@ PYEOF
fail "GET /admin/: oczekiwane 301, otrzymano '$code'"
fi

_runtime_stop_nginx

# ==== 15d: /.well-known/ przechodzi na HTTPS, ukryte pliki dalej blokowane ====
# Regresja, ktora juz raz wystapila na produkcji: `location ~ /\.` (blokada
# plikow ukrytych) to REGEX, a regexy w nginksie maja pierwszenstwo przed
# zwyklymi prefiksami — wiec przechwytywal /.well-known/ i zwracal 403.
# Skutek: metadane serwera autoryzacji OAuth (RFC 8414) byly nieosiagalne i
# discovery klienta MCP padalo przed logowaniem. Lekarstwo to modyfikator
# `^~`, ktory stawia prefiks PONAD regexami.
#
# Ten test pilnuje OBU stron kontraktu naraz — samo "przepusc .well-known"
# dalo by sie spelnic kasujac blokade plikow ukrytych, co byloby regresja
# bezpieczenstwa. Dlatego .git/.env musza dalej dostawac 403.
yellow " -- 15d: /.well-known/ (OAuth discovery) vs blokada plikow ukrytych --"
start_out=$(_runtime_start_nginx "" "legacy.example.org") || {
fail "well-known-test nginx nie wstal w 15s"
return
}
read -r nginx_cid port_80 port_443 <<< "$start_out"

# Metadane AS MUSZA dojsc do Django (nie 403). Appserver echo-uje Path,
# wiec sprawdzamy takze, ze sciezka dolecila w calosci — samo 200 moglo by
# pochodzic z przypadkowego statycznego pliku.
body=$(curl -sk --resolve "legacy.example.org:$port_443:127.0.0.1" \
"https://legacy.example.org:$port_443/.well-known/oauth-authorization-server" || true)
if echo "$body" | grep -q "Path: /.well-known/oauth-authorization-server"; then
pass "HTTPS /.well-known/oauth-authorization-server -> proxy do appservera"
else
fail "well-known OAuth: oczekiwano proxy, otrzymano: $(echo "$body" | head -c 200)"
fi

# Blokada plikow ukrytych MUSI przetrwac wyjatek na .well-known.
for hidden in "/.git/config" "/.env"; do
code=$(curl -sk -o /dev/null -w '%{http_code}' \
--resolve "legacy.example.org:$port_443:127.0.0.1" \
"https://legacy.example.org:$port_443$hidden" || true)
if [ "$code" = "403" ]; then
pass "HTTPS $hidden -> 403 (blokada plikow ukrytych dziala)"
else
fail "$hidden: oczekiwane 403, otrzymano '$code' (blokada oslabiona!)"
fi
done

# cleanup via trap RETURN
}

Expand Down