Skip to content

Commit d4dff7e

Browse files
cowork-bot: reject non-object plan JSON
Fail clearly when Terraform, CloudFormation, or Pulumi input decodes to a non-object JSON value.
1 parent 6dda04d commit d4dff7e

4 files changed

Lines changed: 22 additions & 0 deletions

File tree

src/deploydiff/cloudformation_parser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ def parse_cloudformation_changeset(changeset_json: str | dict[str, Any]) -> Depl
5252
else:
5353
data = changeset_json
5454

55+
if not isinstance(data, dict):
56+
raise ValueError("Change set input must be a JSON object")
57+
5558
changes: list[ResourceChange] = []
5659
changes_list = data.get("Changes", data.get("changes", []))
5760

src/deploydiff/pulumi_parser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ def parse_pulumi_preview(preview_json: str | dict[str, Any]) -> DeployPlan:
5050
else:
5151
data = preview_json
5252

53+
if not isinstance(data, dict):
54+
raise ValueError("Preview input must be a JSON object")
55+
5356
changes: list[ResourceChange] = []
5457

5558
# Pulumi preview JSON has a "steps" array

src/deploydiff/terraform_parser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ def parse_terraform_plan(plan_json: str | dict[str, Any]) -> DeployPlan:
4444
else:
4545
data = plan_json
4646

47+
if not isinstance(data, dict):
48+
raise ValueError("Plan input must be a JSON object")
49+
4750
format_version = data.get("format_version", "")
4851
changes: list[ResourceChange] = []
4952

tests/test_parse_errors.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,16 @@ def test_cloudformation_valid_dict_still_works(self):
5959
data = {"Changes": []}
6060
plan = parse_cloudformation_changeset(data)
6161
assert len(plan.changes) == 0
62+
63+
@pytest.mark.parametrize(
64+
("parser", "payload"),
65+
[
66+
(parse_terraform_plan, []),
67+
(parse_cloudformation_changeset, []),
68+
(parse_pulumi_preview, []),
69+
],
70+
)
71+
def test_json_array_is_rejected_with_clear_error(self, parser, payload):
72+
"""A decoded JSON value must be an object before parser-specific access."""
73+
with pytest.raises(ValueError, match="JSON object"):
74+
parser(payload)

0 commit comments

Comments
 (0)