From a633ee0af45804f888beb2f33cc00d74ffbb4ef7 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Thu, 14 May 2026 17:57:06 -0400 Subject: [PATCH] fix(ui): skip TOML comments when scanning sensitive array values PR-Agent on #1248 flagged that the TOML array walker did not skip `#` line comments while balancing brackets. A sensitive array with a comment containing `]` could terminate the scan early and leave the real tail of the secret unmasked. Skip from `#` to the next newline at the array's top level. Adds a regression test. --- ui/src/components/shared/code-editor.tsx | 12 +++++++++--- .../unit/components/ui/code-editor.test.tsx | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ui/src/components/shared/code-editor.tsx b/ui/src/components/shared/code-editor.tsx index d0370f11..d660c308 100644 --- a/ui/src/components/shared/code-editor.tsx +++ b/ui/src/components/shared/code-editor.tsx @@ -146,9 +146,10 @@ function findValueEnd( return closeIdx >= 0 ? valueStart + 3 + closeIdx + 3 : docLen; } if (lookahead[0] === '[') { - // Track bracket depth, skipping content inside strings. Use the - // backslash-aware skipper so `\"` inside basic strings does not - // prematurely close the string scan. + // Track bracket depth, skipping content inside strings and comments. + // Use the backslash-aware skipper so `\"` inside basic strings does not + // prematurely close the string scan, and skip `# ... \n` so a `]` that + // appears inside a TOML comment cannot terminate the array early. const text = doc.toString(); let depth = 0; let i = valueStart; @@ -158,6 +159,11 @@ function findValueEnd( i = skipString(text, i, ch); continue; } + if (ch === '#') { + const nl = text.indexOf('\n', i); + i = nl >= 0 ? nl + 1 : docLen; + continue; + } if (ch === '[') depth++; else if (ch === ']') { depth--; diff --git a/ui/tests/unit/components/ui/code-editor.test.tsx b/ui/tests/unit/components/ui/code-editor.test.tsx index 4ac14eb1..938039d1 100644 --- a/ui/tests/unit/components/ui/code-editor.test.tsx +++ b/ui/tests/unit/components/ui/code-editor.test.tsx @@ -131,6 +131,24 @@ describe('CodeEditor', () => { expect(masked).not.toContain('ok'); }); + it('does not terminate TOML array masking on a `]` inside a comment', () => { + const value = [ + 'AUTH_TOKEN = [', + ' "first", # closing bracket in comment: ]', + ' "second",', + ']', + 'visible = "ok"', + ].join('\n'); + + const { container } = render(); + const masked = Array.from(container.querySelectorAll('.cm-sensitive-mask')) + .map((el) => el.textContent ?? '') + .join(''); + expect(masked).toContain('"first"'); + expect(masked).toContain('"second"'); + expect(masked).not.toContain('ok'); + }); + it('respects escaped quotes inside TOML array values when masking', () => { const value = ['AUTH_TOKEN = ["a \\"quoted\\" value", "x"]', 'visible = "ok"'].join('\n');