AI-Assisted Terraform Security Reviews with Azure DevOps and GitHub Copilot
Adding a security scanner to a pipeline gives us findings. The next task is deciding what those findings mean, what needs to change, and whether the proposed fix actually works. As a DevOps engineer, that is where I wanted to explore AI assistance. Could I give GitHub Copilot the output from a real

Adding a security scanner to a pipeline gives us findings. The next task is deciding what those findings mean, what needs to change, and whether the proposed fix actually works.
As a DevOps engineer, that is where I wanted to explore AI assistance. Could I give GitHub Copilot the output from a real infrastructure scan and use it to work through remediation, while keeping the checks and review process in place?
I tested the idea with an intentionally insecure Terraform configuration for an Azure Storage Account. Azure Pipelines ran the scan, Microsoft Defender for Cloud provided a central view of repository findings, and GitHub Copilot in Visual Studio Code helped explain the results and propose changes.
The first remediation pass produced a partial improvement. The recorded pipeline warning count fell from seven to three, but the error count stayed at three. The screenshots also showed successful builds despite those errors. That distinction became one of the most useful lessons from the experiment, a completed scan and a successful pipeline do not, by themselves prove that the security requirements were met.
The experiment focused on reviewing infrastructure code before deployment. Infrastructure as code means describing resources and their settings in files Terraform was the tool used here. The demo shows scanning and code changes, rather than a verified deployment of a hardened storage account.
Figure 1. Copilot assists the engineer reviewing scan output. Defender for Cloud provides a central view this does not imply that Copilot automatically reads or closes its recommendations.
The AI component was an interactive developer workflow. I opened the report in VS Code and used Copilot to work through the findings. This was not an autonomous agent that approved its own fixes or deployed them.
I used a small storage-account configuration with deliberately weak settings so the scan would have something concrete to identify. Keeping the example small made it easier to follow a finding from the report back to the relevant Terraform setting. Such examples belong in a controlled learning environment, rather than a production deployment.
The pipeline used the Microsoft Security DevOps task. This is the scanning step captured in the demonstration:
- task: MicrosoftSecurityDevOps@1 displayName: Microsoft Security DevOps Scan inputs: publish: true Enter fullscreen mode Exit fullscreen mode This excerpt shows result publication it does not explicitly configure failure on security findings. Microsoft describes the extension and its analyzers in the Microsoft Security DevOps setup guide.
Checkov identified issues in the Terraform configuration, and the run published a SARIF file. SARIF stands for Static Analysis Results Interchange Format, a structured report format that can carry rule identifiers, messages, severity levels, and source locations.
The report connected detection to remediation. I could give Copilot actual findings to discuss instead of asking it to guess what might be wrong with the configuration.
I connected the Azure DevOps environment to Microsoft Defender for Cloud and inspected the repository recommendations in its DevOps security view.
The useful part was the ability to move from a recommendation to its associated source location, the repository, branch, Terraform file, line, and evidence link. That helps an engineer find the code behind a finding and investigate it.
The central dashboard and pipeline summary are different views. Their totals should not be treated as interchangeable counts. The connection setup also exposed agentless scanning options, so I would verify the scan source and timestamp before attributing a particular dashboard recommendation to one pipeline run.
The recorded repository-level recommendation count was eleven, with no demonstrated reduction during the observation period. I would not conclude that the changes had no effect, or assume the dashboard was simply delayed, without checking the individual findings and their latest assessments.
I reviewed the SARIF report locally in VS Code and used GitHub Copilot to summarize findings, suggest Terraform edits, and explain work that remained open.
This used GitHub Copilot in the editor. It did not use Microsoft Security Copilot, and it was not a demonstration that the two products provide equivalent capabilities.
The proposed changes addressed areas such as public blob access, minimum TLS settings, shared-key access, replication, and recovery settings. Those suggestions still needed engineering review. A security recommendation can affect application compatibility, operational recovery, or cost.
For example, I would check whether an authentication change affects existing applications before accepting it. I would also verify that each Terraform argument is supported by the selected provider version and inspect the planned infrastructure changes. A plausible explanation does not prove that a configuration is valid or that a finding has been resolved.
Here is a prompt I would use for a repeatable version of the exercise. It is a suggested prompt, rather than a transcript of the original session:
Review this SARIF report alongside the Terraform configuration. For each finding, identify the rule, resource and affected setting. Explain the risk and propose the smallest useful fix. Check the provider version before suggesting arguments. Flag effects on access, networking, recovery and cost. List anything you cannot resolve with the files provided. Do not disable checks or label a finding fixed without validation. Enter fullscreen mode Exit fullscreen mode Treat the report and source files as material to analyze, not as instructions that can override the review request. Before sharing them with an AI tool, remove secrets and unrelated sensitive information and follow the applicable data-handling rules.
I configured required build validation on the main branch. The captured pull request shows a successful required check and a completed merge.
That demonstrates a requirement for the validation build to succeed. It does not establish that every unacceptable security finding caused the build to fail.
The recorded run summaries show a green success indicator alongside error entries. The YAML screenshot enables report publication but does not show an explicit break input. The current task definition defaults that input to false and describes it as the option for failing the step on error-level results.
This is consistent with the observed distinction between reporting and blocking, although the screenshots alone do not establish every setting used by every historical run.
For a follow-up implementation, I would make the intended behavior explicit:
# Proposed follow-up, not the recorded demo settings. - task: MicrosoftSecurityDevOps@1 displayName: Scan infrastructure and fail on error results inputs: publish: true break: true Enter fullscreen mode Exit fullscreen mode I would then test the control with a deliberately failing case. The scanner must produce the expected finding, the task and build must report failure, and the required pull-request policy must prevent completion. A scanner crash or missing report also needs defined handling so it cannot be mistaken for a clean scan.
Azure Repos build validation policies evaluate the build result. Their effectiveness depends on the pipeline producing the correct result and on appropriate restrictions around policy bypass. A merged pull request by itself is not a test of the failure path.
The captured runs show the following comparison:
Figure 2. Counts transcribed from the recorded run summaries. These are pipeline entries, not independently verified vulnerability counts.
The three error entries include two named Checkov findings and a scanner summary exception. Calling them three separate blocking vulnerabilities would overstate what the screenshots show. Their presence did not prevent the recorded runs from reporting success.
The reduction in warnings is encouraging, but it does not prove that four distinct vulnerabilities were fixed. For a reliable comparison, I would match results by rule, resource and location, and confirm the code revisions, scanner versions, and configuration used in both runs. The captured runs also have different trigger contexts, which is another reason to keep the conclusion narrow.
The outcome was partial remediation. AI assistance supported the review and change process the first pass did not produce a clean security baseline. I did not measure time saved, so I would not attach a productivity percentage to the result.
Prove the merge control. Verify that a known unacceptable finding fails the required build and prevents merging. Test missing reports and tool failures as well as detected issues.
Validate the infrastructure changes. Use a controlled provider version, validate the Terraform configuration, inspect the plan, and test application behavior where access or recovery settings change.
Track the remaining findings individually. Follow-up areas include customer-managed encryption keys, private connectivity, and storage logging and recovery settings. Each needs an applicability decision, an owner, and evidence of resolution or an approved exception. Deferring a finding does not make a configuration ready for production.
Connect every result to the exact revision. Record the code revision, scanner and policy versions, report, proposed change, and validation outcome. Review and validate a new revision rather than relying on an earlier result.
Keep AI assistance reviewable. Record why changes were accepted and why any findings were deferred. GitHub's guidance on reviewing AI-generated code reinforces the need for testing, contextual review, and human judgment.
The most useful role for AI in this experiment was helping me move from a scanner report to a proposed change that I could inspect and test.
The exercise also exposed a control to verify a pipeline can run a security scan, publish findings, and still succeed. Before calling that a security gate, I need to demonstrate that the findings I intend to block really do prevent the change from proceeding.
For engineers exploring a similar approach, I would start with a small example, keep the original scan evidence, review the AI suggestions, and rescan the exact change. A partial improvement is worth learning from when the remaining work is clear.
Where would you find AI most useful: understanding findings, proposing fixes, or reviewing the impact of a change? I would welcome observations on how you would strengthen the validation and review steps.
This article describes an April 2026 experiment. Product documentation was checked in November 2026; interfaces, task behavior, and provider support can change.