Describe the bug
SerializationOptions(strip_string_quotes=True) strips quotes from string literals inside expressions, not just from top-level string values. The resulting expression text is no longer valid HCL, and the original cannot be recovered.
Software:
- OS: macOS 15 (arm64)
- Python version: 3.11.16
- python-hcl2 version: 8.1.2; also reproduced on 8.1.0. (The option does not
exist in 7.x, and 8.0.0rc1 predates this form of SerializationOptions, so
8.1.0 is the earliest affected release.)
Snippet of HCL2 code causing the unexpected behaviour:
a = upper("x")
b = var.x ? "yes" : "no"
c = [for s in var.list : upper(s) if s != ""]
Actual behavior
import hcl2
from hcl2.utils import SerializationOptions
hcl2.loads(src, serialization_options=SerializationOptions(strip_string_quotes=True))
# {'a': '${upper(x)}',
# 'b': '${var.x ? yes : no}',
# 'c': '${[for s in var.list : upper(s) if s != ]}'}
upper(x) now references an identifier x rather than the string "x"; var.x ? yes : no references two undefined identifiers; and s != is a syntax error.
Expected behavior
Quote stripping should apply to string values, leaving quoted literals inside expression text alone:
{'a': '${upper("x")}', 'b': '${var.x ? "yes" : "no"}', 'c': '${[for s in var.list : upper(s) if s != ""]}'}
which is what 7.2.1 produced.
Impact
docs/06_migrating_to_v8.md presents strip_string_quotes=True as the v7 compatibility path and warns only that it is one-way (not round-trippable). It does not say that expression contents are corrupted, so it reads as safe for read-only consumers — which it is not, for any configuration containing a function call, a conditional, or a comparison against a string.
This matters more given #289 proposes making strip_string_quotes=True the default.
Workaround
Leave the option off and strip the outer quotes yourself, only when a value both starts and ends with ". That preserves expression interiors, since expressions arrive as bare ${...} strings without surrounding quotes.
Describe the bug
SerializationOptions(strip_string_quotes=True)strips quotes from string literals inside expressions, not just from top-level string values. The resulting expression text is no longer valid HCL, and the original cannot be recovered.Software:
exist in 7.x, and 8.0.0rc1 predates this form of
SerializationOptions, so8.1.0 is the earliest affected release.)
Snippet of HCL2 code causing the unexpected behaviour:
Actual behavior
upper(x)now references an identifierxrather than the string"x";var.x ? yes : noreferences two undefined identifiers; ands !=is a syntax error.Expected behavior
Quote stripping should apply to string values, leaving quoted literals inside expression text alone:
{'a': '${upper("x")}', 'b': '${var.x ? "yes" : "no"}', 'c': '${[for s in var.list : upper(s) if s != ""]}'}which is what 7.2.1 produced.
Impact
docs/06_migrating_to_v8.mdpresentsstrip_string_quotes=Trueas the v7 compatibility path and warns only that it is one-way (not round-trippable). It does not say that expression contents are corrupted, so it reads as safe for read-only consumers — which it is not, for any configuration containing a function call, a conditional, or a comparison against a string.This matters more given #289 proposes making
strip_string_quotes=Truethe default.Workaround
Leave the option off and strip the outer quotes yourself, only when a value both starts and ends with
". That preserves expression interiors, since expressions arrive as bare${...}strings without surrounding quotes.