Security: Fix Sensitive Value Exposure in Generated Reports
This release fixes a security issue in which tfplan2md could include plaintext Terraform sensitive values in generated Markdown reports. The bug affected several distinct rendering paths: AzApi resource body properties, AzureDevOps variable groups, Scriban template context variables, and hierarchical sensitivity detection. After this fix, any value marked sensitive in your Terraform plan is rendered as `(sensitive)` in the output — regardless of which provider or rendering path is used.
🐛 Bug fixes
-
AzApi create/delete/replace body: Properties marked sensitive in
after_sensitive.bodyorbefore_sensitive.body(e.g.administratorLoginPassword,clientSecret) are now masked in the Body table. Previously, values fromafter.body(orbefore.body) were rendered verbatim. -
AzApi update body: The
is_sensitiveflag computed from the sensitivity structure was correctly threaded into the update renderers but never applied. Sensitive properties in Body Changes tables now display`(sensitive)`in both Before and After columns. -
Scriban template context (defense in depth): The
before_jsonandafter_jsonScriptObjects exposed to custom Scriban templates are now masked by default when--show-sensitiveis not set. Sensitive leaf paths are replaced with"(sensitive)". The raw structures remain accessible viabefore_sensitiveandafter_sensitivefor templates that need to make layout decisions. -
AzureDevOps Variable Group secret transitions: A variable that transitions from
is_secret: truetois_secret: falsenow shows`(sensitive / hidden)`in the Before column (matching the long-standing behavior for the reverse direction). Previously, the old plaintext value was revealed. -
Root boolean sensitivity (
after_sensitive: trueat the resource level): All attributes are now correctly hidden when the entire resource is marked sensitive via an empty-string key in the sensitivity map. -
Top-level array parent sensitivity (
secrets: trueinafter_sensitive): Array elements such assecrets[0].valueare now covered by the parentsecretssensitivity marker. Previously, only dotted paths were traced upward; bare array keys likesecrets[0]were not linked to their parent. -
Duplicate hierarchical path detection:
GetHierarchicalPathsno longer yields duplicate paths for multi-level indexed keys (e.g.,a[0].b[1]), and now correctly strips only the innermost index when resolving the parent.
The --show-sensitive flag continues to work across all paths: passing it reveals the actual values in all output sections.
🔗 Commits
1d44017efix: handle root boolean and top-level array parent sensitivityb5820a62fix: mask Variable Group values when either side is secret712c3f6ffix: mask sensitive values in AzApi create/delete/replace body renderingca0e215ffix: mask sensitive values in AzApi update body renderingb13f7683fix: mask before_json/after_json at mapper level + fix AzApi comparison81e98ed7fix: deduplicate GetHierarchicalPaths for multi-level indexed keys246fb13cfix: handle ScriptArray per-element sensitivity in MaskSensitiveLeaves