rustmaninoff 0.2.0

Fast IaC security scanner with Checkov-compatible policies
Documentation

Rustmaninoff: IaC Security Scanner

Attribute scanner for Terraform, CloudFormation, Kubernetes, and Dockerfiles. Policies are Checkov-compatible YAML and reuse published CKV ids. The engine is not a port of the Checkov Python runtime.

Built-in policies are rewritten YAML, attributed to Checkov (Bridgecrew / Palo Alto Networks, Apache-2.0).

Build

Requires Rust 1.95 or newer.

cargo build --release -p rustmaninoff
./target/release/rustmaninoff scan .

Scan

rustmaninoff scan [PATH] \
  --framework terraform,cloudformation,kubernetes,docker \
  --check CKV_AWS_3 \
  --skip-check CKV_AWS_8 \
  --output cli,json,sarif,junit \
  --fail-on HIGH \
  --external-checks-dir ./extra

Exit codes: 0 when nothing fails the threshold, 1 when a finding is at or above --fail-on (default HIGH) or a file fails to parse, 2 on usage errors. --soft-fail always exits 0.

Interpolations (${...}, Fn::*, !Ref, !GetAtt) are unknown. Unknown results do not fail the process. Pass --show-unknown to print them.

Inline skip: # checkov:skip=CKV_AWS_3:reason. Kubernetes annotation value: checkov.io/skip: CKV_K8S_16=reason.

Optional .rustmaninoff.yaml:

frameworks: [terraform, cloudformation, kubernetes, docker]
skip_checks: []
fail_on: HIGH
excluded_paths: []
external_checks_dirs: []
show_unknown: false
compact: false

Directories named .git, .terraform, .terragrunt-cache, node_modules, vendor, and target are skipped. Symbolic links are not followed. Files larger than 10 MB, and files past the nesting or YAML-alias limits, are reported as diagnostics and are not parsed.

v0.2 scope

  • Terraform .tf and .tf.json managed resource blocks and data sources. Data sources are emitted as IR resources with kind data and type data.TYPE so policies can target them. No module download and no full HCL evaluation.
  • CloudFormation YAML and JSON Resources. Attribute paths are relative to Properties.
  • Kubernetes multi-document YAML, including List.
  • Dockerfiles (Dockerfile, Containerfile, *.dockerfile): FROM, USER, ADD vs COPY, HEALTHCHECK, and privileged-ish RUN patterns.
  • 181 built-in checks (94 Terraform, 51 CloudFormation, 32 Kubernetes, 4 Docker). Each check has a pass fixture and a fail fixture.
  • Text, JSON, SARIF 2.1.0, and JUnit reports.

S3 encryption, versioning, and logging on current Terraform target aws_s3_bucket_server_side_encryption_configuration, aws_s3_bucket_versioning, and aws_s3_bucket_logging. CKV_AWS_286 matches a static action subset, including * and *:*. CKV_K8S_14 accepts a digest or a tag other than latest; an image whose last colon is a registry port and which has no tag is treated as pinned.

Not in v0.2: graph checks (CKV2_*), Terraform plan JSON, remote modules, Helm, Kustomize, secrets scanning, full variable evaluation, and cfn-lint resource-spec validation.

Policy dialect

A check definition is the pass condition. Operators: equals, not_equals, exists, not_exists, contains, not_contains, within, regex_match, starting_with, ending_with, numeric comparisons, is_true, is_false, is_empty, length_greater_than, length_less_than, and their negated forms. Combinators: and, or, not.

Extensions: no_element, forbid_resource, equals_any, intersects, image_tag_pinned, and missing: pass|fail|unknown. scope is ignored. Severity defaults to MEDIUM when omitted.

Benchmark

Against Checkov and Trivy

Wall-clock time of each CLI on one synthetic corpus, Apple M2, macOS 14.8. Median of three runs after a warmup. Stdout was discarded. The corpus is 40 Terraform files (1,080 resources), 20 CloudFormation files (300 resources), and 20 Kubernetes files (160 resources).

Scanner Full corpus Terraform CloudFormation Kubernetes
Rustmaninoff 0.2.0 20 ms 11 ms 9 ms 11 ms
Checkov 3.3.21 4.51 s 3.72 s 2.71 s 2.92 s
Trivy 0.74.0 5.71 s 2.67 s 1.29 s 2.59 s

On the full corpus that is about 225 times the Rustmaninoff time for Checkov, and about 285 times for Trivy. The catalogs are not the same: Rustmaninoff runs 181 attribute checks, Checkov runs its built-in checks for the selected frameworks, and Trivy runs its misconfiguration policies.

%%{init: {"themeVariables": {"xyChart": {"plotColorPalette": "#E07A3D, #2A9D8F, #3D5A80", "titleColor": "#C44536", "xAxisLineColor": "#E07A3D", "yAxisLineColor": "#2A9D8F", "xAxisTickColor": "#E9C46A", "yAxisTickColor": "#7B6CF6"}}}}%%
xychart-beta
    title "CLI wall time on the full corpus"
    x-axis [Rustmaninoff, Checkov, Trivy]
    y-axis "seconds" 0 --> 6
    bar "Rustmaninoff" [0.02, 0, 0]
    bar "Checkov" [0, 4.51, 0]
    bar "Trivy" [0, 0, 5.71]

Copper is Rustmaninoff, teal is Checkov, and steel blue is Trivy.

%%{init: {"themeVariables": {"xyChart": {"plotColorPalette": "#E07A3D, #2A9D8F, #E9C46A, #3D5A80, #C44536, #7B6CF6", "titleColor": "#C44536", "xAxisLineColor": "#E07A3D", "yAxisLineColor": "#2A9D8F", "xAxisTickColor": "#E9C46A", "yAxisTickColor": "#7B6CF6"}}}}%%
xychart-beta
    title "Times slower than Rustmaninoff"
    x-axis [Terraform, CloudFormation, Kubernetes]
    y-axis "times slower" 0 --> 360
    bar "Checkov" [345, 288, 263]
    bar "Trivy" [247, 137, 234]

Copper is Checkov. Teal is Trivy.

Commands, release binary versus the other CLIs:

rustmaninoff scan CORPUS --soft-fail --compact
checkov -d CORPUS --framework terraform cloudformation kubernetes --quiet --compact --soft-fail
trivy config --quiet --skip-check-update CORPUS

Engine stages

Release build, same synthetic corpus, Apple M2. Findings were 9,476. These times are in-process. They do not include CLI startup or report formatting, which is why they are lower than the CLI rows above.

Stage Time
Terraform, 40 files, 1,080 resources 13.3 ms
Terraform, those files in parallel 2.7 ms
One Terraform file, 400 resources 3.2 ms
CloudFormation, 20 files, 300 resources 2.8 ms
Kubernetes, 20 files, 160 resources 4.3 ms
Full builtin pack on 1,540 resources 7.9 ms
CKV_AWS_3 on 2,000 volumes 2.06 ms
Attribute lookup, 200,000 single keys 5.9 ms
%%{init: {"themeVariables": {"xyChart": {"plotColorPalette": "#E07A3D, #2A9D8F, #3D5A80, #E9C46A, #7B6CF6", "titleColor": "#C44536", "xAxisLineColor": "#E07A3D", "yAxisLineColor": "#2A9D8F", "xAxisTickColor": "#E9C46A", "yAxisTickColor": "#7B6CF6"}}}}%%
xychart-beta
    title "In-process stage time"
    x-axis ["TF", "TF parallel", "TF 400", "CFN", "K8s"]
    y-axis "milliseconds" 0 --> 16
    bar "TF" [13.3, 0, 0, 0, 0]
    bar "TF parallel" [0, 2.7, 0, 0, 0]
    bar "TF 400" [0, 0, 3.2, 0, 0]
    bar "CFN" [0, 0, 0, 2.8, 0]
    bar "K8s" [0, 0, 0, 0, 4.3]

Builtin YAML is parsed once per process (about 6 ms) and reused. Repeat the stage measurement with cargo run --release -p rustmaninoff --example stages.

Install

cargo install rustmaninoff --locked
rustmaninoff scan .

Release

Pushing the tag v0.2.0 runs .github/workflows/release.yml. It publishes Linux and macOS binaries for amd64 and arm64, each with a SHA-256 checksum.

git tag v0.2.0
git push origin v0.2.0
- uses: actions/checkout@v4
- run: cargo install --path crates/cli --locked
- run: rustmaninoff scan . --fail-on HIGH --output sarif --sarif-file rustmaninoff.sarif

License

Apache-2.0. See LICENSE.