> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloudeval.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Review CloudFormation before deployment

> Reproduce a real CloudFormation reference failure, fix it, and connect static checks to Cloudeval pull-request review.

Catch a broken CloudFormation reference before a deployment starts. This example uses two public commits from the [Cloudeval AWS review repository](https://github.com/ganakailabs/cloudeval-aws-cloudformation-review-example). You can reproduce the static check without an AWS account or a Cloudeval access key.

**By Prateek Singh. Verified 10 September 2026 with cfn-lint 1.52.1.**

<Info>
  Cloudeval supports static AWS CloudFormation JSON/YAML evaluation in beta. This example verifies a template error with cfn-lint; it does not prove live AWS security, runtime availability, cost, or a completed Cloudeval report. Unsupported assessment areas remain **Not assessed**.
</Info>

## Reproduce the failure

In a new working directory, install the version used for this example:

```bash theme={null}
python3 -m venv .venv
source .venv/bin/activate
python -m pip install cfn-lint==1.52.1
```

On Windows, activate the environment with `.venv\Scripts\Activate.ps1` in PowerShell. The download and comparison commands below use a POSIX shell.

Download the exact baseline and regression. The commit URLs keep this walkthrough reproducible if the demo branches change:

```bash theme={null}
curl -fsSLo baseline.yaml https://raw.githubusercontent.com/ganakailabs/cloudeval-aws-cloudformation-review-example/c3c867bb6d587482a47be1dc6bd8eae798a37844/templates/webapp.yaml
curl -fsSLo regression.yaml https://raw.githubusercontent.com/ganakailabs/cloudeval-aws-cloudformation-review-example/e18247c84c34944428141841f54dd3075e657b30/templates/webapp.yaml

cfn-lint baseline.yaml
cfn-lint regression.yaml
```

The baseline passes without findings. The regression exits with code **2** and reports **E1020** for `MissingPrivateSubnetB`. The named subnet is absent from the template's declared resources and parameters.

The [public source diff](https://github.com/ganakailabs/cloudeval-aws-cloudformation-review-example/pull/3/files) changes one Auto Scaling subnet reference:

```diff theme={null}
 VPCZoneIdentifier:
   - !Ref PrivateSubnetA
-  - !Ref PrivateSubnetB
+  - !Ref MissingPrivateSubnetB
```

This is a reference-resolution failure. It is different from an architecture concern such as whether two subnets provide the intended availability or whether a security group exposes a workload.

## Correct the reference and check again

```bash theme={null}
sed 's/!Ref MissingPrivateSubnetB/!Ref PrivateSubnetB/' regression.yaml > corrected.yaml
cfn-lint corrected.yaml
```

The corrected file passes with no cfn-lint findings and matches the baseline template. This resolves the demonstrated reference error. Continue reviewing access, networking, availability, and applicable policy findings.

| Input                            | Observed cfn-lint result | What this establishes                                             |
| -------------------------------- | ------------------------ | ----------------------------------------------------------------- |
| Baseline commit `c3c867bb6d58`   | Exit 0, no findings      | The baseline passes this pinned static checker.                   |
| Regression commit `e18247c84c34` | Exit 2, E1020            | The changed `Ref` does not name a declared resource or parameter. |
| Corrected regression             | Exit 0, no findings      | Restoring `PrivateSubnetB` removes this error.                    |

## Add the Cloudeval review workflow

Use the [public AWS example repository](https://github.com/ganakailabs/cloudeval-aws-cloudformation-review-example) when you want template findings, project context, and configured gates in one review workflow.

<Steps>
  <Step title="Connect the repository">
    Fork the example, install the [Cloudeval GitHub App](https://github.com/apps/cloudeval-ai) on your fork, and create a Cloudeval project from the repository. Confirm the selected branch, source root, and `.cloudeval/config.yaml` entry point.
  </Step>

  <Step title="Configure the CI access key">
    Create a project-scoped **GitHub Actions CI** key. Add `CLOUDEVAL_ACCESS_KEY` and `CLOUDEVAL_PROJECT_ID` as GitHub repository secrets. These identify your Cloudeval account and project; the static template example does not require AWS credentials.
  </Step>

  <Step title="Review a controlled change">
    Follow [Review pull requests with GitHub Actions](/guides/review/github-actions). Inspect the evaluated commit, validation findings, gate result, and available artifacts. Keep cfn-lint findings, supplemental Checkov findings, and Cloudeval's supported AWS mappings distinguishable.
  </Step>

  <Step title="Verify the corrected commit">
    Correct the source and rerun the review. Match the new report to the new commit. Enforce only the gates you have configured and reviewed for the beta workflow.
  </Step>
</Steps>

<Warning>
  The example workflow skips Cloudeval review when its required secrets are missing. A green GitHub workflow is not proof that an evaluation ran. Open the review step and confirm a real result before using it as evidence. The local results above are from cfn-lint, not an authenticated Cloudeval run.
</Warning>

## Common mistakes

* **Treating valid syntax as a complete review.** A resolvable template can still contain overly broad ingress, public access, or unsuitable availability assumptions.
* **Comparing different commits.** Keep the GitHub diff, imported project snapshot, and report provenance aligned.
* **Applying Azure assumptions to AWS.** CloudFormation beta does not provide live AWS sync, full Azure report parity, or a complete AWS Well-Architected assessment.
* **Interpreting Not assessed as safe.** It means that the workflow has not established a result for that area.

## Next step

Set up [GitHub Actions review](/guides/review/github-actions), inspect the [supported cloud and IaC boundaries](/trust/supported-clouds-and-iac), or [connect an MCP client](/agents/mcp-client-setup) to read permitted saved project reports.
