mirror of
https://github.com/gtsteffaniak/filebrowser.git
synced 2026-11-13 20:51:59 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfb7d7a58e | ||
|
|
e9e8d0df30 | ||
|
|
b9982964a2 |
No files matched your search
@@ -9,12 +9,17 @@ All notable changes to this project will be documented in this file. For commit
|
||||
- Square image previews: avoid the full-resolution crop copy in imaging.Fill (#3340)
|
||||
|
||||
**Bug Fixes**:
|
||||
- fix(http): Unix socket hardening — default `http.socketFileMode` is `0660`; the socket is created under a restrictive umask and then `chmod`/`chown` apply your configured mode; on filesystem sockets, forwarded headers require `http.unixSocketTrustedUIDs` and/or `http.unixSocketTrustedGIDs`, with `http.unixSocketTrustAllLocalPeers: true` as an explicit opt-in for pre-#3309 trust-all behavior (startup warning) (#3309)
|
||||
- fix(users): save the prompt close button and new file templates when editing a user (#3342) (#3323)
|
||||
- fix(upload): serialize directory creation before uploading files (#3321)
|
||||
- fix(preview): open RAW, HEIC and rendered documents in the viewer when previews are disabled (#3313)
|
||||
- fix(users): keep requested profile values when creating a user
|
||||
- fix advanced user toggle duplicate (#3353) (#3324)
|
||||
|
||||
**Upgrade notes** (Unix socket listeners):
|
||||
- If you listen on a filesystem `http.socket` with `http.trustProxyHeaders: true`, set `http.unixSocketTrustedUIDs` and/or `http.unixSocketTrustedGIDs` to the UID/GID(s) from Linux peer credentials (`SO_PEERCRED`) that may set `X-Forwarded-*`. A GID allowlist trusts every peer with that GID (for example when the proxy and FileBrowser share a group), not only one process. If you relied on empty allowlists before, set `http.unixSocketTrustAllLocalPeers: true` (a warning is logged).
|
||||
- Default `http.socketFileMode` is `0660`; use optional `http.socketGroup` when the proxy runs as another user in the same group.
|
||||
|
||||
## v2.1.4
|
||||
|
||||
**Security**:
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
func setupAccessHTTPTest(t *testing.T) {
|
||||
t.Helper()
|
||||
lockWebGlobals(t)
|
||||
dbPath := filepath.Join(t.TempDir(), "access-http-test.sqlite")
|
||||
if _, err := state.Initialize(dbPath); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
func setupExtractAccessPolicyTest(t *testing.T) (destDir, sourceRoot, sourceName, username string) {
|
||||
t.Helper()
|
||||
lockWebGlobals(t)
|
||||
tempDir := t.TempDir()
|
||||
dbPath := filepath.Join(tempDir, "access.sqlite")
|
||||
if _, err := state.Initialize(dbPath); err != nil {
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
func setupShareArchiveDownloadTest(t *testing.T) (sourceRoot string, sourceName string, owner *users.User) {
|
||||
t.Helper()
|
||||
lockWebGlobals(t)
|
||||
dbPath := filepath.Join(t.TempDir(), "share-dl-test.sqlite")
|
||||
if _, err := state.Initialize(dbPath); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
)
|
||||
|
||||
func setupTestEnv(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
utils.BcryptCost = bcrypt.MinCost
|
||||
dbPath := filepath.Join(t.TempDir(), "test.sqlite")
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func TestGetRemoteIPUsesRightmostForwardedFor(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
@@ -27,6 +28,7 @@ func TestGetRemoteIPUsesRightmostForwardedFor(t *testing.T) {
|
||||
// proxy hops so multi-hop deployments (CDN -> proxy -> filebrowser) resolve the
|
||||
// real client IP instead of collapsing everyone onto the shared edge address.
|
||||
func TestGetRemoteIPTrustedProxies(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
@@ -59,6 +61,7 @@ func TestGetRemoteIPTrustedProxies(t *testing.T) {
|
||||
|
||||
// Bare IPs (not just CIDRs) are accepted in http.trustedProxies.
|
||||
func TestGetRemoteIPTrustedProxiesBareIP(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
@@ -74,6 +77,7 @@ func TestGetRemoteIPTrustedProxiesBareIP(t *testing.T) {
|
||||
|
||||
// Without trustProxyHeaders the XFF chain is ignored entirely.
|
||||
func TestGetRemoteIPIgnoresForwardedForWhenUntrusted(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = false
|
||||
@@ -90,6 +94,7 @@ func TestGetRemoteIPIgnoresForwardedForWhenUntrusted(t *testing.T) {
|
||||
// A direct client that is not a trusted proxy cannot spoof its address with
|
||||
// forwarded headers, even when trustProxyHeaders is enabled.
|
||||
func TestGetRemoteIPIgnoresForwardedHeadersFromUntrustedPeer(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
@@ -104,8 +109,26 @@ func TestGetRemoteIPIgnoresForwardedHeadersFromUntrustedPeer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRemoteIPUnixSocketHonorsForwardedWithTrustAllLocalPeers(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
settings.Config.Http.Socket = "/var/run/filebrowser.sock"
|
||||
settings.Config.Http.UnixSocketTrustAllLocalPeers = true
|
||||
settings.Config.Http.TrustedProxies = nil
|
||||
|
||||
req := httptest.NewRequest("GET", "http://example.com/", nil)
|
||||
req.RemoteAddr = "@"
|
||||
req.Header.Set("X-Forwarded-For", "203.0.113.50")
|
||||
if got := GetRemoteIP(req); got != "203.0.113.50" {
|
||||
t.Fatalf("GetRemoteIP = %q, want 203.0.113.50", got)
|
||||
}
|
||||
}
|
||||
|
||||
// With no trusted proxies configured, forwarded headers are never honored.
|
||||
func TestGetRemoteIPIgnoresForwardedHeadersWithoutTrustedProxies(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
@@ -121,6 +144,7 @@ func TestGetRemoteIPIgnoresForwardedHeadersWithoutTrustedProxies(t *testing.T) {
|
||||
|
||||
// An IPv4-mapped IPv6 trusted hop in the XFF chain must still be skipped.
|
||||
func TestGetRemoteIPMappedTrustedHop(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
@@ -135,6 +159,7 @@ func TestGetRemoteIPMappedTrustedHop(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetScheme(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
t.Run("trusted proto", func(t *testing.T) {
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
t.Cleanup(func() { settings.Config.Http.TrustProxyHeaders = false })
|
||||
@@ -158,6 +183,7 @@ func TestGetScheme(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRequestSchemeTLSFallback(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
settings.Config.Http.TrustProxyHeaders = false
|
||||
|
||||
req := httptest.NewRequest("GET", "https://example.com/", nil)
|
||||
@@ -168,6 +194,7 @@ func TestRequestSchemeTLSFallback(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRequestSchemeIgnoresInvalidProto(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
t.Cleanup(func() { settings.Config.Http.TrustProxyHeaders = false })
|
||||
|
||||
@@ -179,6 +206,7 @@ func TestRequestSchemeIgnoresInvalidProto(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRequestHostTrustProxyHeaders(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
settings.Config.Http.TrustProxyHeaders = true
|
||||
t.Cleanup(func() { settings.Config.Http.TrustProxyHeaders = false })
|
||||
|
||||
@@ -192,6 +220,7 @@ func TestRequestHostTrustProxyHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRequestSchemeForPublicURL(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http.TrustProxyHeaders
|
||||
t.Cleanup(func() { settings.Config.Http.TrustProxyHeaders = orig })
|
||||
|
||||
@@ -225,6 +254,7 @@ func TestRequestSchemeForPublicURL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRequestPageFullURL(t *testing.T) {
|
||||
lockWebGlobals(t)
|
||||
orig := settings.Config.Http
|
||||
t.Cleanup(func() { settings.Config.Http = orig })
|
||||
settings.Config.Http.ExternalUrl = ""
|
||||
|
||||
@@ -237,6 +237,7 @@ func TestResourcePutHandler_SuccessResponseOmitsRealPath(t *testing.T) {
|
||||
|
||||
func setupPutHTTPTest(t *testing.T) string {
|
||||
t.Helper()
|
||||
lockWebGlobals(t)
|
||||
downloadsPath := filepath.Join(t.TempDir(), "downloads")
|
||||
|
||||
dbPath := filepath.Join(t.TempDir(), "quota-http-test.sqlite")
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
func setupQuotaHTTPTest(t *testing.T) {
|
||||
t.Helper()
|
||||
lockWebGlobals(t)
|
||||
dbPath := filepath.Join(t.TempDir(), "quota-http-test.sqlite")
|
||||
if _, err := state.Initialize(dbPath); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
func setupPutQuotaTest(t *testing.T) string {
|
||||
t.Helper()
|
||||
lockWebGlobals(t)
|
||||
downloadsPath := filepath.Join(t.TempDir(), "downloads")
|
||||
|
||||
dbPath := filepath.Join(t.TempDir(), "quota-http-test.sqlite")
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// webGlobalTestMu serializes tests that mutate process-wide settings.Config or state.
|
||||
var webGlobalTestMu sync.Mutex
|
||||
|
||||
func lockWebGlobals(t testing.TB) {
|
||||
t.Helper()
|
||||
webGlobalTestMu.Lock()
|
||||
t.Cleanup(webGlobalTestMu.Unlock)
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
|
||||
// setupWebDAVTestEnv sets up the test environment with multiple sources and users
|
||||
func setupWebDAVTestEnv(t *testing.T) (string, string) {
|
||||
lockWebGlobals(t)
|
||||
// Create temp directories for test sources
|
||||
tempDir := t.TempDir()
|
||||
source1Path := filepath.Join(tempDir, "source1")
|
||||
|
||||
@@ -124,7 +124,11 @@ func warnHttpProxyConfig() {
|
||||
}
|
||||
if Config.Http.TrustProxyHeaders && Config.Http.Socket != "" && !strings.HasPrefix(Config.Http.Socket, "@") &&
|
||||
len(Config.Http.UnixSocketTrustedUIDs) == 0 && len(Config.Http.UnixSocketTrustedGIDs) == 0 {
|
||||
logger.Warning("http.trustProxyHeaders is true and http.socket is a filesystem Unix socket, but http.unixSocketTrustedUIDs and http.unixSocketTrustedGIDs are empty; X-Forwarded-For and X-Real-IP are ignored until you list the reverse proxy's UID or GID (Linux peer credentials).")
|
||||
if Config.Http.UnixSocketTrustAllLocalPeers {
|
||||
logger.Warning("http.unixSocketTrustAllLocalPeers is true: any local process that can connect to the filesystem socket may present X-Forwarded-For and X-Real-IP. Prefer http.unixSocketTrustedUIDs and/or http.unixSocketTrustedGIDs so only peers with allowed Linux credentials can set forwarded headers.")
|
||||
} else {
|
||||
logger.Warning("http.trustProxyHeaders is true on a filesystem Unix socket, but http.unixSocketTrustedUIDs and http.unixSocketTrustedGIDs are empty; forwarded client headers from socket peers are ignored. List allowed peer UIDs and/or GIDs (Linux SO_PEERCRED), or set http.unixSocketTrustAllLocalPeers: true only if you accept legacy trust-all behavior.")
|
||||
}
|
||||
}
|
||||
if !Env.IsDevMode {
|
||||
if u := Config.Http.ExternalUrl; u != "" && strings.HasPrefix(strings.ToLower(u), "http://") {
|
||||
|
||||
@@ -37,11 +37,14 @@ type Http struct {
|
||||
TrustProxyHeaders bool `json:"trustProxyHeaders"` // honor X-Forwarded-* and X-Real-IP from a reverse proxy (default: false)
|
||||
TrustedProxies []string `json:"trustedProxies"` // IPs/CIDRs of trusted proxies; forwarded client headers are only honored when the socket peer matches one of these (default: empty = forwarded headers ignored)
|
||||
// UnixSocketTrustedUIDs and UnixSocketTrustedGIDs list peer credentials (Linux SO_PEERCRED) allowed to
|
||||
// present X-Forwarded-* on a filesystem http.socket listener. When both are empty, forwarded headers
|
||||
// are not trusted on Unix sockets. Abstract sockets (@name) never trust forwarded headers.
|
||||
UnixSocketTrustedUIDs []int `json:"unixSocketTrustedUIDs"`
|
||||
UnixSocketTrustedGIDs []int `json:"unixSocketTrustedGIDs"`
|
||||
SocketFileMode string `json:"socketFileMode"` // octal mode for filesystem http.socket (default "0660"); ignored for abstract sockets
|
||||
// present X-Forwarded-* on a filesystem http.socket listener. When both are empty, peers are not trusted
|
||||
// unless UnixSocketTrustAllLocalPeers is true (legacy; startup logs a warning). A GID allowlist trusts
|
||||
// every peer with that GID, not only a single reverse-proxy process. Abstract sockets (@name) never trust
|
||||
// forwarded headers.
|
||||
UnixSocketTrustedUIDs []int `json:"unixSocketTrustedUIDs"`
|
||||
UnixSocketTrustedGIDs []int `json:"unixSocketTrustedGIDs"`
|
||||
UnixSocketTrustAllLocalPeers bool `json:"unixSocketTrustAllLocalPeers"` // default false: set true to trust forwarded headers from any local filesystem socket peer when allowlists are empty
|
||||
SocketFileMode string `json:"socketFileMode"` // octal mode for filesystem http.socket (default "0660"); ignored for abstract sockets
|
||||
SocketGroup string `json:"socketGroup"` // optional group name or numeric gid for the socket file (filesystem sockets only)
|
||||
DisableRateLimit bool `json:"disableRateLimit"` // turns off built-in auth route rate limiting and failed-login lockout (default false).
|
||||
}
|
||||
|
||||
@@ -113,10 +113,11 @@ func ipMatchesPrefixes(ip string, prefixes []netip.Prefix) bool {
|
||||
// proxy headers. Forwarded client headers must only be honored when this returns
|
||||
// true; otherwise any client that can reach the listener directly could spoof its address.
|
||||
//
|
||||
// When http.socket is set the server listens only on that Unix socket. Filesystem
|
||||
// socket peers are trusted only when their UID or GID matches
|
||||
// http.unixSocketTrustedUIDs / http.unixSocketTrustedGIDs (Linux peer credentials).
|
||||
// Abstract sockets ("@name") have no filesystem permissions and their peers are never trusted.
|
||||
// When http.socket is set the server listens only on that Unix socket. Abstract
|
||||
// sockets ("@name") have no filesystem permissions and their peers are never trusted.
|
||||
// On filesystem sockets, when either allowlist is set, only peers whose Linux SO_PEERCRED
|
||||
// UID or GID matches may present forwarded headers. When both allowlists are empty,
|
||||
// peers are trusted only if http.unixSocketTrustAllLocalPeers is true (legacy opt-in).
|
||||
func IsTrustedProxyPeer(r *http.Request) bool {
|
||||
if r == nil {
|
||||
return false
|
||||
@@ -125,6 +126,9 @@ func IsTrustedProxyPeer(r *http.Request) bool {
|
||||
if strings.HasPrefix(socket, "@") {
|
||||
return false
|
||||
}
|
||||
if len(Config.Http.UnixSocketTrustedUIDs) == 0 && len(Config.Http.UnixSocketTrustedGIDs) == 0 {
|
||||
return Config.Http.UnixSocketTrustAllLocalPeers
|
||||
}
|
||||
cred, ok := UnixPeerFromContext(r.Context())
|
||||
if !ok {
|
||||
return false
|
||||
|
||||
@@ -132,7 +132,6 @@ func TestIsTrustedProxyPeer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// With http.socket set, forwarded headers require matching unixSocketTrustedUIDs/GIDs.
|
||||
func TestIsTrustedProxyPeerUnixSocket(t *testing.T) {
|
||||
resetTrustedProxyCache()
|
||||
Config.Http.TrustedProxies = nil
|
||||
@@ -141,15 +140,23 @@ func TestIsTrustedProxyPeerUnixSocket(t *testing.T) {
|
||||
Config.Http.Socket = ""
|
||||
Config.Http.UnixSocketTrustedUIDs = nil
|
||||
Config.Http.UnixSocketTrustedGIDs = nil
|
||||
Config.Http.UnixSocketTrustAllLocalPeers = false
|
||||
resetTrustedProxyCache()
|
||||
})
|
||||
for _, peer := range []string{"", "@"} {
|
||||
if IsTrustedProxyPeer(&http.Request{RemoteAddr: peer}) {
|
||||
t.Fatalf("unix socket peer %q must not be trusted without peer credentials", peer)
|
||||
}
|
||||
if IsTrustedProxyPeer(&http.Request{RemoteAddr: "@"}) {
|
||||
t.Fatal("filesystem unix socket with empty allowlists must not trust forwarded headers without opt-in")
|
||||
}
|
||||
Config.Http.UnixSocketTrustAllLocalPeers = true
|
||||
if !IsTrustedProxyPeer(&http.Request{RemoteAddr: "@"}) {
|
||||
t.Fatal("unixSocketTrustAllLocalPeers should restore legacy trust-all behavior")
|
||||
}
|
||||
Config.Http.UnixSocketTrustAllLocalPeers = false
|
||||
|
||||
Config.Http.UnixSocketTrustedUIDs = []int{33}
|
||||
reqNoCred := &http.Request{RemoteAddr: "@"}
|
||||
if IsTrustedProxyPeer(reqNoCred) {
|
||||
t.Fatal("with allowlists set, peer without credentials must not be trusted")
|
||||
}
|
||||
req := (&http.Request{}).WithContext(ContextWithUnixPeerForTest(context.Background(), 33, 1000))
|
||||
if !IsTrustedProxyPeer(req) {
|
||||
t.Fatal("peer with allowed UID should be trusted")
|
||||
|
||||
@@ -8,8 +8,11 @@ import (
|
||||
"os/user"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var unixListenUmaskMu sync.Mutex
|
||||
|
||||
type unixPeerCredKey struct{}
|
||||
|
||||
// UnixPeerCredential holds the peer process identity for a Unix domain connection.
|
||||
@@ -69,14 +72,15 @@ func ListenUnixFilesystem(socketPath string) (net.Listener, error) {
|
||||
}
|
||||
setGroup = true
|
||||
}
|
||||
unixListenUmaskMu.Lock()
|
||||
oldMask := unixUmask(0o077)
|
||||
defer unixUmask(oldMask)
|
||||
listener, err := net.Listen("unix", socketPath)
|
||||
unixUmask(oldMask)
|
||||
unixListenUmaskMu.Unlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
closeListener := func() { _ = listener.Close() }
|
||||
// Assign group ownership while the socket is still owner-only (umask 077), then grant mode bits.
|
||||
if setGroup {
|
||||
if err := os.Chown(socketPath, -1, gid); err != nil {
|
||||
closeListener()
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package settings
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseSocketFileModeDefaults(t *testing.T) {
|
||||
mode, err := parseSocketFileMode("")
|
||||
@@ -51,3 +56,29 @@ func TestUnixPeerAllowed(t *testing.T) {
|
||||
t.Fatal("empty allowlists must deny")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListenUnixFilesystemSetsModeWithRestrictiveUmask(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("filesystem unix sockets are not used on Windows")
|
||||
}
|
||||
dir := t.TempDir()
|
||||
socketPath := filepath.Join(dir, "fb.sock")
|
||||
orig := Config.Http
|
||||
Config.Http.SocketFileMode = ""
|
||||
t.Cleanup(func() {
|
||||
Config.Http = orig
|
||||
_ = os.Remove(socketPath)
|
||||
})
|
||||
ln, err := ListenUnixFilesystem(socketPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = ln.Close() })
|
||||
st, err := os.Stat(socketPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if st.Mode().Perm() != 0o660 {
|
||||
t.Fatalf("socket perm = %o, want 0660", st.Mode().Perm())
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
//go:build !unix && !windows
|
||||
|
||||
package settings
|
||||
|
||||
func unixUmask(_ int) int {
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//go:build !unix
|
||||
|
||||
package settings
|
||||
|
||||
func unixUmask(mask int) int {
|
||||
return 0
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package settings
|
||||
|
||||
func unixUmask(_ int) int {
|
||||
return 0
|
||||
}
|
||||
@@ -6040,6 +6040,10 @@ const docTemplate = `{
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"unixSocketTrustAllLocalPeers": {
|
||||
"description": "default false: set true to trust forwarded headers from any local filesystem socket peer when allowlists are empty",
|
||||
"type": "boolean"
|
||||
},
|
||||
"unixSocketTrustedGIDs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -6047,7 +6051,7 @@ const docTemplate = `{
|
||||
}
|
||||
},
|
||||
"unixSocketTrustedUIDs": {
|
||||
"description": "UnixSocketTrustedUIDs and UnixSocketTrustedGIDs list peer credentials (Linux SO_PEERCRED) allowed to\npresent X-Forwarded-* on a filesystem http.socket listener. When both are empty, forwarded headers\nare not trusted on Unix sockets. Abstract sockets (@name) never trust forwarded headers.",
|
||||
"description": "UnixSocketTrustedUIDs and UnixSocketTrustedGIDs list peer credentials (Linux SO_PEERCRED) allowed to\npresent X-Forwarded-* on a filesystem http.socket listener. When both are empty, peers are not trusted\nunless UnixSocketTrustAllLocalPeers is true (legacy; startup logs a warning). A GID allowlist trusts\nevery peer with that GID, not only a single reverse-proxy process. Abstract sockets (@name) never trust\nforwarded headers.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
|
||||
@@ -6029,6 +6029,10 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"unixSocketTrustAllLocalPeers": {
|
||||
"description": "default false: set true to trust forwarded headers from any local filesystem socket peer when allowlists are empty",
|
||||
"type": "boolean"
|
||||
},
|
||||
"unixSocketTrustedGIDs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -6036,7 +6040,7 @@
|
||||
}
|
||||
},
|
||||
"unixSocketTrustedUIDs": {
|
||||
"description": "UnixSocketTrustedUIDs and UnixSocketTrustedGIDs list peer credentials (Linux SO_PEERCRED) allowed to\npresent X-Forwarded-* on a filesystem http.socket listener. When both are empty, forwarded headers\nare not trusted on Unix sockets. Abstract sockets (@name) never trust forwarded headers.",
|
||||
"description": "UnixSocketTrustedUIDs and UnixSocketTrustedGIDs list peer credentials (Linux SO_PEERCRED) allowed to\npresent X-Forwarded-* on a filesystem http.socket listener. When both are empty, peers are not trusted\nunless UnixSocketTrustAllLocalPeers is true (legacy; startup logs a warning). A GID allowlist trusts\nevery peer with that GID, not only a single reverse-proxy process. Abstract sockets (@name) never trust\nforwarded headers.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
|
||||
@@ -500,6 +500,10 @@ definitions:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
unixSocketTrustAllLocalPeers:
|
||||
description: 'default false: set true to trust forwarded headers from any
|
||||
local filesystem socket peer when allowlists are empty'
|
||||
type: boolean
|
||||
unixSocketTrustedGIDs:
|
||||
items:
|
||||
type: integer
|
||||
@@ -507,8 +511,10 @@ definitions:
|
||||
unixSocketTrustedUIDs:
|
||||
description: |-
|
||||
UnixSocketTrustedUIDs and UnixSocketTrustedGIDs list peer credentials (Linux SO_PEERCRED) allowed to
|
||||
present X-Forwarded-* on a filesystem http.socket listener. When both are empty, forwarded headers
|
||||
are not trusted on Unix sockets. Abstract sockets (@name) never trust forwarded headers.
|
||||
present X-Forwarded-* on a filesystem http.socket listener. When both are empty, peers are not trusted
|
||||
unless UnixSocketTrustAllLocalPeers is true (legacy; startup logs a warning). A GID allowlist trusts
|
||||
every peer with that GID, not only a single reverse-proxy process. Abstract sockets (@name) never trust
|
||||
forwarded headers.
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
|
||||
@@ -318,9 +318,12 @@ http:
|
||||
trustProxyHeaders: false # honor X-Forwarded-* and X-Real-IP from a reverse proxy (default: false)
|
||||
trustedProxies: # IPs/CIDRs of trusted proxies; forwarded client headers are only honored when the socket peer matches one of these (default: empty = forwarded headers ignored)
|
||||
unixSocketTrustedUIDs: # UnixSocketTrustedUIDs and UnixSocketTrustedGIDs list peer credentials (Linux SO_PEERCRED) allowed to
|
||||
# present X-Forwarded-* on a filesystem http.socket listener. When both are empty, forwarded headers
|
||||
# are not trusted on Unix sockets. Abstract sockets (@name) never trust forwarded headers.
|
||||
# present X-Forwarded-* on a filesystem http.socket listener. When both are empty, peers are not trusted
|
||||
# unless UnixSocketTrustAllLocalPeers is true (legacy; startup logs a warning). A GID allowlist trusts
|
||||
# every peer with that GID, not only a single reverse-proxy process. Abstract sockets (@name) never trust
|
||||
# forwarded headers.
|
||||
unixSocketTrustedGIDs:
|
||||
unixSocketTrustAllLocalPeers: false # default false: set true to trust forwarded headers from any local filesystem socket peer when allowlists are empty
|
||||
socketFileMode: "" # octal mode for filesystem http.socket (default "0660"); ignored for abstract sockets
|
||||
socketGroup: "" # optional group name or numeric gid for the socket file (filesystem sockets only)
|
||||
disableRateLimit: false # turns off built-in auth route rate limiting and failed-login lockout (default false).
|
||||
Reference in new issue
Block a user