diff --git a/bin/idstack-manifest-merge b/bin/idstack-manifest-merge index a799825..8470c97 100755 --- a/bin/idstack-manifest-merge +++ b/bin/idstack-manifest-merge @@ -98,9 +98,12 @@ def load_payload(payload_arg): except Exception as exc: die(6, f"failed to read payload file {payload_arg!r}: {exc}") try: - return json.loads(text) + data = json.loads(text) except json.JSONDecodeError as exc: die(1, f"payload is not valid JSON: {exc}") + if not isinstance(data, dict): + die(1, f"payload root must be a JSON object: got {type(data).__name__}") + return data def load_manifest(manifest_path): diff --git a/test/test-manifest-merge.sh b/test/test-manifest-merge.sh index 51206c0..fd41e86 100755 --- a/test/test-manifest-merge.sh +++ b/test/test-manifest-merge.sh @@ -135,6 +135,26 @@ EC=$? set -e assert "manifest with string root exits 2" "[ $EC -eq 2 ]" +echo "" + +# --- Test 13: payload with non-dict root (list) rejected with exit 1 --- +seed_manifest +echo '[]' > "$WORK/payload.json" +set +e +"$MERGE" --section red_team_audit --payload "$WORK/payload.json" --manifest "$WORK/project.json" --quiet 2>/dev/null +EC=$? +set -e +assert "payload with list root exits 1" "[ $EC -eq 1 ]" + +# --- Test 14: payload with non-dict root (string) rejected with exit 1 --- +seed_manifest +echo '"a string"' > "$WORK/payload.json" +set +e +"$MERGE" --section red_team_audit --payload "$WORK/payload.json" --manifest "$WORK/project.json" --quiet 2>/dev/null +EC=$? +set -e +assert "payload with string root exits 1" "[ $EC -eq 1 ]" + echo "" echo "manifest-merge: $PASS/$TOTAL passed, $FAIL failed" [ "$FAIL" -eq 0 ] && exit 0 || exit 1