{"record":{"id":"056bfc1ce0df916f","repo":"golang/go","slug":"gzip-write-non-latin-1-header-string","errorCode":null,"errorMessage":"gzip.Write: non-Latin-1 header string","messagePattern":"gzip\\.Write: non-Latin-1 header string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/compress/gzip/gzip.go","lineNumber":121,"sourceCode":"\t\treturn errors.New(\"gzip.Write: Extra data is too large\")\n\t}\n\tle.PutUint16(z.buf[:2], uint16(len(b)))\n\t_, err := z.w.Write(z.buf[:2])\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = z.w.Write(b)\n\treturn err\n}\n\n// writeString writes a UTF-8 string s in GZIP's format to z.w.\n// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).\nfunc (z *Writer) writeString(s string) (err error) {\n\t// GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.\n\tneedconv := false\n\tfor _, v := range s {\n\t\tif v == 0 || v > 0xff {\n\t\t\treturn errors.New(\"gzip.Write: non-Latin-1 header string\")\n\t\t}\n\t\tif v > 0x7f {\n\t\t\tneedconv = true\n\t\t}\n\t}\n\tif needconv {\n\t\tb := make([]byte, 0, len(s))\n\t\tfor _, v := range s {\n\t\t\tb = append(b, byte(v))\n\t\t}\n\t\t_, err = z.w.Write(b)\n\t} else {\n\t\t_, err = io.WriteString(z.w, s)\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\t// GZIP strings are NUL-terminated.","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/compress/gzip/gzip.go#L103-L139","documentation":"gzip.Writer.writeString rejects any string containing a NUL byte (0x00) or a rune above 0xff because GZIP header strings (FNAME, FCOMMENT) are NUL-terminated ISO 8859-1 Latin-1 per RFC 1952. A NUL would terminate the string early and a non-Latin-1 rune cannot be represented.","triggerScenarios":"Setting gz.Header.Name or gz.Header.Comment to a value containing a NUL byte or any rune above U+00FF (e.g., emoji, CJK characters, accented Cyrillic, right-to-left scripts), then calling Write/Flush/Close.","commonSituations":"Storing user-supplied UTF-8 filenames (Android downloads with CJK names, macOS NFD-decomposed accents) in the GZIP FNAME field; copying a Comment from a JSON or YAML manifest that contains em-dashes, smart quotes, or emoji.","solutions":["Sanitize Header.Name and Header.Comment: drop or replace runes > 0xFF and any NUL.","Encode the original filename with percent-encoding or base32 so it stays inside the ASCII subset of Latin-1.","Store the full Unicode filename in a sidecar metadata file instead of the GZIP header.","If you must preserve Unicode, transcode the string to ISO 8859-1 only when every rune is <= 0xFF; otherwise reject upfront."],"exampleFix":"// before\ngz.Header.Name = path.Base(userSuppliedFilename) // may contain emoji\n\n// after: keep only Latin-1, substitute everything else\ngz.Header.Name = sanitizeLatin1(userSuppliedFilename)\n\nfunc sanitizeLatin1(s string) string {\n    var b strings.Builder\n    for _, r := range s {\n        if r == 0 || r > 0xff { r = '_' }\n        b.WriteRune(r)\n    }\n    return b.String()\n}","handlingStrategy":"validation","validationCode":"func latin1Safe(s string) (string, error) {\n    for _, r := range s {\n        if r == 0 || r > 0xff {\n            return \"\", fmt.Errorf(\"rune U+%04X not representable in Latin-1\", r)\n        }\n    }\n    return s, nil\n}\n\nfunc setGzipName(h *gzip.Header, name string) error {\n    safe, err := latin1Safe(name)\n    if err != nil { return err }\n    h.Name = safe\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := setGzipName(&gz.Header, userFilename); err != nil {\n    // Fall back to an ASCII slug or store filename out-of-band.\n    gz.Header.Name = asciiSlug(userFilename)\n}","preventionTips":["Sanitize user-supplied filenames before assigning to Header.Name.","Percent-encode or base32-encode Unicode filenames to stay in the ASCII subset.","Test with CJK, emoji, and NFD-decomposed samples in your test fixtures.","Audit every place that sets Header.Comment for the same restriction."],"tags":["gzip","compression","header-validation","encoding","latin-1","unicode"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}