To follow this guide you need a SafeDep Cloud API Key and Tenant Identifier. See Cloud Quickstart on how to onboard to SafeDep Cloud and get an API key.
In this guide, we’ll discover Terraform providers used in a Terraform project, synchronize the inventory (BOM) with SafeDep Cloud, and execute queries to discover unofficial providers that may pose risks to developer, cloud, and CI/CD infrastructure security.
Supply Chain Security Unofficial providers may lack security oversight and could introduce vulnerabilities
Compliance Requirements Many organizations require approved provider lists for infrastructure code
Risk Management Understand the security posture of your infrastructure dependencies
Centralized Visibility Get organization-wide visibility into Terraform provider usage
Prerequisites
vet
installed (see quickstart for installation options)
SafeDep Cloud account with API key and tenant identifier
Terraform project with initialized providers (.terraform.lock.hcl
must exist)
Run vet
on your Terraform codebase to scan for Terraform providers. The Terraform project must be initialized so that .terraform.lock.hcl
is available in the project directory.
vet scan -D /path/to/terraform-code \
--report-sync \
--report-sync-project gh/test/infra1 \
--report-sync-project-version main
What This Command Does
Provider Discovery
Scans Terraform configuration files and lock files to identify all providers
Metadata Collection
Gathers information about provider versions, sources, and tiers (official, partner, community)
Cloud Synchronization
Uploads the provider inventory to SafeDep Cloud for centralized analysis
Project Tracking
Associates findings with specific projects and versions for tracking over time
Query Provider Inventory
Use SafeDep Cloud SQL queries to analyze your Terraform provider inventory. See SafeDep Cloud Quickstart for more details on the query interface.
Query for providers that are not officially maintained by HashiCorp:
SELECT
projects . name ,
projects . version ,
packages . name ,
packages . version
FROM projects
WHERE terraform_providers . tier != 'official'
Execute the query using the vet CLI:
vet cloud query execute --sql "
SELECT projects.name, projects.version, packages.name, packages.version
FROM projects
WHERE terraform_providers.tier != 'official'
"
Example Response
Here’s an example response from our test repository:
┌───────────────────────────────────────────┬──────────────────┬────────────────┬──────────────────┐
│ PACKAGES.NAME │ PACKAGES.VERSION │ PROJECTS.NAME │ PROJECTS.VERSION │
├───────────────────────────────────────────┼──────────────────┼────────────────┼──────────────────┤
│ registry.terraform.io/hetznercloud/hcloud │ 1.48.0 │ gh/test/infra1 │ main │
├───────────────────────────────────────────┼──────────────────┼────────────────┼──────────────────┤
│ registry.terraform.io/digitalocean/do │ 2.34.1 │ gh/test/infra1 │ main │
└───────────────────────────────────────────┴──────────────────┴────────────────┴──────────────────┘
Advanced Queries
Provider Tier Analysis
Get a breakdown of providers by their tier classification:
SELECT
terraform_providers . tier ,
COUNT ( * ) as provider_count,
COUNT ( DISTINCT projects . name ) as project_count
FROM projects
GROUP BY terraform_providers . tier
Find community providers that might need additional security review:
SELECT
packages . name ,
packages . version ,
projects . name as project,
terraform_providers . tier ,
terraform_providers . source
FROM projects
WHERE terraform_providers . tier = 'community'
ORDER BY packages . name
Provider Version Consistency
Check for version inconsistencies across projects:
SELECT
packages . name ,
packages . version ,
COUNT ( DISTINCT projects . name ) as project_count
FROM projects
GROUP BY packages . name , packages . version
HAVING COUNT ( DISTINCT projects . name ) > 1
ORDER BY packages . name
Recent Provider Additions
Find recently added providers (useful for change tracking):
SELECT
packages . name ,
packages . version ,
projects . name ,
projects . created_at
FROM projects
WHERE projects . created_at > DATE ( 'now' , '-7 days' )
ORDER BY projects . created_at DESC
CI/CD Integration
GitHub Actions
Integrate Terraform provider auditing into your CI/CD pipeline:
name : Terraform Security Audit
on :
push :
paths :
- '**/*.tf'
- '.terraform.lock.hcl'
pull_request :
paths :
- '**/*.tf'
- '.terraform.lock.hcl'
jobs :
terraform-audit :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- name : Setup Terraform
uses : hashicorp/setup-terraform@v3
- name : Terraform Init
run : terraform init
- name : Audit Terraform Providers
run : |
vet scan -D . \
--report-sync \
--report-sync-project ${{ github.repository }} \
--report-sync-project-version ${{ github.ref_name }}
env :
SAFEDEP_CLOUD_API_KEY : ${{ secrets.SAFEDEP_CLOUD_API_KEY }}
SAFEDEP_CLOUD_TENANT : ${{ secrets.SAFEDEP_CLOUD_TENANT }}
- name : Check for Unofficial Providers
run : |
vet cloud query execute --sql "
SELECT packages.name
FROM projects
WHERE terraform_providers.tier != 'official'
AND projects.name = '${{ github.repository }}'
AND projects.version = '${{ github.ref_name }}'
" --format json > unofficial-providers.json
if [ $(jq length unofficial-providers.json) -gt 0 ]; then
echo "⚠️ Unofficial providers detected:"
jq -r '.[].name' unofficial-providers.json
echo "Please review these providers for security compliance."
fi
GitLab CI
stages :
- init
- audit
terraform-init :
stage : init
image : hashicorp/terraform:latest
script :
- terraform init
artifacts :
paths :
- .terraform.lock.hcl
expire_in : 1 hour
terraform-audit :
stage : audit
image : ghcr.io/safedep/vet:latest
script :
- vet scan -D .
--report-sync
--report-sync-project $CI_PROJECT_PATH
--report-sync-project-version $CI_COMMIT_REF_NAME
dependencies :
- terraform-init
variables :
SAFEDEP_CLOUD_API_KEY : $SAFEDEP_CLOUD_API_KEY
SAFEDEP_CLOUD_TENANT : $SAFEDEP_CLOUD_TENANT
Policy Enforcement
Custom Provider Policies
Create policies to enforce provider compliance:
# terraform-provider-policy.yml
name : Terraform Provider Security Policy
description : Enforce approved provider usage
filters :
- name : unofficial-providers-blocked
value : |
terraform_providers.tier != "official" &&
!packages.name.startsWith("registry.terraform.io/hashicorp/")
- name : community-providers-require-approval
value : |
terraform_providers.tier == "community" &&
!packages.name.contains("approved-community-providers")
Use the policy during scanning:
vet scan -D . \
--filter-suite terraform-provider-policy.yml \
--filter-fail \
--report-sync \
--report-sync-project myproject \
--report-sync-project-version main
Schema Exploration
List all queryable columns for Terraform providers:
This will show you all available fields for building custom queries, including:
terraform_providers.tier
- Provider tier (official, partner, community)
terraform_providers.source
- Provider source URL
terraform_providers.namespace
- Provider namespace
packages.name
- Full provider name
packages.version
- Provider version
Best Practices
Troubleshooting