v0.329.0 (review): an app named like another app's appdata folder gets no root; USERDATA_PATH is always derived, never the app's env
gates / gates (push) Successful in 46s
gates / gates (push) Successful in 46s
Security review of 2fe6341 (same night, before any release). Both red-proofed.
This commit is contained in:
@@ -90,10 +90,15 @@ func mustLoad(b []byte) (map[string]Entry, map[string]string) {
|
||||
}
|
||||
m[key(e.App, e.Service, e.Setting)] = e
|
||||
}
|
||||
owner := map[string]string{}
|
||||
for app, f := range l.AppdataFolders {
|
||||
if !oneSegment(f) {
|
||||
panic("privpolicy: allowlist.json appdata folder of " + app + " is not one folder name: " + f)
|
||||
}
|
||||
if o, dup := owner[f]; dup {
|
||||
panic("privpolicy: allowlist.json gives the appdata folder " + f + " to both " + o + " and " + app)
|
||||
}
|
||||
owner[f] = app
|
||||
}
|
||||
return m, l.AppdataFolders
|
||||
}
|
||||
@@ -112,6 +117,13 @@ func AppdataFolder(app string) string {
|
||||
if !oneSegment(app) {
|
||||
return ""
|
||||
}
|
||||
// A folder the map gives to ANOTHER app is not this app's, even when this app is named like it: a catalog push
|
||||
// adding a template called "paperless" must not get paperless-ngx's files (security review 2026-10-18).
|
||||
for _, f := range appdataFolders {
|
||||
if f == app {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return app
|
||||
}
|
||||
|
||||
|
||||
@@ -527,6 +527,21 @@ func TestAllowList_AppdataFolderMustBeOneName(t *testing.T) {
|
||||
mustLoad([]byte(`{"version":2,"entries":[],"appdata_folders":{"app":"` + bad + `"}}`))
|
||||
}()
|
||||
}
|
||||
// Security review 2026-10-18: an app NAMED like a folder the map gives to another app gets no root at all.
|
||||
if got := AppdataFolder("paperless"); got != "" {
|
||||
t.Errorf("AppdataFolder(paperless) = %q — a template named like paperless-ngx's folder must not own it", got)
|
||||
}
|
||||
if err := admit(t, "paperless", "services:\n app:\n image: x/y:1\n volumes:\n - ${HDD_PATH}/appdata/paperless/media:/m\n", env()); err == nil {
|
||||
t.Error("a template named paperless was admitted to paperless-ngx's folder")
|
||||
}
|
||||
func() {
|
||||
defer func() {
|
||||
if recover() == nil {
|
||||
t.Error("one folder given to two apps was loaded")
|
||||
}
|
||||
}()
|
||||
mustLoad([]byte(`{"version":2,"entries":[],"appdata_folders":{"a":"x","b":"x"}}`))
|
||||
}()
|
||||
if got := AppdataFolder("paperless-ngx"); got != "paperless" {
|
||||
t.Errorf("AppdataFolder(paperless-ngx) = %q", got)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user