fix: improve settings distributor robustness and security - #12
Conversation
- Fix TOML string escaping to handle newlines, tabs, carriage returns - Fix TOML inline table parsing to handle commas in quoted strings - Fix TOML scalar insertion to only target top-level keys, avoid section overwrites - Add warning for Cursor project-level permission limitations per security advisory - Add warning for unsupported Codex permission keys to clarify what's actually mapped - Deduplicate SETTINGS_TARGETS constant and resolveTargets logic across modules - Add process.env fallback for env resolution (after file lookup) - Add .env.agents to default lookup order for dedicated agent secrets - Improve test coverage for new fallback behavior Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
| return inner | ||
| .replace(/\\n/g, '\n') | ||
| .replace(/\\r/g, '\r') | ||
| .replace(/\\t/g, '\t') | ||
| .replace(/\\"/g, '"') | ||
| .replace(/\\\\/g, '\\'); |
There was a problem hiding this comment.
馃煛 Sequential regex replacements in unquote corrupt values containing escaped backslashes
The unquote function in src/core/env-resolver.ts:10-15 processes escape sequences using sequential regex replacements in an order that cannot correctly handle escaped backslashes preceding other escape characters like \n, \r, or \t.
Root Cause and Impact
For a .env file containing KEY="hello\\nworld" (intended to represent the literal string hello\nworld), the inner content after stripping quotes is the character sequence h,e,l,l,o,\,\,n,w,o,r,l,d.
Step 1 (replace(/\\n/g, '\n')) matches the second backslash + n first, converting it to a newline character. The first backslash is left as-is, producing hello\<newline>world instead of the intended hello\nworld.
Processing \\ last at step 5 cannot fix this because the \n has already been consumed. Reordering the replacements does not help either鈥攑rocessing \\ first would turn \\n into \n, which step 2 would then convert to a newline.
The fix requires a single-pass replacement, e.g.:
inner.replace(/\\([\\nrt"])/g, (_, ch) => {
const map: Record<string, string> = { '\\': '\\', n: '\n', r: '\r', t: '\t', '"': '"' };
return map[ch] ?? ch;
});Impact: Any double-quoted .env value containing a literal escaped backslash before n, r, t, or " (e.g. Windows paths like C:\\new_folder) will be silently corrupted.
| return inner | |
| .replace(/\\n/g, '\n') | |
| .replace(/\\r/g, '\r') | |
| .replace(/\\t/g, '\t') | |
| .replace(/\\"/g, '"') | |
| .replace(/\\\\/g, '\\'); | |
| return inner | |
| .replace(/\\([\\nrt"])/g, (_, ch) => { | |
| const map: Record<string, string> = { '\\': '\\', n: '\n', r: '\r', t: '\t', '"': '"' }; | |
| return map[ch] ?? ch; | |
| }); |
Was this helpful? React with 馃憤 or 馃憥 to provide feedback.
Summary
Fixed multiple bugs in the settings distributor module, added process.env fallback for env resolution, and introduced .env.agents for dedicated agent secrets.
Key fixes:
Test plan
馃 Generated with Claude Code