Skip to content

config.json trustedFolders corruption: \\. and \\L path segments get squashed on round-trip #3488

@johncormier-lovelytics

Description

@johncormier-lovelytics

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

  1. Run /add-dir C:\Users\<you>\.copilot to add a trusted folder whose next path segment starts with ..
  2. Run /add-dir C:\Users\<you>\AppData\Local\<anything> to add one whose next segment starts with L.
  3. 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.
  4. 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.
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions