Terrascan Tutorial: Securing Infrastructure as Code with DevSecOps [2025 Guide]
Learn how to implement DevSecOps in your infrastructure as code using Terrascan. This step-by-step guide covers installation, scanning, custom policies, and CI/CD integration to prevent security misconfiguration.
Are you looking to advance your DevOps career?
Join my 16-week Advanced, real-world, project-based DevOps Bootcamp is for you.
You are making a big mistake by not scanning your Terraform for vulnerabilities
Last year, someone I know deployed a Kubernetes cluster that accidentally exposed internal APIs to the internet because of a misconfigured network policy.
They caught it during a routine scan, but it could have been much worse.
Infra misconfigurations aren’t just embarrassing — they’re potentially catastrophic.
Infrastructure misconfigurations have been behind some of the most notorious security incidents in recent years.
From the Capital One breach caused by a misconfigured WAF to the thousands of Elasticsearch instances leaking sensitive data, the pattern is clear: the security of your cloud depends heavily on your configuration, not just your code.
Security in infrastructure code often feels like an afterthought. We’re so focused on making things work that we forget to make them secure.
At my company, we already use Checkov for basic security scanning, but we’ve found limitations in its policy coverage and customization options.
That’s why we’re adding Terrascan to our security toolkit — it offers deeper analysis, better policy flexibility, and more comprehensive coverage across different cloud providers.
Catching Security Nightmares Before They Happen with Terrascan
What is Terrascan?
Terrascan is an open-source static code analyzer created by Tenable and specially designed for Infrastructure as Code.
It works with various IaC tools like Terraform, Kubernetes, Helm, and others. It scans your configuration files (HCL, YAML, and JSON) for security best practices, misconfigurations, compliance issues, and potential vulnerabilities.
Terrascan policies are written using the Rego policy language. You can write custom policies tailored to your organization’s requirements.
The best part is that it integrates seamlessly into your development workflow, catching problems before they make it to production.
Key Features of Terrascan
- It ensures that your infrastructure code aligns with regulatory requirements.
- It is cloud-agnostic and supports multiple cloud providers.
- Integrate well with CICD workflows.
- It’s open-source with an active community
Let’s take Terrascan for a spin
Getting Started with Terrascan
Installation
I am using a Mac, and you can install Terrascan using brew
$ brew install terrascan
Alternatively, you can use the below steps to install it on Mac/Linux machines.
$ curl -L "$(curl -s https://api.github.com/repos/tenable/terrascan/releases/latest | grep -o -E "https://.+?_Darwin_x86_64.tar.gz")" > terrascan.tar.gz
$ tar -xf terrascan.tar.gz terrascan && rm terrascan.tar.gz
$ install terrascan /usr/local/bin && rm terrascan
$ terrascan
Basic syntax
It is fairly easy to use, just cd
to any directory with the IAC code on and run the below command.
terrascan scan

It shows you all the vulnerabilities in your code base. You can customize the command to give you more specific output or check for a particular type of file and severity. But more on that later.
Let’s see what we got for terraform CLI; just run the command
terrascan --help

terrascan scan --help
Flags:
--config-only will output resource config (should only be used for debugging purposes)
--config-with-error will output resource config and errors (if any)
--find-vuln fetches vulnerabilities identified in Docker images
-h, --help help for scan
-d, --iac-dir string path to a directory containing one or more IaC files (default ".")
-f, --iac-file string path to a single IaC file
-i, --iac-type string iac type (arm, cft, docker, helm, k8s, kustomize, terraform, tfplan)
--iac-version string iac version (arm: v1, cft: v1, docker: v1, helm: v3, k8s: v1, kustomize: v2, v3, v4, terraform: v12, v13, v14, v15, tfplan: v1)
--non-recursive do not scan directories and modules recursively
-p, --policy-path stringArray policy path directory
-t, --policy-type strings policy type (all, aws, azure, docker, gcp, github, k8s) (default [all])
-r, --remote-type string type of remote backend (git, s3, gcs, http, terraform-registry)
-u, --remote-url string url pointing to remote IaC repository
--repo-ref string branch of the repo being scanned
--repo-url string URL of the repo being scanned, will be reflected in scan summary
--scan-rules strings one or more rules to scan (example: --scan-rules="ruleID1,ruleID2")
--severity string minimum severity level of the policy violations to be reported by terrascan
--show-passed display passed rules, along with violations
--skip-rules strings one or more rules to skip while scanning (example: --skip-rules="ruleID1,ruleID2")
--use-colors string color output (auto, t, f) (default "auto")
--use-terraform-cache use terraform init cache for remote modules (when used directory scan will be non recursive, flag applicable only with terraform IaC provider)
--values-files strings one or more values files to scan(applicable for iactype=helm) (example: --values-files="file1-values.yaml,file2-values.yaml")
-v, --verbose will show violations with details (applicable for default output)
--webhook-token string optional token used when sending authenticated requests to the notification webhook
--webhook-url string webhook URL where Terrascan will send JSON scan report and normalized IaC JSON
Global Flags:
-c, --config-path string config file path
-l, --log-level string log level (debug, info, warn, error, panic, fatal) (default "info")
--log-output-dir string directory path to write the log and output files
-x, --log-type string log output type (console, json) (default "console")
-o, --output string output type (human, json, yaml, xml, junit-xml, sarif, github-sarif) (default "human")
--temp-dir string temporary directory path to download remote repository,module and templates
As you can see above, there are a ton of options available with terraform scan
. You can use these flags to customize the output.
Let’s use some of the flags
-t
To scan for a specific cloud provider.
Useful options are all, aws, azure, gcp, github, k8s
-i
To scan for a particular IAC provider.
Some useful options are docker, helm, k8s, kustomize, and terraform.
-f
To scan a specific file-o
output format— — severity
Check with the minimum severity level.
The options are Low, Medium, and High.
Try out different flags with the command
terrascan scan -t gcp -i terraform -o json --severity "High"

--config-only
It prints resource configs for debugging purposes.
For debugging purposes, you can print this resource configs list as an output by using the --config-only
terrascan scan -i terraform -t gcp -f main.tf --config-only -o json
{
"google_compute_network": [
{
"id": "google_compute_network.default",
"name": "default",
"module_name": "root",
"source": "main.tf",
"line": 1,
"type": "google_compute_network",
"config": {
"auto_create_subnetworks": false,
"name": "${var.vpc_name}",
"project": "${var.project_id}"
},
"line_config": {
"auto_create_subnetworks": 3,
"name": 2,
"project": 4
},
"skip_rules": null,
"max_severity": "",
"min_severity": "",
"terraform_version": "0.15.0",
"provider_version": "5.4.0"
}
],
"google_compute_subnetwork": [
{
"id": "google_compute_subnetwork.default",
"name": "default",
"module_name": "root",
"source": "main.tf",
"line": 7,
"type": "google_compute_subnetwork",
"config": {
"ip_cidr_range": "${var.subnet_cidr}",
"name": "${var.subnetwork_name}",
"network": "${google_compute_network.default.name}",
"private_ip_google_access": true,
"project": "${var.project_id}",
"region": "${var.region}"
},
Terrascan can be used to scan docker image vulnerabilities
You can scan the Dockerfile by specifying “docker” on the -i flag
terrascan scan -i docker

To display container image vulnerabilities present in the IaC files
$ terrascan scan -i <IaC Provider> --find-vuln
Terrascan can also be run as a docker container
docker run --rm tenable/terrascan version
You can mount the IAC code as volume (with -v ) and run the container with the below command. Since I am already in the directory where my IAC code exists, I can run the below command.
docker run --rm -it -v "$(pwd)" -w /iac tenable/terrascan
Integrating Terrascan into Your Workflow
You can integrate Terrascan into your CICD workflow using tenable/terrascan-action
Github Action
Below is a simple GitHub action workflow that would run the Terrascan on a push to the main branch
# .github/workflows/run-terrascan.yaml
name: run terrascan
on: [push]
jobs:
terrascan_job:
runs-on: ubuntu-latest
name: terrascan-action
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Run Terrascan
id: terrascan
uses: tenable/terrascan-action@main
with:
iac_type: 'terraform'
iac_version: 'v14'
policy_type: 'gcp'
only_warn: true
You can customize it with all the options you have with Terrascan CLI
Using Pre-commit Hooks
I suggest adding Terrascan to your pre-commit hooks to catch issues before they get committed.
# .pre-commit-config.yaml
repos:
- repo: https://github.com/tenable/terrascan
rev: v1.18.0
hooks:
- id: terrascan
args: ['scan', '-i', 'terraform']
Writing Custom Security Policies
One of Terrascan’s most powerful features is the ability to write custom security policies using the Rego policy language. This lets you enforce organization-specific security rules that might not be covered by default policies.
For example, if you want to ensure that all your GCP firewall rules don’t allow SSH (port 22) from the internet, you could create a custom policy:
# custom-policies/terraform/no_public_ssh/rule.rego
package accurics
tcp_port_22_open[api.id] {
api := input.google_compute_firewall[_]
rule := api.config.allow[_]
port := rule.ports[_]
contains(lower(port), "22")
api.config.direction == "INGRESS"
api.config.source_ranges[_] == "0.0.0.0/0"
}
Then, scan with your custom policies:
terrascan scan -i terraform -p custom-policies
Final words
Security in infrastructure can’t be an afterthought anymore. With the rise in cloud misconfigurations leading to major breaches, scanning your IaC is no longer optional.
Terrascan makes this easy by automatically checking your infrastructure code against hundreds of security policies.
Resources
Are you looking to advance your DevOps career?
Join my 16-week Advanced, real-world, project-based DevOps Bootcamp is for you.