CloudFormation drift detector with property-level diffs and Slack/GitHub integration
Project description
stackdrift
A pip-installable CloudFormation drift detector. Detects when deployed AWS resources have drifted from their CloudFormation template definitions, with property-level diffs and optional Slack/GitHub integrations.
Features
- Detects drift across all stacks in an AWS account, or a filtered subset by name, prefix, or tag
- Property-level diffs — shows exactly which resource properties changed and what the expected vs. actual values are
- Concurrent drift detection (configurable, default: 5 simultaneous)
- Rich color terminal output (tree view), JSON, and Markdown formats
- Slack webhook and GitHub PR comment integrations
--redact-valuesflag to suppress sensitive values from output and reports- CI-friendly exit codes:
0no drift,1drift detected,2detection failure
Installation
pip install stackdrift
Usage
# Check all stacks in the account
stackdrift
# Check specific stacks by name
stackdrift --stack my-stack
stackdrift --stack my-stack-1 --stack my-stack-2
# Filter stacks by name prefix or tag
stackdrift --prefix prod-
stackdrift --tag Environment=prod
# Show only stacks with drift (suppress IN_SYNC stacks)
stackdrift --drifted-only
# AWS region (defaults to AWS_DEFAULT_REGION / ~/.aws/config)
stackdrift --region us-east-1
# Output formats
stackdrift --format table # default — colored Rich tree
stackdrift --format json
stackdrift --format markdown
# Suppress sensitive expected/actual values in all output
stackdrift --redact-values
# Suppress warning messages (show only errors)
stackdrift --quiet
# Control how many stacks are checked concurrently (1–50)
stackdrift --max-concurrent 10
# Post report to Slack (requires STACKDRIFT_SLACK_WEBHOOK env var)
stackdrift --post-slack
# Post report as a GitHub PR comment (requires GITHUB_TOKEN and GITHUB_REPO env vars)
stackdrift --post-github-pr 42
Exit Codes
| Code | Meaning |
|---|---|
0 |
All stacks in sync — no drift detected |
1 |
Drift detected in one or more stacks |
2 |
Detection failed for one or more stacks (API error, insufficient permissions, etc.), or a required env var was missing (STACKDRIFT_SLACK_WEBHOOK, GITHUB_TOKEN, GITHUB_REPO) |
Useful for CI pipelines:
stackdrift --drifted-only || echo "Drift detected!"
Environment Variables
| Variable | Required for | Description |
|---|---|---|
STACKDRIFT_SLACK_WEBHOOK |
--post-slack |
Incoming webhook URL for the target Slack channel |
GITHUB_TOKEN |
--post-github-pr |
Personal access token or Actions token with pull_requests: write |
GITHUB_REPO |
--post-github-pr |
Repository in owner/repo format (e.g. myorg/myrepo) |
Reading the Output
Property diffs are shown as expected → actual. A value of null means the property is absent on that side:
| Pattern | Meaning |
|---|---|
null → "value" |
Property exists on the live resource but not in the template — added out-of-band |
"value" → null |
Property is in the template but missing from the live resource — removed out-of-band |
Examples:
/Parameters/3: null → {"ParameterKey":"ExistingOIDCProviderArn","ParameterValue":""}
An extra parameter was added directly to the StackSet, not through CloudFormation.
/TargetIds/0: ou-350a-kg3vy772 → null
That OU target was detached from the SCP directly in AWS — CloudFormation still expects it.
/KmsMasterKeyId: alias/aws/sns → null
The SNS topic's KMS encryption key was removed outside of CloudFormation.
Required IAM Permissions
{
"Effect": "Allow",
"Action": [
"cloudformation:ListStacks",
"cloudformation:DetectStackDrift",
"cloudformation:DescribeStackDriftDetectionStatus",
"cloudformation:DescribeStackResourceDrifts",
"cloudformation:DescribeStacks"
],
"Resource": "*"
}
Development
git clone https://github.com/Specter099/stackdrift.git
cd stackdrift
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Run tests
pytest
# Lint and format check
ruff check src/ tests/
ruff format --check .
Contributing
See CONTRIBUTING.md for guidelines.
Security
See SECURITY.md for reporting vulnerabilities.
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stackdrift-0.1.4.tar.gz.
File metadata
- Download URL: stackdrift-0.1.4.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22ca4224f4c658a5ad8000a6c3142f3b27d5e3bdb08d38420c0dc0b28e437659
|
|
| MD5 |
310714403a201d9ca5527d0387e23a42
|
|
| BLAKE2b-256 |
0ebfa5119362ef5ed685e241cfc260f0f8227920e8152d4cd5362b86caae50cb
|
Provenance
The following attestation bundles were made for stackdrift-0.1.4.tar.gz:
Publisher:
publish.yml on Specter099/stackdrift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stackdrift-0.1.4.tar.gz -
Subject digest:
22ca4224f4c658a5ad8000a6c3142f3b27d5e3bdb08d38420c0dc0b28e437659 - Sigstore transparency entry: 1004889409
- Sigstore integration time:
-
Permalink:
Specter099/stackdrift@0eaa458e8b8792199eb740b7d493c6c2b6bb1aa9 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/Specter099
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0eaa458e8b8792199eb740b7d493c6c2b6bb1aa9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file stackdrift-0.1.4-py3-none-any.whl.
File metadata
- Download URL: stackdrift-0.1.4-py3-none-any.whl
- Upload date:
- Size: 14.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
90d3c0796e72359d7ed25e110364eab703c2faeef65e707731cf53f6a4be759d
|
|
| MD5 |
8bb29264eab720f5264f8493eecb38be
|
|
| BLAKE2b-256 |
4cf1da261703bf14f8d2804341fb5a727f52133139895eccca99c2ef90b3def2
|
Provenance
The following attestation bundles were made for stackdrift-0.1.4-py3-none-any.whl:
Publisher:
publish.yml on Specter099/stackdrift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stackdrift-0.1.4-py3-none-any.whl -
Subject digest:
90d3c0796e72359d7ed25e110364eab703c2faeef65e707731cf53f6a4be759d - Sigstore transparency entry: 1004889415
- Sigstore integration time:
-
Permalink:
Specter099/stackdrift@0eaa458e8b8792199eb740b7d493c6c2b6bb1aa9 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/Specter099
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0eaa458e8b8792199eb740b7d493c6c2b6bb1aa9 -
Trigger Event:
release
-
Statement type: