Replaces #3487 — earlier version had Markdown rendering issues that obscured the bug evidence.
Describe the bug
When a trusted folder path contains a backslash followed by . (e.g., C:\Users\me\.copilot) or a backslash followed by L (e.g., C:\Users\me\AppData\Local\<anything>), Copilot CLI silently corrupts the entry the next time it rewrites ~/.copilot/config.json. Result: the agent re-prompts for permission to access these folders even though /list-dirs reports them as trusted.
Observed corruption (real example from my config.json):
"trustedFolders": [
"C:\\Projects",
"C:\\Repositories",
"C:\\Users\\mecopilot", <- was "C:\\Users\\me\\.copilot"
"C:\\Users\\me\\AppDataocal\\genie_talend_converter", <- was "C:\\Users\\me\\AppData\\Local\\genie_talend_converter"
"C:\\Users\\me"
]
Notice the boundaries that collapsed: me + copilot (lost \.) and AppData + ocal (lost \L).
Root cause hypothesis: the writer that updates trustedFolders is double-decoding or applying JSON-escape logic to an already-decoded string, so:
\\ decodes to \, then on re-encode \. is treated as an invalid escape, the \ is silently dropped, and the boundary between adjacent path segments collapses.
- Same fault for
\L (which follows the same code path through whatever escape table — possibly adjacent to the legitimate \b, \f, \n, \r, \t, \u cases).
Pattern: any trusted folder whose next path segment starts with ., L, or potentially b, f, n, r, t, u is at risk. Folders not affected: C:\Projects, C:\Repositories, C:\Users\me (no problematic next char following a backslash).
Impact: users who have a permission "always" approved watch it silently lapse and re-prompt indefinitely. Mitigation requires hand-editing config.json. The same corruption recurs after the next /add-dir.
Workaround: trust a parent path with no problematic next segment (e.g., trust C:\Users\me instead of C:\Users\me\.copilot). Confirms the trust check itself is functional; the bug is purely in path serialization.
Affected version
GitHub Copilot CLI 1.0.52-4
Steps to reproduce the behavior
- Run
/add-dir C:\Users\<you>\.copilot to add a trusted folder whose next path segment starts with ..
- Run
/add-dir C:\Users\<you>\AppData\Local\<anything> to add one whose next segment starts with L.
- Trigger any code path that rewrites
~/.copilot/config.json — e.g., approve another permission with "Always", or run another /add-dir for an unrelated folder.
- Open
~/.copilot/config.json and inspect trustedFolders. The two entries from steps 1–2 will appear with the \ before . / L missing — <you>\.copilot becomes <you>copilot, and AppData\Local\X becomes AppDataocal\X.
- The agent will re-prompt for access to those folders even though
/list-dirs still claims them trusted.
Expected behavior
Round-tripping config.json should leave path entries in trustedFolders byte-identical. Specifically: a path written with \\. or \\L in JSON form (representing literal \. or \L) should still be \\. or \\L after the next write of the file.
Additional context
- I noticed because the agent kept re-prompting for read access to
C:\Users\me\.copilot\session-state\<session>\plan.md and C:\Users\me\AppData\Local\genie_talend_converter\state\ despite my having approved those folders with "Always" multiple times.
- Confirmed it is the path serialization at fault (not the trust-check): hand-editing
config.json to restore the missing backslashes makes the prompts stop. The corruption only re-appears after a subsequent write.
- Strongly suggests the writer is path-stringifying, then JSON-encoding once, when the source string is already a valid Python/JS string with literal backslashes — i.e.,
\\ -> \, then \. is treated as an escape attempt and \ is dropped on serialize.
Replaces #3487 — earlier version had Markdown rendering issues that obscured the bug evidence.
Describe the bug
When a trusted folder path contains a backslash followed by
.(e.g.,C:\Users\me\.copilot) or a backslash followed byL(e.g.,C:\Users\me\AppData\Local\<anything>), Copilot CLI silently corrupts the entry the next time it rewrites~/.copilot/config.json. Result: the agent re-prompts for permission to access these folders even though/list-dirsreports them as trusted.Observed corruption (real example from my
config.json):Notice the boundaries that collapsed:
me+copilot(lost\.) andAppData+ocal(lost\L).Root cause hypothesis: the writer that updates
trustedFoldersis double-decoding or applying JSON-escape logic to an already-decoded string, so:\\decodes to\, then on re-encode\.is treated as an invalid escape, the\is silently dropped, and the boundary between adjacent path segments collapses.\L(which follows the same code path through whatever escape table — possibly adjacent to the legitimate\b,\f,\n,\r,\t,\ucases).Pattern: any trusted folder whose next path segment starts with
.,L, or potentiallyb,f,n,r,t,uis at risk. Folders not affected:C:\Projects,C:\Repositories,C:\Users\me(no problematic next char following a backslash).Impact: users who have a permission "always" approved watch it silently lapse and re-prompt indefinitely. Mitigation requires hand-editing
config.json. The same corruption recurs after the next/add-dir.Workaround: trust a parent path with no problematic next segment (e.g., trust
C:\Users\meinstead ofC:\Users\me\.copilot). Confirms the trust check itself is functional; the bug is purely in path serialization.Affected version
GitHub Copilot CLI 1.0.52-4
Steps to reproduce the behavior
/add-dir C:\Users\<you>\.copilotto add a trusted folder whose next path segment starts with../add-dir C:\Users\<you>\AppData\Local\<anything>to add one whose next segment starts withL.~/.copilot/config.json— e.g., approve another permission with "Always", or run another/add-dirfor an unrelated folder.~/.copilot/config.jsonand inspecttrustedFolders. The two entries from steps 1–2 will appear with the\before./Lmissing —<you>\.copilotbecomes<you>copilot, andAppData\Local\XbecomesAppDataocal\X./list-dirsstill claims them trusted.Expected behavior
Round-tripping
config.jsonshould leave path entries intrustedFoldersbyte-identical. Specifically: a path written with\\.or\\Lin JSON form (representing literal\.or\L) should still be\\.or\\Lafter the next write of the file.Additional context
C:\Users\me\.copilot\session-state\<session>\plan.mdandC:\Users\me\AppData\Local\genie_talend_converter\state\despite my having approved those folders with "Always" multiple times.config.jsonto restore the missing backslashes makes the prompts stop. The corruption only re-appears after a subsequent write.\\->\, then\.is treated as an escape attempt and\is dropped on serialize.