Skip to content

fix(lib): escape backslashes in HCL string literals - #593

Open
Ramnath0521 wants to merge 1 commit into
open-constructs:mainfrom
Ramnath0521:fix/issue-562
Open

Ramnath0521 wants to merge 1 commit into
open-constructs:mainfrom
Ramnath0521:fix/issue-562

Conversation

@Ramnath0521

Copy link
Copy Markdown

Closes: #562

Summary

HCL synth copied backslashes in string values through unchanged, so a Windows path rendered as "C:\Users\me\project\terraform.tfstate". Terraform and OpenTofu reject that at init (The \U escape sequence must be followed by eight hexadecimal digits). The default LocalBackend path is path.join(process.cwd(), ...), so every HCL synth on Windows with the default backend produced a cdk.tf that cannot initialise. A value ending in a backslash left the string unterminated.

Change

In packages/cdktn/src/hcl/render.ts, escapeQuotes now escapes both \ and ", so Terraform reads the value back as written (the same result as JSON.stringify). The old (?<!\\) lookbehind is gone: once backslashes are escaped, a backslash before a quote no longer means the quote is already escaped.

A string that contains ${...} used to skip escaping entirely, and locals and outputs also wrote such strings without any escaping. Both now go through the same function, which keeps each ${...} interpolation as written and escapes only the text around it. The scanner follows nested braces and quoted strings inside the interpolation, so ${lookup({a = "}"}, "a")} is not cut short, and leaves $${ alone.

Tests

Seven tests in test/json-to-hcl.test.ts: a Windows path, a trailing backslash, a quote after a backslash, backslashes around an interpolation, a quoted string inside an interpolation, a brace inside a quoted string inside an interpolation, and the default LocalBackend path on Windows. Six fail on main and pass with the change; the one with a quoted string inside an interpolation passes either way and pins that handling. All 47 tests in json-to-hcl.test.ts pass, snapshots included (40/40).

I ran the whole cdktn package on Windows 11. 13 tests fail in 4 suites, with and without this change: no terraform binary on PATH (matchers.test.ts) and no built lib directory (the asset-* suites). Prettier and eslint are clean on both files. I did not run terraform init on the output; the tests compare the generated HCL text.

Notes

🤖 Generated with Claude Code

escapeQuotes only escaped quotes, so a Windows path such as the default
local backend path was written as "C:\Users\..." and Terraform rejected it
at init. A value ending in a backslash left the string unterminated.

Escape backslashes and quotes, and drop the lookbehind that skipped a quote
after a backslash. A string with ${...} interpolations, including locals and
outputs, keeps each interpolation as written and escapes the text around it.

Closes: open-constructs#562

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Ramnath0521
Ramnath0521 requested a review from a team as a code owner November 9, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HCL synth doesn't escape backslashes in strings: the default local backend path on Windows produces invalid cdk.tf

1 participant