Free plan Signups are open now. The full audytx engine — Terraform and CloudFormation — is live. The Free plan is 100 scans a month and stays free — paid tiers arrive Nov 01, 2026 from $20/month for unlimited repositories. Try it on your own code.

Terraform plan scanning (optional)

A plan resolves what static parsing cannot: final computed values, count/for_each expansion, and the resources inside modules. Hand audytx the plan and it scans with those final values folded in; where the plan and your source differ, the plan's value is used. Strictly opt-in: the normal scan keeps working as before, and if the upload fails it still stands.

Add this workflow. It authenticates with the run's GitHub OIDC token — nothing to paste, no secret to store; audytx verifies the token and scopes it to your repo automatically:

# .github/workflows/audytx-plan.yml
on: [pull_request]
permissions:
  contents: read
  id-token: write        # lets the job mint an OIDC token
jobs:
  audytx-plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init -backend=false && terraform plan -out=tf.plan && terraform show -json tf.plan > plan.json
      - name: Upload plan to audytx
        env:
          AUD: https://audytx.com
        run: |
          OIDC=$(curl -sH "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
            "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=$AUD" | jq -r .value)
          PR=$(jq -r .number "$GITHUB_EVENT_PATH")
          SHA=$(jq -r .pull_request.head.sha "$GITHUB_EVENT_PATH")
          jq -n --slurpfile p plan.json \
            --arg repo "$GITHUB_REPOSITORY" --argjson pr "$PR" --arg sha "$SHA" \
            '{repo:$repo, pr_number:$pr, head_sha:$sha, plan:$p[0]}' > body.json
          curl -sf -X POST "$AUD/plan-upload" \
            -H "Authorization: Bearer $OIDC" -H "Content-Type: application/json" \
            --data-binary @body.json

Limits: 5 MB per upload, and the request must declare its size with a Content-Length header so it can be checked before the body is read — curl sets that for you in the command above. The pr_number and head_sha you send are checked against the real pull request: it must still be open, and the commit must be the tip of its branch right now, or the upload is refused. The usual innocent cause is a branch that moved while the job ran — rerun on the new commit. The plan JSON is processed in memory and is not stored. A record of the scan (counts, not findings) is kept for 90 days (see the Privacy Policy). The PR comment notes a 🔬 plan-enhanced scan in its footer when plan data was used.

CloudFormation twin: the same enrichment exists for CloudFormation — a CI workflow POSTs DescribeChangeSet output to /changeset-upload with the same OIDC authentication. It is opt-in too, and the change set is not stored. See the CloudFormation guide for the walkthrough.