Catch infrastructure risks before they reach production.

StackGuard scans Terraform, Kubernetes, Helm, Docker and CI pipelines against policy as code, then scores every result.

Single Go binary, no daemon Apache 2.0 licensed Console, JSON, SARIF, HTML, CSV

One scanner for the whole stack

TerraformTerraform
KubernetesKubernetes
HelmHelm
Docker and ComposeDocker
GitHub ActionsActions
JenkinsJenkins
AnsibleAnsible
nginxnginx

A single pass turns files into findings.

Every file becomes a normalized resource, every rule is compiled once, and positions travel with the data so each finding points at the exact line.

CLI Discovery Parsers Engine Reporters paths files resources findings loader: embedded rules + local layers compiled rules
Everything is a Resource.Parsers emit a target, type, name and generic property tree. Rules never touch raw text.
Compiled once.Queries and regexes compile before any file is read. Evaluation is pure in-memory traversal.
Failures are contained.A file that will not parse becomes a diagnostic, not a crash. One bad file never hides the rest.

Policy as code, built for the people who run production.

No plugin SDK and no embedded scripting language. Rules are YAML, results are a number your pipeline can gate on.

Write a rule without writing Go

A rule names the resources it applies to and describes the bad condition as a query. Drop the file in a rules directory and it loads on the next scan.

id: TF_SEC_002 title: SSH open to the internet severity: ERROR target: terraform query: path: ingress.*.cidr_blocks contains: "0.0.0.0/0"

A score, not a wall of text

81/ 100
-10 per error
-3 per warning
-1 per info

Nine targets, one tool

Compose, Dockerfile, Kubernetes, Helm, Terraform, Actions, Jenkins, Ansible and nginx.

Terraform Kubernetes Docker Helm GitHub Actions nginx

Fails the build on your terms

Gate on severity, gate on score, or both. The exit code does the rest.

scan . --fail-on error \ --min-score 80

Report where you already look

Human output for the terminal, SARIF for code scanning, JSON for everything else.

console json sarif html csv

Rules

A rule on the left. The finding it produces on the right.

Rules carry the message, the reason and the fix, so the output explains itself and tells the reader what to do next.

rules/terraform/TF_SEC_001.yamlpolicy
id: TF_SEC_001
title: Public S3 bucket ACL
severity: ERROR
category: security
target: terraform
resource: [resource.aws_s3_bucket, resource.aws_s3_bucket_acl]
message: "{{ .Resource.Name }} grants a public ACL ({{ .Value }})"
remediation: |
  Use acl = "private" and enable
  aws_s3_bucket_public_access_block.
query:
  path: acl
  regex: '^(public-read|public-read-write|authenticated-read)$'
ERROR assets grants a public ACL (public-read) TF_SEC_001 prod/s3.tf:12 aws_s3_bucket.assets
Remediation Use acl = "private" and enable aws_s3_bucket_public_access_block.
Run stackguard explain TF_SEC_001

Wire it into the pipeline you already have.

One step scans, gates and uploads to GitHub code scanning. No service to run and nothing to host.

.github/workflows/stackguard.ymlci
# fail the PR on errors, and on a score under 80
- name: StackGuard
  run: >
    stackguard scan .
    --fail-on error --min-score 80
    --format sarif --output stackguard.sarif

- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: stackguard.sarif

Exit codes that mean something

Code 1 when a finding reaches your severity floor, or when the score drops below min_score.

Findings land in the PR

SARIF annotations point at the exact line, so reviewers see the issue in the diff instead of a log.

Silence noise with a reason

An inline stackguard:ignore comment suppresses a rule and the count shows up in the report.

Everything runs through one command.

Install the binary, scan a path, and reach for the sub-commands when you need them. Five commands cover the whole surface. The full reference lives in the docs.

1Install

A single static binary. No runtime and no daemon.

$ go install \ github.com/nexutils/StackGuard/cmd/stackguard@latest $ brew install nexutils/tap/stackguard > scoop bucket add nexutils \ https://github.com/nexutils/scoop-bucket > scoop install stackguard

2Scan a directory

Point it at your repo. It detects every target it knows.

$ stackguard scan .

3Gate in CI

Fail on errors, or on a score below your threshold.

$ stackguard scan . \ --fail-on error --min-score 80
scanstackguard scan [path...]

Scan files or directories for issues and emit a report.

scorestackguard score [path...]

Print the production-readiness score, and nothing else.

rulesstackguard rules

List the available rules, or validate a rule directory.

explainstackguard explain RULE_ID

Show the details, reason and remediation for one rule.

versionstackguard version

Print the StackGuard version and build information.

On every command --config --log-level -v, --verbose --no-color

Scan your stack in under a minute.

Install the binary, point it at a directory, and read the score. Add the CI step once you trust the output.

$ go install github.com/nexutils/StackGuard/cmd/stackguard@latest
$ brew install nexutils/tap/stackguard
> scoop bucket add nexutils https://github.com/nexutils/scoop-bucket && scoop install stackguard

Then: stackguard scan .