ESLint for AWS IAM — catch over-permissioned policies in your Terraform PRs before they merge.
IAM misconfigurations are the #1 cause of AWS breaches — wildcards on Action and
Resource, forgotten AdministratorAccess attachments, and overly-permissive
assume_role_policy are easy to ship and hard to spot in code review.
iamarmor is a static linter for Terraform IAM resources. It runs entirely
offline — no AWS credentials, no Terraform plan needed — and integrates as a
pre-commit hook or a CI step in seconds. Think ESLint, but for your IAM policies.
$ iamarmor lint modules/iam/
modules/iam/main.tf
✘ IAM001 [HIGH] resource 'aws_iam_policy.app' has Action: "*" — grant least-privilege actions instead.
✘ IAM005 [HIGH] resource 'aws_iam_policy.deployer' grants iam:PassRole on Resource: "*" — scope to specific role ARNs.
✘ IAM010 [HIGH] resource 'aws_iam_role_policy_attachment.admin' attaches AdministratorAccess — grant only required permissions.
3 findings (3 high, 0 medium, 0 low) in 0.12 s
exit 1
Regenerate with:
vhs docs/demo.tape
# Install (requires Python 3.11+)
pip install iamarmor
# Lint the current directory
iamarmor lint .
# Lint a specific file
iamarmor lint modules/iam/main.tf
# Machine-readable output for CI pipelines
iamarmor lint . --format jsoniamarmor lint exits 0 when clean, 1 when findings meet the fail_on
threshold (default: medium), 2 on usage/config errors, and 3 on
internal errors — making CI integration trivial.
Place a .iamarmor.yml in the root of your Terraform repository:
version: 1
severity_threshold: low # report findings at or above this level (default: info)
fail_on: high # exit 1 only for high/critical (default: medium)
rules:
ignore: [IAM004] # skip noisy rules for your environment
overrides:
IAM002:
severity: critical # escalate a rule's severity
paths:
exclude:
- "modules/legacy/**" # skip paths you're not ready to fix yetiamarmor auto-discovers .iamarmor.yml by walking upward from the linted path
(same pattern as .eslintrc). Pass --no-config to skip loading.
See docs/config.md for the full configuration reference.
iamarmor ships with 10 default IAM rules covering the most common misconfigurations:
| ID | Name | Severity |
|---|---|---|
| IAM001 | No Action: "*" |
High |
| IAM002 | No Resource: "*" with sensitive actions |
High |
| IAM003 | No inline policies | Medium |
| IAM004 | IAM roles must set max_session_duration |
Low |
| IAM005 | No iam:PassRole with Resource: "*" |
High |
| IAM006 | No wildcard Principal in resource-based policies |
High |
| IAM007 | assume_role_policy must specify a concrete principal |
High |
| IAM008 | No NotAction in Allow statements |
Medium |
| IAM009 | No NotResource in Allow statements |
Medium |
| IAM010 | Do not attach AdministratorAccess managed policy |
High |
See STARTER_RULES.md for full documentation of each rule, including rationale, examples, and configuration options.
Add to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/iam-armor/iamarmor
rev: v0.1.1
hooks:
- id: iamarmorSee docs/pre-commit.md for details.
Add to your workflow to lint Terraform in every PR:
- name: Lint IAM policies
run: |
pip install iamarmor
iamarmor lint . --fail-on highOr pin a specific version:
- name: Lint IAM policies
run: |
pip install iamarmor==0.1.1
iamarmor lint modules/iam/ --format json > iam-findings.jsonThe CLI is the recommended entry point for most users. For embedding iamarmor in other tools, the Python API is also public:
from iamarmor import extract_from_directory, RuleEngine, load_default_rules
resources = extract_from_directory("path/to/terraform/")
engine = RuleEngine(rules=load_default_rules())
findings = engine.run(resources)
for finding in findings:
print(f"[{finding.rule_id}] {finding.severity.value.upper()} — {finding.message}")The demo GIF was recorded with VHS. To regenerate it:
# Install VHS (requires Go)
go install github.com/charmbracelet/vhs@latest
# Re-record
vhs docs/demo.tapeThe resulting docs/demo.gif is committed to the repository. The tape script
exercises iamarmor lint against the bundled tests/fixtures/ directory.
iamarmor (this repo) is the OSS linter engine. The hosted GitHub App at
iamarmor.dev (coming soon) will add:
- 🔌 GitHub App with inline PR annotations
- 📦 Premium rule packs: SOC 2, PCI-DSS, HIPAA, AWS Well-Architected Security
- 📊 Findings dashboard and trend tracking
- 🔧 One-click auto-fix suggestions
Contributions are welcome! Please open an issue before submitting a PR for new features or rules. See STARTER_RULES.md for the existing rule inventory and docs/ for design docs.
git clone https://github.com/iam-armor/iamarmor.git
cd iamarmor
pip install -e ".[dev]"
pytest
ruff check src/ tests/MIT © 2026 iam-armor
