{"record":{"id":"e0757ce13ec402e1","repo":"direnv/direnv","slug":"unmarshal-base64-decoding-w","errorCode":null,"errorMessage":"unmarshal() base64 decoding: %w","messagePattern":"unmarshal\\(\\) base64 decoding: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gzenv/gzenv.go","lineNumber":43,"sourceCode":"\tw := zlib.NewWriter(zlibData)\n\t// we assume the zlib writer would never fail\n\t_, _ = w.Write(jsonData)\n\tif err := w.Close(); err != nil {\n\t\tlog.Printf(\"Warning: failed to close zlib writer: %v\", err)\n\t}\n\n\tbase64Data := base64.URLEncoding.EncodeToString(zlibData.Bytes())\n\n\treturn base64Data\n}\n\n// Unmarshal restores the gzenv format back into a Go object\nfunc Unmarshal(gzenv string, obj interface{}) error {\n\tgzenv = strings.TrimSpace(gzenv)\n\n\tdata, err := base64.URLEncoding.DecodeString(gzenv)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unmarshal() base64 decoding: %w\", err)\n\t}\n\n\tzlibReader := bytes.NewReader(data)\n\tw, err := zlib.NewReader(zlibReader)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unmarshal() zlib opening: %w\", err)\n\t}\n\n\tenvData := bytes.NewBuffer([]byte{})\n\t// G110: Potential DoS vulnerability via decompression bomb (gosec)\n\t// #nosec\n\t_, err = io.Copy(envData, w)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unmarshal() zlib decoding: %w\", err)\n\t}\n\tif err := w.Close(); err != nil {\n\t\tlog.Printf(\"Warning: failed to close zlib reader: %v\", err)\n\t}","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/direnv/direnv/blob/b00e451f547f39be7ab836d969054114a465a0f9/gzenv/gzenv.go#L25-L61","documentation":"Unmarshal first base64url-decodes the gzenv string before zlib decompression; this error wraps any base64 decoding failure, meaning the input is not valid gzenv data (corrupt, truncated, or the wrong format entirely).","triggerScenarios":"Unmarshal (and callers cmdShowDumpAction, LoadEnv, LoadEnvDiff) receives a string that is not valid base64url: empty garbage, plain text, a gzenv value mangled by shell quoting, or a value with invalid characters/padding.","commonSituations":"Restoring a DIRENV_DUMP file that was hand-edited or truncated; passing a gzenv blob through a transport that altered +// characters or newlines; pointing direnv at a dump produced by another tool or format version.","solutions":["Regenerate the gzenv data (`direnv dump` / re-enter the directory to refresh DIRENV_DUMP) instead of repairing it","Verify the string is intact, unquoted and has no injected whitespace/newlines before decoding","Check the data source: ensure you are reading a gzenv blob, not plain JSON or another format"],"exampleFix":"// before\ndump := os.Getenv(\"DIRENV_DUMP\")\nerr := gzenv.Unmarshal(dump, &env) // corrupt value\n// after\nif dump == \"\" {\n    return fmt.Errorf(\"no dump to load\")\n}\nerr := gzenv.Unmarshal(dump, &env)\nif err != nil {\n    return fmt.Errorf\"invalid dump, regenerating: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"if gzenv == \"\" { return errors.New(\"empty gzenv input\") }\nif _, err := base64.URLEncoding.DecodeString(strings.TrimSpace(gzenv)); err != nil {\n    return fmt.Errorf(\"not valid gzenv: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"env, err := gzenv.Unmarshal(raw, &out)\nif err != nil {\n    if strings.Contains(err.Error(), \"base64 decoding\") {\n        // corrupt/non-gzenv input: regenerate dump and retry\n        regenerateDump()\n    }\n    return err\n}","preventionTips":["Never hand-edit or reformat gzenv blobs","Transport gzenv data through base64-safe channels (no quoting/newline mangling)","Confirm the source file is actually a direnv dump, not another format"],"tags":["gzenv","serialization","base64","corrupt-data"],"backgroundTag":"gzenv-decode-failed","analyzedSha":"b00e451f547f39be7ab836d969054114a465a0f9","analyzedAt":"2026-09-05T21:39:49.983Z","contentChangedAt":"2026-09-05T21:39:49.983Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}