fix(R-1187 b): the import writes only through os.Root — never through a link that leaves the app's folder
Found by the automated security review of dfd0f8e. Red-proved. Commit only.
This commit is contained in:
@@ -109,7 +109,7 @@ func TestR1187b_TheImportKeepsOwnersModesAndInsideLinks(t *testing.T) {
|
||||
|
||||
var chowned []string
|
||||
old := lchownFn
|
||||
lchownFn = func(p string, uid, gid int) error {
|
||||
lchownFn = func(_ *os.Root, p string, uid, gid int) error {
|
||||
chowned = append(chowned, filepath.Base(p)+":"+strconv.Itoa(uid)+":"+strconv.Itoa(gid))
|
||||
return nil
|
||||
}
|
||||
@@ -190,3 +190,29 @@ func TestR1187g_PostgisIsPostgresAndPsqlStopsOnError(t *testing.T) {
|
||||
t.Fatalf("psql does not stop on error: %s", args)
|
||||
}
|
||||
}
|
||||
|
||||
// (b), the security review's case: a link already in the destination folder (left by the old app, or made by an earlier
|
||||
// entry) that points OUTSIDE must never be written through — a tar entry „evil/passwd" would otherwise create a file
|
||||
// wherever „evil" points. Every write is confined to the app's folder (os.Root). RED-PROOF: with plain os.Create the
|
||||
// outside file is created.
|
||||
func TestR1187b_NoWriteThroughALinkThatLeavesTheFolder(t *testing.T) {
|
||||
outside := t.TempDir()
|
||||
dest := t.TempDir()
|
||||
os.Symlink(outside, filepath.Join(dest, "evil")) // pre-existing, pointing out
|
||||
tarPath := filepath.Join(t.TempDir(), "d.tar")
|
||||
f, _ := os.Create(tarPath)
|
||||
tw := tar.NewWriter(f)
|
||||
tw.WriteHeader(&tar.Header{Name: "evil/passwd", Typeflag: tar.TypeReg, Mode: 0o644, Size: 3})
|
||||
tw.Write([]byte("pwn"))
|
||||
tw.WriteHeader(&tar.Header{Name: "ok.txt", Typeflag: tar.TypeReg, Mode: 0o644, Size: 2})
|
||||
tw.Write([]byte("ok"))
|
||||
tw.Close()
|
||||
f.Close()
|
||||
old := lchownFn
|
||||
lchownFn = func(*os.Root, string, int, int) error { return nil }
|
||||
defer func() { lchownFn = old }()
|
||||
extractTar(tarPath, dest)
|
||||
if _, err := os.Stat(filepath.Join(outside, "passwd")); err == nil {
|
||||
t.Fatal("a file was written OUTSIDE the app's folder through a pre-existing link")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user