{"record":{"id":"6b6e2ec38367ff38","repo":"cloudflare/cloudflared","slug":"convert-path-to-utf-16-w","errorCode":null,"errorMessage":"convert path to UTF-16: %w","messagePattern":"convert path to UTF-16: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/windows_service.go","lineNumber":149,"sourceCode":"\t// - (A;;FA;;;SY) -> ACE #2: Ditto but for the Local System user (SY)\n\t//\n\t// Relevant Docs:\n\t//\n\t// - SecurityDescriptor string as a whole:\n\t//     https://learn.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format\n\t// - SID Strings such as BA/SY\n\t//     https://learn.microsoft.com/en-us/windows/win32/secauthz/sid-strings\n\t// - ACE Strings such as (A;;FA;;BA)\n\t//     https://learn.microsoft.com/en-us/windows/win32/secauthz/ace-strings\n\tconst sdString = \"O:BAD:P(A;;FA;;;BA)(A;;FA;;;SY)\"\n\tsd, err := windows.SecurityDescriptorFromString(sdString)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create token security descriptor: %w\", err)\n\t}\n\n\tpathRaw, err := windows.UTF16PtrFromString(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"convert path to UTF-16: %w\", err)\n\t}\n\n\tf, err := windows.CreateFile(\n\t\tpathRaw,\n\t\twindows.GENERIC_WRITE,\n\t\t0,\n\t\t&windows.SecurityAttributes{\n\t\t\tLength:             uint32(unsafe.Sizeof(windows.SecurityAttributes{})),\n\t\t\tSecurityDescriptor: sd,\n\t\t\tInheritHandle:      0,\n\t\t},\n\t\twindows.CREATE_ALWAYS, // Will truncate the file if it exists\n\t\twindows.FILE_ATTRIBUTE_NORMAL,\n\t\t0,\n\t)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create token file: %w\", err)","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/windows_service.go#L131-L167","documentation":"After building the security descriptor, createTokenFile converts the token file path to a Windows UTF-16 pointer via windows.UTF16PtrFromString for the Win32 CreateFile call. This conversion fails when the path contains an interior NUL byte (0x00), because Windows paths are NUL-terminated C strings. cloudflared wraps that failure with this message.","triggerScenarios":"The `path` argument passed to createTokenFile contains an embedded NUL character, so UTF16PtrFromString cannot produce a valid *uint16 path.","commonSituations":"A config/env value feeding the path was read from a buffer that was not trimmed at the NUL terminator; programmatic misuse of cloudflared internals with a Go string built from a C buffer.","solutions":["Remove NUL bytes from the path before use: strings.TrimSuffix(p, \"\\x00\") or strings.ReplaceAll(p, \"\\x00\", \"\")","Check where the path originates (config file, env var) and fix the producer so it trims at the first NUL","Call strings.Trim(configDir, \"\\x00 \") after reading environment variables populated by C interop"],"exampleFix":"// before\npathRaw, err := windows.UTF16PtrFromString(path)\nif err != nil {\n\treturn fmt.Errorf(\"convert path to UTF-16: %w\", err)\n}\n// after\npath = strings.TrimRight(path, \"\\x00\")\nif strings.ContainsRune(path, 0) {\n\treturn fmt.Errorf(\"path contains interior NUL byte: %q\", path)\n}\npathRaw, err := windows.UTF16PtrFromString(path)\nif err != nil {\n\treturn fmt.Errorf(\"convert path to UTF-16: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// Go: reject NUL bytes before any Win32 path call\nfunc validWinPath(p string) bool { return p != \"\" && !strings.ContainsRune(p, 0) && len(p) <= 32767 }","typeGuard":"func hasInteriorNul(s string) bool { return strings.IndexByte(s, 0) >= 0 }","tryCatchPattern":"if err := installWindowsService(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"convert path to UTF-16\") {\n\t\tlog.Error().Msg(\"path contains NUL bytes; sanitize inputs feeding the path\")\n\t}\n\treturn err\n}","preventionTips":["Trim NUL terminators from strings obtained via C/FFI boundaries","Validate environment variables and config values used as paths","Never build Windows paths from raw binary buffers without sanitizing"],"tags":["windows","path-handling","utf-16"],"backgroundTag":"invalid-argument-format","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}