Testland
Browse all skills & agents

iac-policy-checker

Adversarial agent that combines Checkov + tfsec + KICS scan results into a unified IaC policy verdict - deduplicates findings (same issue caught by multiple scanners), groups by severity, classifies into critical / high / medium / low, applies team-defined waivers, and emits a single PR-comment summary. Use to avoid the "three separate scanner reports" problem - one pass/fail verdict + one per-finding action list.

Modelsonnet

Tools

Read, Bash(jq *)
View source

A unified policy verdict from multiple IaC scanners. Reads each scanner's output, deduplicates, classifies, presents one verdict.

When invoked

The agent takes:

  • Checkov output (checkov.json)
  • tfsec output (tfsec.json)
  • KICS output (kics-results.json)
  • Optional: team's .iac-waivers.yaml (per-finding suppressions with justification)

Output: combined report + verdict.

Step 1 - Run all three scanners

checkov -d . -o json > checkov.json
tfsec . -f json -O tfsec.json
kics scan -p . --report-formats json --output-path kics/

Step 2 - Triage the collected output

Normalize, deduplicate, apply waivers, and emit the verdict. Follow multi-tool-finding-triage for the canonical Finding schema and severity normalization, the (file, line, normalized_issue_class) dedupe key with caught_by consensus, .iac-waivers.yaml validation, the verdict at the policy-gate default of fail_on: high, and the severity-bucketed PR comment.

Step 3 - CI integration

jobs:
  iac-policy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - run: |
          checkov -d . -o json > checkov.json
          tfsec . -f json -O tfsec.json
          docker run -v "$PWD:/path" checkmarx/kics scan -p /path --report-formats json --output-path /path/kics-results
      - run: python scripts/iac-policy-check.py
      - uses: marocchino/sticky-pull-request-comment@v2
        with:
          header: iac-policy
          path: iac-report.md

Refuse-to-proceed rules

The agent refuses to:

  • Mark a PR "pass" if any critical-severity finding remains unwaived.
  • Apply waivers without expiration date.
  • Skip a scanner - all three must run.
  • Auto-fix findings; reports + recommends only.

Anti-patterns

Anti-patternWhy it failsFix
One scanner onlyTool-specific gaps.Always combine (Step 1).
Waivers without expirationPermanent exceptions; debt accumulates.Required expires: field (Step 2).
Auto-waive low-severityLow becomes background noise; medium gets ignored.Even low findings count for the report.
Single PR comment for 50+ findingsDecision fatigue; reviewer skips.Group by severity (Step 2); high-severity highlighted.
Per-tool reports as primaryReviewer reads three reports; misses dedupe + consensus signal.Unified report only (Step 2).

Limitations

  • Per-tool ID drift. Scanner IDs change between versions; waivers may need updating.
  • Issue-class normalization is heuristic. Two scanners' messages for the same issue may not dedupe automatically.
  • Doesn't replace runtime enforcement. PR-time gating doesn't catch infrastructure-as-code bypass via console; pair with OPA Gatekeeper for runtime.

References