Audit rules reference
This is the reference for every rule chant audit can report. Each finding in a report links to its rule here.
Each rule is tagged with its tier — merge-worthy (a security or correctness issue worth a PR) or report-only (hygiene) — and its fix kind — deterministic (a safe mechanical fix the report can apply as a diff) or guidance (needs a judgement call). Where an open-source tool checks the same thing, the rule says so under Prior art; the Prior art section at the end lists every tool the rules on this page credit.
GitHub Actions (GHA)
Section titled “GitHub Actions (GHA)”Also applied to Forgejo workflows, which are GitHub-dialect.
GHA006
Section titled “GHA006”Duplicate workflow name — report-only · guidance
Give each workflow a unique name:.
GHA009
Section titled “GHA009”Empty matrix dimension — merge-worthy · guidance
Remove the empty matrix axis or give it values; an empty axis produces zero jobs.
| Prior art | actionlint Unexpected empty mappings (overlaps) |
GHA011
Section titled “GHA011”needs references a non-existent job — merge-worthy · guidance
Fix the needs: target to name a real job.
| Prior art | actionlint Job dependencies validation (equivalent) |
GHA013
Section titled “GHA013”Missing job permissions on a sensitive trigger — merge-worthy · guidance
Add an explicit least-privilege permissions: block to jobs under pull_request_target/workflow_dispatch.
| Authority | OSSF Scorecard — Token-Permissions · GitHub — Automatic token authentication |
| Prior art | poutine default_permissions_on_risky_events (overlaps) · zizmor excessive-permissions (overlaps) · OpenSSF Scorecard Token-Permissions (overlaps) |
GHA017
Section titled “GHA017”No explicit permissions block — merge-worthy · deterministic
Add a top-level permissions: \{ contents: read } and widen only where a job needs it.
| Authority | OSSF Scorecard — Token-Permissions · GitHub — Automatic token authentication |
| Prior art | zizmor excessive-permissions (overlaps) · OpenSSF Scorecard Token-Permissions (overlaps) |
GHA018
Section titled “GHA018”pull_request_target checks out untrusted code — merge-worthy · guidance
Don’t check out / run PR head code under pull_request_target; split into a privileged + unprivileged workflow.
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | OpenSSF Scorecard Dangerous-Workflow (overlaps) · octoscan dangerous-checkout (overlaps) · poutine untrusted_checkout_exec (overlaps) |
GHA019
Section titled “GHA019”Circular needs chain — merge-worthy · guidance
Break the cycle in the job dependency graph.
| Prior art | actionlint Job dependencies validation (equivalent) |
GHA021
Section titled “GHA021”actions/checkout not pinned to a SHA — merge-worthy · deterministic
Pin actions/checkout to a full 40-char commit SHA.
| Authority | OSSF Scorecard — Pinned-Dependencies · GitHub — Using third-party actions |
| Prior art | zizmor unpinned-uses (overlaps) · OpenSSF Scorecard Pinned-Dependencies (overlaps) |
GHA022
Section titled “GHA022”Job without timeout-minutes — report-only · guidance
Add timeout-minutes: to bound runaway jobs.
GHA023
Section titled “GHA023”Deprecated ::set-output — report-only · guidance
Replace ::set-output with $GITHUB_OUTPUT.
| Prior art | actionlint Check deprecated workflow commands (overlaps) |
GHA024
Section titled “GHA024”Missing concurrency block — report-only · guidance
Add a concurrency: group to deploy workflows.
| Prior art | zizmor concurrency-limits (overlaps) |
GHA025
Section titled “GHA025”Unrestricted pull_request_target — merge-worthy · guidance
Gate pull_request_target jobs and avoid running untrusted code with elevated scope.
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | zizmor dangerous-triggers (overlaps) |
GHA026
Section titled “GHA026”Secret used without environment protection — report-only · guidance
Move secret-consuming jobs behind a protected environment:.
| Prior art | zizmor secrets-outside-env (equivalent) |
GHA027
Section titled “GHA027”Cleanup step without if: always() — report-only · guidance
Add if: always() to cleanup steps.
GHA028
Section titled “GHA028”Workflow with no triggers — merge-worthy · guidance
Add an on: trigger; the workflow never runs without one.
| Prior art | actionlint Missing required keys and key duplicates (overlaps) |
GHA029
Section titled “GHA029”Action not pinned to a commit SHA — merge-worthy · deterministic
Pin the action to a full commit SHA instead of a tag/branch.
| Authority | OSSF Scorecard — Pinned-Dependencies · GitHub — Using third-party actions |
| Prior art | zizmor unpinned-uses (overlaps) · OpenSSF Scorecard Pinned-Dependencies (overlaps) |
GHA030
Section titled “GHA030”Container image not pinned to a digest — merge-worthy · deterministic
Pin the image to an immutable @sha256: digest.
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | zizmor unpinned-images (overlaps) |
GHA031
Section titled “GHA031”Possible action impersonation — merge-worthy · guidance
Verify the action owner/slug; it resembles a well-known action.
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | zizmor typosquat-uses (equivalent) |
GHA032
Section titled “GHA032”Archived/abandoned or vulnerable action — merge-worthy · guidance
Replace the archived action or one with a disclosed security issue.
| Prior art | zizmor archived-uses (overlaps) · zizmor known-vulnerable-actions (overlaps) |
GHA033
Section titled “GHA033”Blanket write-all permissions — merge-worthy · deterministic
Replace write-all with the specific scopes the jobs need (default contents: read).
| Authority | OSSF Scorecard — Token-Permissions · GitHub — Automatic token authentication |
| Prior art | zizmor excessive-permissions (overlaps) · OpenSSF Scorecard Token-Permissions (overlaps) |
GHA034
Section titled “GHA034”Write permissions granted workflow-wide — merge-worthy · guidance
Move write scopes to the single job that needs them; keep the workflow least-privilege.
| Authority | OSSF Scorecard — Token-Permissions · GitHub — Automatic token authentication |
| Prior art | zizmor excessive-permissions (overlaps) · OpenSSF Scorecard Token-Permissions (overlaps) |
GHA035
Section titled “GHA035”Elevated token on an untrusted-code trigger — merge-worthy · guidance
Drop the elevated permissions: on triggers that can run untrusted code.
| Authority | GitHub Security Lab — Preventing pwn requests · OSSF Scorecard — Token-Permissions |
GHA036
Section titled “GHA036”Untrusted input interpolated into run: — merge-worthy · guidance
Pass untrusted $\{\{ }} values via an env: var and reference "$VAR", never inline in the script.
| Authority | GitHub — Understanding the risk of script injections |
| Prior art | zizmor template-injection (equivalent) · poutine injection (equivalent) · actionlint Script injection by potentially untrusted inputs (equivalent) · octoscan expression-injection (equivalent) · OpenSSF Scorecard Dangerous-Workflow (overlaps) |
GHA037
Section titled “GHA037”Untrusted input written to GITHUB_ENV/GITHUB_PATH — merge-worthy · guidance
Don’t write untrusted input to $GITHUB_ENV/$GITHUB_PATH; sanitize or avoid.
| Authority | GitHub — Understanding the risk of script injections |
| Prior art | zizmor github-env (equivalent) · octoscan dangerous-write (overlaps) |
GHA038
Section titled “GHA038”workflow_run checks out untrusted code in a privileged context — merge-worthy · guidance
Avoid checking out untrusted code under workflow_run; treat it as privileged.
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | OpenSSF Scorecard Dangerous-Workflow (overlaps) · octoscan dangerous-checkout (overlaps) |
GHA039
Section titled “GHA039”Auth gate on a spoofable author field — merge-worthy · guidance
Gate on a non-spoofable identity, not a commit-author field.
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | zizmor bot-conditions (overlaps) · octoscan bot-check (overlaps) · poutine confused_deputy_auto_merge (overlaps) |
GHA040
Section titled “GHA040”Self-hosted runner on an untrusted-code trigger — merge-worthy · guidance
Don’t run untrusted-code triggers on self-hosted runners.
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | poutine pr_runs_on_self_hosted (equivalent) · zizmor self-hosted-runner (overlaps) · octoscan runner-label (overlaps) |
GHA041
Section titled “GHA041”Blanket secrets: inherit — merge-worthy · guidance
Pass only the specific secrets the reusable workflow needs.
| Authority | GitHub — Using secrets in GitHub Actions |
| Prior art | zizmor secrets-inherit (equivalent) |
GHA042
Section titled “GHA042”Entire secrets context passed — merge-worthy · guidance
Pass named secrets instead of the whole secrets context.
| Authority | GitHub — Using secrets in GitHub Actions |
| Prior art | zizmor overprovisioned-secrets (equivalent) · poutine job_all_secrets (equivalent) |
GHA043
Section titled “GHA043”Secret consumed without an environment gate — merge-worthy · guidance
Put secret-consuming jobs behind a protected environment.
| Authority | GitHub — Using secrets in GitHub Actions |
| Prior art | zizmor secrets-outside-env (equivalent) |
GHA044
Section titled “GHA044”Hardcoded registry/container credential — merge-worthy · guidance
Remove the hardcoded credential, move it to a secret, and rotate it (responsible disclosure first).
| Authority | GitHub — Using secrets in GitHub Actions |
| Prior art | zizmor hardcoded-container-credentials (equivalent) · actionlint Hardcoded credentials (equivalent) · octoscan credentials (equivalent) |
GHA045
Section titled “GHA045”Secret interpolated into run: — merge-worthy · guidance
Reference secrets via env:, not inline in the shell command.
| Authority | GitHub — Understanding the risk of script injections · GitHub — Using secrets in GitHub Actions |
GHA046
Section titled “GHA046”Constant/unsound guard condition — merge-worthy · guidance
Fix the always-true/false if: — it may neutralize a security gate.
| Prior art | actionlint Constant conditions at if:“ (equivalent) · zizmor unsound-condition (overlaps) · poutine if_always_true (overlaps) |
GHA047
Section titled “GHA047”Ineffective contains() guard (reversed args) — merge-worthy · guidance
Swap the contains() arguments so the guard actually filters.
| Prior art | zizmor unsound-contains (equivalent) |
GHA048
Section titled “GHA048”Obfuscated guard condition — merge-worthy · guidance
Simplify the indirect if: so its effect is reviewable.
| Prior art | zizmor obfuscation (overlaps) |
GHA049
Section titled “GHA049”Persisted checkout credentials reachable by an artifact — merge-worthy · guidance
Use persist-credentials: false or exclude .git from uploaded artifacts.
| Authority | GitHub — Using secrets in GitHub Actions |
| Prior art | zizmor artipacked (equivalent) · octoscan dangerous-artefact (overlaps) |
GHA050
Section titled “GHA050”Cache populated in a privileged context — merge-worthy · guidance
Don’t populate caches from untrusted code paths (poisoning risk).
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | zizmor cache-poisoning (overlaps) |
GHA051
Section titled “GHA051”Long-lived token instead of OIDC — report-only · guidance
Migrate publish/release to OIDC short-lived credentials.
| Prior art | zizmor use-trusted-publishing (overlaps) |
GHA052
Section titled “GHA052”Software piped to a shell without verification — merge-worthy · guidance
Verify a checksum/signature before executing fetched scripts.
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | poutine unverified_script_exec (equivalent) · OpenSSF Scorecard Pinned-Dependencies (overlaps) |
GHA053
Section titled “GHA053”Re-enables unsafe set-env/add-path — merge-worthy · guidance
Remove ACTIONS_ALLOW_UNSECURE_COMMANDS; use $GITHUB_ENV/$GITHUB_PATH.
| Authority | GitHub — Understanding the risk of script injections |
| Prior art | zizmor insecure-commands (equivalent) · octoscan unsecure-commands (equivalent) |
GHA054
Section titled “GHA054”Feature with a known security footgun — merge-worthy · guidance
Replace the flagged feature with the safe alternative.
| Prior art | zizmor misfeature (overlaps) |
GHA055
Section titled “GHA055”Runtime install of a tool already on the runner — report-only · guidance
Drop the redundant install to save time.
| Prior art | zizmor superfluous-actions (overlaps) |
GHA056
Section titled “GHA056”Workflow without a name — report-only · guidance
Add a name: to the workflow.
| Prior art | zizmor anonymous-definition (overlaps) |
GHA057
Section titled “GHA057”Dependency update can execute untrusted code — merge-worthy · guidance
Disable the option that lets dependency updates run external code.
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | zizmor dependabot-execution (equivalent) |
GHA058
Section titled “GHA058”Dependency update has no cooldown window — report-only · guidance
Add a cooldown so new releases aren’t merged instantly.
| Prior art | zizmor dependabot-cooldown (equivalent) |
GHA059
Section titled “GHA059”Stale or missing pin annotation — merge-worthy · guidance
Add or correct the trailing version comment on the SHA-pinned reference so it matches the digest.
| Authority | OSSF Scorecard — Pinned-Dependencies · GitHub — Using third-party actions |
| Prior art | zizmor ref-version-mismatch (equivalent) |
GHA060
Section titled “GHA060”Over-scoped generated token — merge-worthy · guidance
Narrow the GitHub App token’s permission-* inputs to the scopes its consuming steps actually use, or remove the unused ones.
| Authority | OSSF Scorecard — Token-Permissions · GitHub — Automatic token authentication |
| Prior art | zizmor github-app (overlaps) |
GHA061
Section titled “GHA061”Action reference outside the configured usage policy — merge-worthy · guidance
Replace the reference with one from the approved allowlist, or get it added if it should be trusted.
| Prior art | zizmor forbidden-uses (equivalent) |
GHA062
Section titled “GHA062”Pinned reference matches a known-vulnerability advisory — merge-worthy · guidance
Bump the reference to a patched ref/commit named by the advisory.
| Authority | OSSF Scorecard — Vulnerabilities |
| Prior art | zizmor known-vulnerable-actions (equivalent) · poutine known_vulnerability_in_build_component (equivalent) · octoscan known-vulnerability (equivalent) · OpenSSF Scorecard Vulnerabilities (overlaps) |
GHA063
Section titled “GHA063”Dependency setup action without caching enabled — report-only · guidance
Enable the setup action’s cache: option or add an actions/cache step.
GHA064
Section titled “GHA064”Expensive runner without justification — report-only · guidance
Confirm the job needs that OS, or move it to a Linux runner.
GHA065
Section titled “GHA065”Unbounded matrix fan-out — report-only · guidance
Trim the matrix with include/exclude, or cap it with max-parallel.
GHA066
Section titled “GHA066”Unbounded artifact retention — report-only · guidance
Set a retention-days sized to how long the artifact is actually needed.
GHA067
Section titled “GHA067”Unconditional heavy step with no path filter — report-only · guidance
Scope the trigger’s paths, or add an if: guard to the step.
GHA068
Section titled “GHA068”Pull-request workflow missing a concurrency group — report-only · guidance
Add a concurrency group with cancel-in-progress: true.
| Prior art | zizmor concurrency-limits (overlaps) |
GitLab CI (WGL)
Section titled “GitLab CI (WGL)”WGL010
Section titled “WGL010”Job references an undefined stage — merge-worthy · guidance
Add the stage to stages: or fix the job’s stage:.
| Prior art | GitLab CI/CD YAML reference stage: supported values are the default stages or stages listed in stages“ (equivalent) |
WGL011
Section titled “WGL011”Job rules always evaluate to never — merge-worthy · guidance
Fix the rules: so the job can run; it is currently unreachable.
WGL012
Section titled “WGL012”Deprecated property — report-only · guidance
Replace the deprecated GitLab CI property.
| Prior art | GitLab CI/CD YAML reference Deprecated keywords (only/except, globally-defined image/services/cache/before_script/after_script) (equivalent) |
WGL013
Section titled “WGL013”Invalid needs target — merge-worthy · guidance
Fix the dangling/self needs: reference.
| Prior art | GitLab CI/CD YAML reference Error: 'job' does not exist in the pipeline (needs) (equivalent) |
WGL014
Section titled “WGL014”Invalid extends target — merge-worthy · guidance
Point extends: at a template that exists in the pipeline.
| Prior art | GitLab CI/CD YAML reference extends: supported values are the name(s) of another job in the pipeline (equivalent) |
WGL015
Section titled “WGL015”Circular needs chain — merge-worthy · guidance
Break the cycle in the job dependency graph.
WGL016
Section titled “WGL016”Hardcoded secret in variables — merge-worthy · guidance
Move the secret out of variables: into a masked/protected CI variable and rotate it.
| Authority | GitHub — Using secrets in GitHub Actions |
| Prior art | GitLab CI/CD YAML reference CI/CD variable security (secrets belong in masked/protected variables, not in .gitlab-ci.yml) (overlaps) |
WGL017
Section titled “WGL017”Insecure (non-HTTPS) registry — merge-worthy · guidance
Use an HTTPS registry endpoint.
WGL018
Section titled “WGL018”Missing job timeout — report-only · guidance
Add a timeout: to bound long-running jobs.
WGL019
Section titled “WGL019”Missing retry on deploy job — report-only · guidance
Add a retry: strategy to deploy jobs.
WGL020
Section titled “WGL020”Duplicate job names — merge-worthy · guidance
Rename so each job resolves to a unique name.
WGL021
Section titled “WGL021”Unused global variable — report-only · guidance
Remove the unused global variables: entry.
WGL022
Section titled “WGL022”Missing artifacts expiry — report-only · guidance
Add expire_in: to artifacts to avoid disk bloat.
WGL023
Section titled “WGL023”Overly broad rules (when: always) — report-only · guidance
Add real conditions to the job’s rules:.
| Prior art | GitLab CI/CD YAML reference Pipeline warning: Job may allow multiple pipelines to run for a single action (final when rule without conditions) (overlaps) |
WGL024
Section titled “WGL024”Manual job without allow_failure — report-only · guidance
Add allow_failure: true so a manual job doesn’t block the pipeline.
| Prior art | GitLab CI/CD YAML reference allow_failure default: true for manual jobs, false for rules:when: manual (overlaps) |
WGL025
Section titled “WGL025”Cache without a key — report-only · guidance
Add a cache.key to avoid cross-job cache collisions.
| Prior art | GitLab CI/CD YAML reference cache:key: all jobs with cachebut nocache:keyshare thedefault cache (overlaps) |
WGL026
Section titled “WGL026”Privileged DinD service without TLS — merge-worthy · guidance
Set DOCKER_TLS_CERTDIR for privileged Docker-in-Docker services.
| Prior art | GitLab CI/CD YAML reference Docker-in-Docker with TLS enabled (recommended); DOCKER_TLS_CERTDIR (overlaps) |
WGL027
Section titled “WGL027”Empty script — merge-worthy · guidance
Give the job a non-empty script:; it currently does nothing.
WGL028
Section titled “WGL028”Redundant needs — report-only · guidance
Drop needs: already implied by stage ordering.
WGL029
Section titled “WGL029”include/component resolved by a moving ref — merge-worthy · guidance
Pin include:project/component to a tag or commit SHA, not a branch.
WGL030
Section titled “WGL030”Insecure or mutable include:remote — merge-worthy · guidance
Use HTTPS and pin the remote include to an immutable ref.
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | GitLab CI/CD YAML reference include:remote: treat as a third-party dependency; verify integrity with include:integrity (overlaps) |
WGL031
Section titled “WGL031”Container image not pinned to a digest — merge-worthy · deterministic
Pin the image to an immutable @sha256: digest.
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | GitLab CI/CD YAML reference Use checksum to keep your image secure (image@sha256:digest) (overlaps) |
WGL032
Section titled “WGL032”Possible include/component impersonation — merge-worthy · guidance
Verify the include source; it resembles a well-known project.
| Authority | OSSF Scorecard — Pinned-Dependencies |
WGL033
Section titled “WGL033”OIDC id_token without a scoped audience — merge-worthy · guidance
Set a specific aud: on the OIDC id_token.
| Authority | GitHub — Security hardening with OpenID Connect |
| Prior art | GitLab CI/CD YAML reference id_tokens: the required aud sub-keyword configures the aud claim (overlaps) |
WGL034
Section titled “WGL034”OIDC id_token mintable from a merge-request pipeline — merge-worthy · guidance
Restrict OIDC token minting to protected pipelines.
| Authority | GitHub — Security hardening with OpenID Connect · GitHub Security Lab — Preventing pwn requests |
WGL035
Section titled “WGL035”Untrusted CI variable interpolated into a script — merge-worthy · guidance
Pass untrusted variables via the environment and quote them; don’t inline.
| Authority | GitHub — Understanding the risk of script injections |
| Prior art | poutine injection (overlaps) |
WGL036
Section titled “WGL036”Privileged service reachable from merge-request pipelines — merge-worthy · guidance
Block privileged/DinD services on merge-request pipelines.
| Authority | GitHub Security Lab — Preventing pwn requests |
WGL037
Section titled “WGL037”Security gate on an untrusted ref regex — merge-worthy · guidance
Don’t gate security decisions on a regex over an untrusted ref variable.
| Authority | GitHub Security Lab — Preventing pwn requests |
WGL038
Section titled “WGL038”Secret reachable from a merge-request pipeline — merge-worthy · guidance
Scope secret-like variables to protected branches/pipelines.
WGL039
Section titled “WGL039”Secret printed to job logs — merge-worthy · guidance
Stop echoing the secret-like variable; mask it.
| Authority | GitHub — Using secrets in GitHub Actions |
| Prior art | GitLab CI/CD YAML reference CI/CD variable security: accidental-leak-job example (echo of $PASSWORD); mask sensitive variables (overlaps) |
WGL040
Section titled “WGL040”Hardcoded credential in a registry login — merge-worthy · guidance
Move the credential to a masked CI variable and rotate it.
| Authority | GitHub — Using secrets in GitHub Actions |
WGL041
Section titled “WGL041”Tautological rules:if condition — merge-worthy · guidance
Fix the always-true rules:if; it may neutralize a gate.
WGL042
Section titled “WGL042”Unreachable rules after an unconditional match — report-only · guidance
Remove the dead rules: entries after the catch-all.
WGL043
Section titled “WGL043”Match-anything regex gate in rules:if — merge-worthy · guidance
Tighten the regex; a match-anything gate is no gate.
| Authority | GitHub Security Lab — Preventing pwn requests |
WGL044
Section titled “WGL044”Public artifacts expose build output — merge-worthy · guidance
Mark sensitive artifacts non-public (public: false).
| Prior art | GitLab CI/CD YAML reference artifacts:public (default true: downloadable by anonymous users in public pipelines) (overlaps) |
WGL045
Section titled “WGL045”Artifact path may capture a credential file — merge-worthy · guidance
Narrow the artifact path so it can’t capture credential files.
| Authority | GitHub — Using secrets in GitHub Actions |
WGL046
Section titled “WGL046”Cache populated in a merge-request pipeline — merge-worthy · guidance
Don’t populate caches from merge-request pipelines (poisoning risk).
| Authority | GitHub Security Lab — Preventing pwn requests |
| Prior art | GitLab CI/CD YAML reference Cache key names: protected and non-protected branches do not share the cache by default (overlaps) |
WGL047
Section titled “WGL047”Software piped to a shell without verification — merge-worthy · guidance
Verify a checksum/signature before executing fetched scripts.
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | poutine unverified_script_exec (equivalent) |
WGL048
Section titled “WGL048”Pipeline without workflow:name — report-only · guidance
Add a workflow:name for clearer pipeline naming.
| Prior art | GitLab CI/CD YAML reference Use pipeline names (workflow:name) (overlaps) |
WGL049
Section titled “WGL049”Dependency install without a cache — report-only · guidance
Add a cache: covering the dependency directory.
WGL050
Section titled “WGL050”Merge-request job missing interruptible — report-only · guidance
Add interruptible: true so a superseded pipeline can be cancelled.
Forgejo (WFJ)
Section titled “Forgejo (WFJ)”WFJ010
Section titled “WFJ010”Unresolved action reference on Forgejo — merge-worthy · guidance
Use an action reference Forgejo can resolve (full URL or a mirrored action).
WFJ011
Section titled “WFJ011”GitHub-hosted runner label with no Forgejo equivalent — merge-worthy · guidance
Use a runner label your Forgejo instance provides.
Kubernetes (WK8 / ARGO / FLUX)
Section titled “Kubernetes (WK8 / ARGO / FLUX)”Run against Kubernetes manifests.
ARGO002
Section titled “ARGO002”Argo Application references an undeclared AppProject — merge-worthy · guidance
Declare the named AppProject or reference an existing project.
ARGO003
Section titled “ARGO003”Argo Application targets an unregistered cluster — merge-worthy · guidance
Point spec.destination at a registered cluster or the in-cluster target.
ARGO005
Section titled “ARGO005”Argo source.path may not resolve — report-only · guidance
Ensure the source path exists under the build root.
FLUX002
Section titled “FLUX002”Flux Kustomization references an undeclared source — merge-worthy · guidance
Declare the GitRepository/OCIRepository/Bucket, or point sourceRef at the bootstrap flux-system repo.
| Prior art | Flux Kustomization API reference .spec.sourceRef (overlaps) |
FLUX003
Section titled “FLUX003”Flux Kustomization dependsOn names an undeclared Kustomization — report-only · guidance
Fix the dependsOn name, or ignore if the dependency is declared in another repo.
| Prior art | Flux Kustomization API reference .spec.dependsOn (overlaps) |
WK8005
Section titled “WK8005”Hardcoded secret in env var — merge-worthy · guidance
Use a secretKeyRef instead of a literal value, and rotate the secret.
| Authority | Kubernetes — Good practices for Secrets |
| Prior art | Fairwinds Polaris sensitiveContainerEnvVar (overlaps) · KubeLinter env-var-secret (overlaps) |
WK8006
Section titled “WK8006”Image uses :latest or no tag — merge-worthy · guidance
Pin the image to an explicit version tag (ideally a digest).
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | KubeLinter latest-tag (equivalent) · Fairwinds Polaris tagNotSpecified (equivalent) · Checkov CKV_K8S_14 (equivalent) |
WK8041
Section titled “WK8041”Hardcoded API key in env var — merge-worthy · guidance
Move the key to a Secret and rotate it.
| Authority | Kubernetes — Good practices for Secrets |
| Prior art | Fairwinds Polaris sensitiveContainerEnvVar (overlaps) · KubeLinter env-var-secret (overlaps) · Datree prevent-exposed-secrets-aws (overlaps) |
WK8042
Section titled “WK8042”Private key stored in a ConfigMap — merge-worthy · guidance
Store private keys in a Secret, not a ConfigMap.
| Authority | Kubernetes — Good practices for Secrets |
| Prior art | Fairwinds Polaris sensitiveConfigmapContent (overlaps) · Datree prevent-exposed-secrets-privatekey (overlaps) |
WK8101
Section titled “WK8101”Deployment selector does not match template labels — merge-worthy · guidance
Align spec.selector with the pod template labels.
| Prior art | KubeLinter mismatching-selector (equivalent) · kube-score deployment-pod-selector-labels-match-template-metadata-labels (equivalent) |
WK8102
Section titled “WK8102”Resource missing metadata labels — report-only · guidance
Add metadata labels for filtering and tooling.
WK8103
Section titled “WK8103”Container missing name — merge-worthy · guidance
Add the required container name.
WK8104
Section titled “WK8104”Container ports not named — report-only · guidance
Name ports for clearer Service/NetworkPolicy config.
WK8105
Section titled “WK8105”imagePullPolicy not explicit — report-only · guidance
Set imagePullPolicy explicitly to avoid surprising defaults.
| Prior art | Fairwinds Polaris pullPolicyNotAlways (overlaps) · kube-score container-image-pull-policy (overlaps) · Checkov CKV_K8S_15 (overlaps) |
WK8201
Section titled “WK8201”Container missing resource limits — report-only · guidance
Set CPU and memory limits.
| Prior art | Fairwinds Polaris cpuLimitsMissing (overlaps) · Checkov CKV_K8S_13 (overlaps) · kube-score container-resources (overlaps) |
WK8202
Section titled “WK8202”Privileged container — merge-worthy · guidance
Remove privileged: true; grant only the specific capabilities needed.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | KubeLinter privileged-container (equivalent) · Fairwinds Polaris runAsPrivileged (equivalent) · Checkov CKV_K8S_16 (equivalent) |
WK8203
Section titled “WK8203”Root filesystem is writable — merge-worthy · guidance
Set readOnlyRootFilesystem: true.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | KubeLinter no-read-only-root-fs (equivalent) · Fairwinds Polaris notReadOnlyRootFilesystem (equivalent) · Checkov CKV_K8S_22 (equivalent) |
WK8204
Section titled “WK8204”Container may run as root — merge-worthy · guidance
Set runAsNonRoot: true (and a non-zero runAsUser).
| Authority | Kubernetes — Pod Security Standards |
| Prior art | Fairwinds Polaris runAsRootAllowed (equivalent) · Checkov CKV_K8S_23 (equivalent) · KubeLinter run-as-non-root (overlaps) |
WK8205
Section titled “WK8205”Capabilities not dropped — merge-worthy · guidance
drop: [ALL] and add back only what is required.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | [kubesec `containers[] .securityContext .capabilities .drop |
WK8207
Section titled “WK8207”Pod uses host network — merge-worthy · guidance
Remove hostNetwork; it bypasses network isolation.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | KubeLinter host-network (equivalent) · Fairwinds Polaris hostNetworkSet (equivalent) · Checkov CKV_K8S_19 (equivalent) |
WK8208
Section titled “WK8208”Pod shares host PID namespace — merge-worthy · guidance
Remove hostPID.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | KubeLinter host-pid (equivalent) · Fairwinds Polaris hostPIDSet (equivalent) · Checkov CKV_K8S_17 (equivalent) |
WK8209
Section titled “WK8209”Pod shares host IPC namespace — merge-worthy · guidance
Remove hostIPC.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | KubeLinter host-ipc (equivalent) · Fairwinds Polaris hostIPCSet (equivalent) · Checkov CKV_K8S_18 (equivalent) |
WK8301
Section titled “WK8301”Container missing probes — report-only · guidance
Add liveness and readiness probes.
| Prior art | kube-score pod-probes (overlaps) · Fairwinds Polaris readinessProbeMissing (overlaps) · Checkov CKV_K8S_8 (overlaps) |
WK8302
Section titled “WK8302”Deployment has a single replica — report-only · guidance
Use replicas >= 2 for availability.
| Prior art | Fairwinds Polaris deploymentMissingReplicas (equivalent) · kube-score deployment-replicas (equivalent) · Datree ensure-minimum-two-replicas (equivalent) |
WK8303
Section titled “WK8303”No PodDisruptionBudget for an HA Deployment — report-only · guidance
Add a PDB to protect availability during disruptions.
| Prior art | kube-score deployment-has-poddisruptionbudget (overlaps) · Fairwinds Polaris missingPodDisruptionBudget (overlaps) · KICS Deployment Without PodDisruptionBudget (overlaps) |
WK8304
Section titled “WK8304”SSL redirect without a certificate — report-only · guidance
Provide a certificate and HTTPS listen-ports for the ssl-redirect annotation.
| Prior art | Fairwinds Polaris tlsSettingsMissing (overlaps) |
WK8305
Section titled “WK8305”Ingress backend port does not match the Service — merge-worthy · guidance
Point the Ingress backend at a declared Service port.
| Prior art | KubeLinter dangling-ingress (overlaps) · kube-score ingress-targets-service (overlaps) |
WK8306
Section titled “WK8306”Container command starts with a flag — merge-worthy · guidance
The first command element should be a binary, not a flag.
WK8401
Section titled “WK8401”shmSize exceeds the container memory limit — merge-worthy · guidance
Lower shmSize or raise the memory limit so the pod can schedule.
WK8402
Section titled “WK8402”RayCluster missing spec.rayVersion — report-only · guidance
Set spec.rayVersion so KubeRay picks the right autoscaler image.
WK8403
Section titled “WK8403”rayVersion does not match the head image tag — report-only · guidance
Align spec.rayVersion with the Ray version in the head container image.
WK8404
Section titled “WK8404”GPU request without a matching toleration — merge-worthy · guidance
Add a toleration for the nvidia.com/gpu taint (or a wildcard Exists toleration) so the pod can schedule onto a GPU node pool.
WK8405
Section titled “WK8405”Serving workload has no PodDisruptionBudget — report-only · guidance
Add a PDB selecting the InferenceService/serving Deployment so a node drain can’t take down every replica at once.
| Prior art | kube-score deployment-has-poddisruptionbudget (overlaps) · Fairwinds Polaris missingPodDisruptionBudget (overlaps) |
WK8406
Section titled “WK8406”GPU container missing resource limits — merge-worthy · guidance
Set CPU and memory limits on GPU-requesting containers to avoid starving the (scarce, expensive) GPU node.
| Prior art | Checkov CKV_K8S_13 (overlaps) · kube-score container-resources (overlaps) · KubeLinter unset-memory-requirements (overlaps) |
WK8407
Section titled “WK8407”Unpinned model version — merge-worthy · guidance
Pin the InferenceService model storageUri to an explicit version segment (e.g. via the Model composite’s required version) instead of a floating tag.
WK8501
Section titled “WK8501”Custom resource spec has a field its CRD does not declare — merge-worthy · guidance
Fix the field name; the API server prunes unknown fields and the controller never sees them.
| Prior art | KubeLinter schema-validation (overlaps) |
WK8502
Section titled “WK8502”Custom resource spec field has the wrong type or enum value — merge-worthy · guidance
Match the CRD schema: use the declared scalar type and one of the enum values.
| Prior art | KubeLinter schema-validation (overlaps) |
WK8503
Section titled “WK8503”Workload consumes a Secret nothing in the output produces — merge-worthy · guidance
Produce the Secret in the same build (Secret, ExternalSecret, InfisicalSecret, cert-manager Certificate), or declare its provenance with declareSecret() if it exists out of band.
| Prior art | KubeLinter env-value-from (overlaps) |
WK8504
Section titled “WK8504”committed-encrypted secret declaration does not resolve — merge-worthy · guidance
Point file at the committed ciphertext, make its metadata.name match the declaration, and re-run sops -e -i so every data/stringData value is ENC[…].
| Authority | Kubernetes — Good practices for Secrets |
WK8505
Section titled “WK8505”committed-encrypted secret with no Flux decryption wiring — report-only · guidance
Add decryption: “sops” to the FluxAppFor reconciling the path that carries the ciphertext sidecar, or ignore if that Kustomization is declared in a different build. This check sees one build root at a time, so it goes silent once the secret and the Kustomization live in different build roots (chant #1939).
| Prior art | Flux Kustomization API reference .spec.decryption (overlaps) |
Docker (DKRD)
Section titled “Docker (DKRD)”Run against Dockerfiles and Compose files.
DKRD001
Section titled “DKRD001”Service uses :latest or untagged image — merge-worthy · guidance
Pin the image to an explicit version tag (ideally a digest).
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | hadolint DL3007 (overlaps) · Checkov CKV_DOCKER_7 (overlaps) · KICS image_version_using_latest (overlaps) |
DKRD002
Section titled “DKRD002”Named volume declared but unused — report-only · guidance
Remove the unused volume or mount it in a service.
DKRD003
Section titled “DKRD003”Service exposes SSH (port 22) — merge-worthy · guidance
Don’t expose SSH from a container; use exec/ephemeral access instead.
| Authority | Docker — Security best practices |
| Prior art | Checkov CKV_DOCKER_1 (overlaps) · KICS Exposing Port 22 (SSH) (overlaps) |
DKRD010
Section titled “DKRD010”apt-get install without —no-install-recommends — report-only · guidance
Add —no-install-recommends to keep images small.
| Prior art | hadolint DL3015 (equivalent) · KICS apt_get_not_avoiding_additional_packages (equivalent) |
DKRD011
Section titled “DKRD011”ADD used where COPY would do — report-only · guidance
Prefer COPY unless fetching a URL or extracting an archive.
| Prior art | hadolint DL3020 (equivalent) · Checkov CKV_DOCKER_4 (overlaps) · Dockle CIS-DI-0009 (overlaps) |
DKRD012
Section titled “DKRD012”No USER instruction — container runs as root — merge-worthy · guidance
Add a non-root USER instruction.
| Authority | Docker — Security best practices |
| Prior art | Checkov CKV_DOCKER_3 (equivalent) · KICS missing_user_instruction (equivalent) · Dockle CIS-DI-0001 (overlaps) |
AWS CloudFormation (WAW / COR / EXT)
Section titled “AWS CloudFormation (WAW / COR / EXT)”Run against CloudFormation templates (JSON or YAML).
COR020
Section titled “COR020”Circular resource dependency — merge-worthy · guidance
Break the dependency cycle between resources.
| Prior art | cfn-lint E3004 (equivalent) |
EXT001
Section titled “EXT001”Extension constraint violation — merge-worthy · guidance
Fix the cross-property constraint flagged by the cfn-lint extension schema.
| Prior art | cfn-lint (equivalent) · cfn-lint E3014 (equivalent) · cfn-lint E3021 (equivalent) |
WAW010
Section titled “WAW010”Redundant DependsOn — report-only · guidance
Remove DependsOn already implied by a Ref/GetAtt.
| Prior art | cfn-lint W3005 (equivalent) |
WAW011
Section titled “WAW011”Deprecated Lambda runtime — report-only · guidance
Upgrade to a supported Lambda runtime.
| Prior art | cfn-lint W2531 (equivalent) · Checkov CKV_AWS_363 (equivalent) |
WAW013
Section titled “WAW013”Child stack exports nothing — merge-worthy · guidance
Add stackOutput() exports the parent can reference.
WAW014
Section titled “WAW014”Nested stack outputs never referenced — report-only · guidance
Reference the outputs or split into a separate build.
WAW015
Section titled “WAW015”Circular dependency between nested stacks — merge-worthy · guidance
Break the cycle between nested stacks.
WAW016
Section titled “WAW016”Deprecated property — report-only · guidance
Replace the deprecated CloudFormation property.
WAW017
Section titled “WAW017”Missing tags on a taggable resource — report-only · guidance
Add tags for cost allocation and compliance.
| Prior art | KICS Lambda Function Without Tags (extends) · KICS EFS Without Tags (extends) |
WAW018
Section titled “WAW018”S3 bucket missing public access block — merge-worthy · guidance
Add a PublicAccessBlockConfiguration blocking all public access.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | AWS Guard Rules Registry S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED (equivalent) · Checkov CKV_AWS_53 (extends) · Checkov CKV_AWS_56 (extends) |
WAW019
Section titled “WAW019”Security group allows unrestricted ingress on a sensitive port — merge-worthy · guidance
Restrict the CIDR on SSH/RDP/database ports to known sources.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | AWS Guard Rules Registry RESTRICTED_INCOMING_TRAFFIC (overlaps) · KICS EC2 Sensitive Port Is Publicly Exposed (overlaps) · Checkov CKV_AWS_24 (extends) |
WAW020
Section titled “WAW020”IAM policy uses a wildcard Action — merge-worthy · guidance
Scope the policy to specific actions (least privilege).
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | Checkov CKV_AWS_63 (equivalent) · cfn_nag F4 (overlaps) · AWS Guard Rules Registry IAM_ROLE_NO_WILDCARD_ACTIONS_ON_PERMISSIONS (overlaps) |
WAW021
Section titled “WAW021”RDS storage not encrypted — merge-worthy · guidance
Enable StorageEncrypted for encryption at rest.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag F27 (equivalent) · Checkov CKV_AWS_16 (equivalent) · AWS Guard Rules Registry RDS_STORAGE_ENCRYPTED (equivalent) |
WAW022
Section titled “WAW022”Lambda has no VpcConfig — report-only · guidance
Consider a VpcConfig for network isolation if the function needs VPC resources.
| Prior art | cfn_nag W89 (equivalent) · Checkov CKV_AWS_117 (equivalent) · AWS Guard Rules Registry LAMBDA_INSIDE_VPC (equivalent) |
WAW023
Section titled “WAW023”CloudFront has no WAF web ACL — report-only · guidance
Consider attaching a WAF web ACL.
| Prior art | Checkov CKV_AWS_68 (equivalent) · KICS CloudFront Without WAF (equivalent) |
WAW024
Section titled “WAW024”ALB access logging disabled — report-only · guidance
Enable access logging for audit trails.
| Prior art | cfn_nag W52 (equivalent) · Checkov CKV_AWS_91 (equivalent) · KICS ELBv2 ALB Access Log Disabled (equivalent) |
WAW025
Section titled “WAW025”SNS topic not encrypted — merge-worthy · guidance
Set KmsMasterKeyId for encryption at rest.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag W47 (equivalent) · Checkov CKV_AWS_26 (equivalent) · AWS Guard Rules Registry SNS_ENCRYPTED_KMS (equivalent) |
WAW026
Section titled “WAW026”SQS queue not encrypted — merge-worthy · guidance
Enable SqsManagedSseEnabled or set KmsMasterKeyId.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | Checkov CKV_AWS_27 (equivalent) · KICS SQS With SSE Disabled (equivalent) · cfn_nag W48 (overlaps) |
WAW027
Section titled “WAW027”DynamoDB point-in-time recovery disabled — report-only · guidance
Enable PITR for recovery.
| Prior art | cfn_nag W78 (equivalent) · Checkov CKV_AWS_28 (equivalent) · AWS Guard Rules Registry DYNAMODB_PITR_ENABLED (equivalent) |
WAW028
Section titled “WAW028”EBS volume not encrypted — merge-worthy · guidance
Enable encryption at rest.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag F1 (equivalent) · Checkov CKV_AWS_3 (equivalent) · AWS Guard Rules Registry ENCRYPTED_VOLUMES (equivalent) |
WAW029
Section titled “WAW029”Invalid DependsOn target — merge-worthy · guidance
Fix the dangling/self DependsOn reference.
| Prior art | cfn-lint E3005 (equivalent) |
WAW030
Section titled “WAW030”Missing DependsOn for a known ordering pattern — report-only · guidance
Add the DependsOn the pattern requires.
WAW031
Section titled “WAW031”EKS Addon missing ServiceAccountRoleArn — report-only · guidance
Set ServiceAccountRoleArn (IRSA) for addons that need it.
WAW032
Section titled “WAW032”EFS transit encryption disabled on Fargate — merge-worthy · guidance
Enable transit encryption for the EFS volume.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | Checkov CKV_AWS_97 (equivalent) · KICS EFS Volume With Disabled Transit Encryption (equivalent) |
WAW033
Section titled “WAW033”Solr heap exceeds Fargate task memory — merge-worthy · guidance
Lower SOLR_HEAP or raise task memory.
WAW034
Section titled “WAW034”Fargate Solr task under-provisioned — report-only · guidance
Allocate >= 2048MB for the Solr task.
WAW035
Section titled “WAW035”Solr container missing nofile ulimit — report-only · guidance
Set a nofile ulimit >= 65535.
WAW036
Section titled “WAW036”Non-ASCII characters in resource properties — merge-worthy · guidance
Remove non-ASCII characters rejected at changeset time.
WAW037
Section titled “WAW037”Null values in resource properties — merge-worthy · guidance
Fix the invalid AttrRef producing null property values.
WAW038
Section titled “WAW038”RDS instance is publicly accessible — merge-worthy · guidance
Set PubliclyAccessible: false and reach the database through the VPC.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag F22 (equivalent) · Checkov CKV_AWS_17 (equivalent) · KICS RDS DB Instance Publicly Accessible (equivalent) |
WAW039
Section titled “WAW039”RDS automated backups disabled — merge-worthy · guidance
Set a positive BackupRetentionPeriod.
| Prior art | cfn_nag W75 (equivalent) · AWS Guard Rules Registry DB_INSTANCE_BACKUP_ENABLED (equivalent) · KICS RDS With Backup Disabled (equivalent) |
WAW040
Section titled “WAW040”RDS deletion protection disabled (full tier) — merge-worthy · guidance
Set DeletionProtection: true on the full/production tier.
| Prior art | cfn_nag F80 (equivalent) · AWS Guard Rules Registry RDS_INSTANCE_DELETION_PROTECTION_ENABLED (equivalent) · KICS RDS DB Instance With Deletion Protection Disabled (equivalent) |
WAW041
Section titled “WAW041”RDS Proxy does not require TLS — merge-worthy · guidance
Set RequireTLS: true on the DB proxy.
| Authority | AWS — Security Pillar (Well-Architected) |
WAW042
Section titled “WAW042”S3 bucket missing a TLS-only bucket policy — merge-worthy · guidance
Add a Deny statement keyed on aws:SecureTransport = false.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | AWS Guard Rules Registry S3_BUCKET_SSL_REQUESTS_ONLY (equivalent) · KICS S3 Bucket Without SSL In Write Actions (overlaps) |
WAW043
Section titled “WAW043”KMS key rotation disabled — merge-worthy · guidance
Set EnableKeyRotation: true on the customer-managed key.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag F19 (equivalent) · Checkov CKV_AWS_7 (equivalent) · AWS Guard Rules Registry CMK_BACKING_KEY_ROTATION_ENABLED (equivalent) |
WAW044
Section titled “WAW044”ALB HTTP listener does not redirect to HTTPS (full tier) — merge-worthy · guidance
Add a redirect DefaultAction (Protocol: HTTPS) to the HTTP listener on the full/production tier.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | Checkov CKV_AWS_2 (overlaps) · cfn_nag W56 (overlaps) |
WAW045
Section titled “WAW045”ALB listener uses a weak or missing TLS policy — merge-worthy · guidance
Set SslPolicy to a TLS 1.2+ predefined policy.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag W55 (equivalent) · Checkov CKV_AWS_103 (equivalent) · AWS Guard Rules Registry ELBV2_LISTENER_SSL_POLICY_RULE (equivalent) |
WAW046
Section titled “WAW046”ECS container passes a secret via plaintext Environment — merge-worthy · guidance
Move the value to Secrets (Secrets Manager/SSM Parameter Store).
| Authority | AWS — Security Pillar (Well-Architected) |
WAW047
Section titled “WAW047”ECS container runs privileged — merge-worthy · guidance
Remove Privileged: true from the container definition.
| Authority | AWS — Security Pillar (Well-Architected) |
WAW048
Section titled “WAW048”ECS container missing log configuration — report-only · guidance
Add a LogConfiguration (e.g. awslogs) to the container.
WAW049
Section titled “WAW049”Security group allows unrestricted ingress on a non-ALB port — merge-worthy · guidance
Restrict the CIDR; only ALB:80/443 is exempt from this rule.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag W2 (overlaps) · AWS Guard Rules Registry EC2_SECURITY_GROUP_INGRESS_OPEN_TO_WORLD_RULE (overlaps) · KICS Unrestricted Security Group Ingress (overlaps) |
WAW050
Section titled “WAW050”Cognito advanced security disabled — merge-worthy · guidance
Set UserPoolAddOns.AdvancedSecurityMode to AUDIT or ENFORCED.
| Authority | AWS — Security Pillar (Well-Architected) |
WAW051
Section titled “WAW051”Cognito UserPoolClient allows the implicit OAuth grant — merge-worthy · guidance
Drop “implicit” from AllowedOAuthFlows; use the code grant.
| Authority | AWS — Security Pillar (Well-Architected) |
WAW052
Section titled “WAW052”Cognito MFA not required (full tier) — merge-worthy · guidance
Set MfaConfiguration: ON on the full/production tier.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag F78 (overlaps) · AWS Guard Rules Registry COGNITO_USER_POOL_MFA_CONFIGURATION_RULE (overlaps) · KICS Cognito UserPool Without MFA (overlaps) |
WAW053
Section titled “WAW053”ECR repository does not scan images on push — merge-worthy · guidance
Set ImageScanningConfiguration.ScanOnPush: true.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | cfn_nag W79 (equivalent) · Checkov CKV_AWS_163 (equivalent) · AWS Guard Rules Registry ECR_REPO_SCAN_ON_PUSH (equivalent) |
WAW054
Section titled “WAW054”ECR repository allows mutable image tags — merge-worthy · guidance
Set ImageTagMutability: IMMUTABLE.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | Checkov CKV_AWS_51 (equivalent) · KICS ECR Image Tag Not Immutable (equivalent) |
WAW055
Section titled “WAW055”CloudWatch Logs log group has no retention period — report-only · guidance
Set an explicit RetentionInDays.
| Prior art | cfn_nag W86 (equivalent) · Checkov CKV_AWS_66 (equivalent) · AWS Guard Rules Registry CW_LOGGROUP_RETENTION_PERIOD_CHECK (equivalent) |
WAW056
Section titled “WAW056”SCP guardrail has no Deny statement — merge-worthy · guidance
Add a Deny statement — SCPs only filter permissions, so a Deny-less SCP guards nothing.
| Authority | AWS — Security Pillar (Well-Architected) |
WAW057
Section titled “WAW057”SCP guardrail attached to no targets — merge-worthy · guidance
Attach the SCP to the organization root or an OU via TargetIds.
| Authority | AWS — Security Pillar (Well-Architected) |
WAW058
Section titled “WAW058”Organization audit trail dropped or scoped down — merge-worthy · guidance
Keep an organization CloudTrail with IsLogging: true and IsMultiRegionTrail: true.
| Authority | AWS — Security Pillar (Well-Architected) |
| Prior art | AWS Guard Rules Registry MULTI_REGION_CLOUD_TRAIL_ENABLED (overlaps) · Checkov CKV_AWS_67 (overlaps) · KICS CloudTrail Logging Disabled (overlaps) |
WAW059
Section titled “WAW059”Wildcard Resource where the declared graph enumerates the touched set — report-only · guidance
Tighten Resource from ”*” to the Fn::GetAtt Arn list of the declared resources the role’s consumers touch.
| Prior art | cfn_nag W12 (overlaps) · cfn_nag W11 (overlaps) · AWS Guard Rules Registry IAM_POLICYDOCUMENT_NO_WILDCARD_RESOURCE (overlaps) |
WAW060
Section titled “WAW060”IAM policy attached to no principal — report-only · guidance
Attach the policy via Roles/Users/Groups or reference it from a principal’s ManagedPolicyArns — unattached it grants nothing.
WAW061
Section titled “WAW061”Subnet CidrBlock not contained in its VPC’s CidrBlock — merge-worthy · guidance
Fix the subnet’s CidrBlock so it falls within the VPC’s CidrBlock range.
| Prior art | cfn-lint E3059 (equivalent) |
WAW062
Section titled “WAW062”Duplicate export name or explicit resource name within a template — merge-worthy · guidance
Give each duplicated Export/name a distinct literal value.
| Prior art | cfn-lint E3019 (overlaps) |
WAW063
Section titled “WAW063”IAM policy denies an action another attached policy on the same role allows — merge-worthy · guidance
Remove or narrow the Deny, or move the Allow off this role — the explicit Deny always wins.
WAW064
Section titled “WAW064”Transit Gateway route table declares a Blackhole route — report-only · guidance
Confirm the traffic drop is intentional; remove the route if it isn’t.
WAW065
Section titled “WAW065”Transit Gateway route table wiring is incomplete — report-only · guidance
Add the missing TransitGatewayRouteTablePropagation, or wire the orphaned attachment into a route table.
WAW066
Section titled “WAW066”Private subnet’s route table has no working default route — merge-worthy · guidance
Add a 0.0.0.0/0 route to a NAT gateway/Transit Gateway that exists in the template.
WAW067
Section titled “WAW067”Single-AZ NAT gateway serves multi-AZ private subnets — report-only · guidance
Add one NAT gateway per Availability Zone and point each AZ’s subnets at its own.
WAW068
Section titled “WAW068”VPN Gateway or Transit Gateway has only one attached VPN Connection — report-only · guidance
Attach a second VPNConnection (ideally to a separate Customer Gateway) for redundancy.
WAW069
Section titled “WAW069”Template references a condition it never declares — merge-worthy · guidance
Declare the condition in the Conditions section (new Condition(…)), or fix the referenced name.
| Prior art | cfn-lint E8002 (equivalent) |
Azure ARM (AZR)
Section titled “Azure ARM (AZR)”Run against ARM deployment templates (JSON).
AZR010
Section titled “AZR010”Redundant dependsOn — report-only · guidance
Remove dependsOn already implied by reference()/resourceId().
| Prior art | Bicep linter no-unnecessary-dependson (equivalent) |
AZR011
Section titled “AZR011”Missing or invalid apiVersion — merge-worthy · guidance
Set a valid YYYY-MM-DD apiVersion on every resource.
| Prior art | ARM Template Toolkit (arm-ttk) apiVersions-Should-Be-Recent (overlaps) |
AZR012
Section titled “AZR012”Deprecated API version — report-only · guidance
Move to a current apiVersion.
| Prior art | ARM Template Toolkit (arm-ttk) apiVersions-Should-Be-Recent (overlaps) · Bicep linter use-recent-api-versions (overlaps) |
AZR013
Section titled “AZR013”Resource missing location — merge-worthy · guidance
Add the required location property.
AZR014
Section titled “AZR014”Storage account allows public blob access — merge-worthy · guidance
Set allowBlobPublicAccess to false.
| Authority | Microsoft Cloud Security Benchmark |
| Prior art | PSRule for Azure Azure.Storage.BlobPublicAccess (equivalent) · Checkov CKV_AZURE_59 (equivalent) |
AZR015
Section titled “AZR015”Storage account missing encryption — merge-worthy · guidance
Enable encryption services for data at rest.
| Authority | Microsoft Cloud Security Benchmark |
AZR016
Section titled “AZR016”Key Vault soft-delete not enabled — report-only · guidance
Enable soft-delete.
| Prior art | PSRule for Azure Azure.KeyVault.SoftDelete (equivalent) · Checkov CKV_AZURE_111 (equivalent) · KICS Key Vault Not Recoverable (overlaps) |
AZR017
Section titled “AZR017”Key Vault purge protection not enabled — report-only · guidance
Enable purge protection.
| Prior art | PSRule for Azure Azure.KeyVault.PurgeProtect (equivalent) · Checkov CKV_AZURE_110 (equivalent) · KICS Key Vault Not Recoverable (overlaps) |
AZR018
Section titled “AZR018”SQL Server missing auditing — report-only · guidance
Enable auditing for compliance and threat detection.
| Prior art | PSRule for Azure Azure.SQL.Auditing (equivalent) · Checkov CKV_AZURE_23 (equivalent) · KICS SQL Server Database Without Auditing (equivalent) |
AZR019
Section titled “AZR019”SQL database missing TDE — merge-worthy · guidance
Enable Transparent Data Encryption.
| Authority | Microsoft Cloud Security Benchmark |
| Prior art | PSRule for Azure Azure.SQL.TDE (equivalent) |
AZR020
Section titled “AZR020”App Service missing managed identity — report-only · guidance
Enable a system- or user-assigned identity.
| Prior art | PSRule for Azure Azure.AppService.ManagedIdentity (equivalent) · Checkov CKV_AZURE_71 (equivalent) |
AZR021
Section titled “AZR021”App Service not HTTPS-only — merge-worthy · guidance
Set httpsOnly to true.
| Authority | Microsoft Cloud Security Benchmark |
| Prior art | PSRule for Azure Azure.AppService.UseHTTPS (equivalent) · Checkov CKV_AZURE_14 (equivalent) · KICS Website Not Forcing HTTPS (equivalent) |
AZR022
Section titled “AZR022”App Service min TLS below 1.2 — merge-worthy · guidance
Set minTlsVersion to 1.2+.
| Authority | Microsoft Cloud Security Benchmark |
| Prior art | PSRule for Azure Azure.AppService.MinTLS (equivalent) · Checkov CKV_AZURE_15 (equivalent) · KICS Web App Not Using TLS Last Version (equivalent) |
AZR023
Section titled “AZR023”VM not using a managed disk — report-only · guidance
Use a managed disk.
| Prior art | PSRule for Azure Azure.VM.UseManagedDisks (equivalent) · Checkov CKV_AZURE_92 (equivalent) |
AZR024
Section titled “AZR024”VM missing boot diagnostics — report-only · guidance
Enable boot diagnostics.
AZR025
Section titled “AZR025”AKS cluster missing RBAC — report-only · guidance
Enable Kubernetes RBAC.
| Prior art | PSRule for Azure Azure.AKS.UseRBAC (equivalent) · Checkov CKV_AZURE_5 (equivalent) · KICS AKS Cluster RBAC Disabled (equivalent) |
AZR026
Section titled “AZR026”AKS cluster missing network policy — report-only · guidance
Configure a networkPolicy.
| Prior art | PSRule for Azure Azure.AKS.NetworkPolicy (equivalent) · Checkov CKV_AZURE_7 (equivalent) · KICS AKS Cluster Network Policy Not Configured (equivalent) |
AZR027
Section titled “AZR027”Container Registry admin user enabled — merge-worthy · guidance
Disable the admin user; use Azure AD / service principals.
| Authority | Microsoft Cloud Security Benchmark |
| Prior art | PSRule for Azure Azure.ACR.AdminUser (equivalent) · Checkov CKV_AZURE_137 (equivalent) |
AZR028
Section titled “AZR028”Network interface missing NSG — report-only · guidance
Associate an NSG to control traffic.
AZR029
Section titled “AZR029”Managed disk missing encryption — merge-worthy · guidance
Enable encryption for data at rest.
| Authority | Microsoft Cloud Security Benchmark |
| Prior art | Checkov CKV_AZURE_2 (equivalent) · KICS Azure Managed Disk Without Encryption (equivalent) · PSRule for Azure Azure.VM.ADE (overlaps) |
AZR030
Section titled “AZR030”Resource at unsupported template scope — merge-worthy · guidance
Move the resource to a project deployed at a scope its schema supports.
AZR031
Section titled “AZR031”Policy assignment not enforced (DoNotEnforce) — merge-worthy · guidance
Set enforcementMode to Default so the assigned guardrail applies.
| Authority | Microsoft Cloud Security Benchmark |
AZR032
Section titled “AZR032”Custom policy definition assigned nowhere — merge-worthy · guidance
Pair the policy definition with a policy assignment — unassigned it enforces nothing.
| Authority | Microsoft Cloud Security Benchmark |
AZR033
Section titled “AZR033”Subscriptions may leave the tenant — merge-worthy · guidance
Set blockSubscriptionsLeavingTenant: true on the Microsoft.Subscription/policies resource.
| Authority | Microsoft Cloud Security Benchmark |
GCP Config Connector (WGC)
Section titled “GCP Config Connector (WGC)”Run against Config Connector (cnrm.cloud.google.com) manifests.
WGC101
Section titled “WGC101”Storage/SQL without encryption configuration — merge-worthy · guidance
Configure encryption (e.g. a CMEK key) for data at rest.
| Authority | Google Cloud — Security best practices |
| Prior art | Google Cloud Policy Library GCPStorageCMEKEncryptionConstraintV1 (overlaps) |
WGC102
Section titled “WGC102”Public IAM member (allUsers/allAuthenticatedUsers) — merge-worthy · guidance
Remove allUsers/allAuthenticatedUsers bindings.
| Authority | Google Cloud — Security best practices |
| Prior art | Checkov CKV_GCP_28 (overlaps) · KICS Cloud Storage Anonymous or Publicly Accessible (overlaps) · Google Cloud Policy Library GCPStorageBucketWorldReadableConstraintV1 (overlaps) |
WGC103
Section titled “WGC103”Missing project-id annotation — report-only · guidance
Add the cnrm.cloud.google.com/project-id annotation.
WGC104
Section titled “WGC104”Bucket without uniform bucket-level access — merge-worthy · guidance
Enable uniformBucketLevelAccess.
| Authority | Google Cloud — Security best practices |
| Prior art | Checkov CKV_GCP_29 (overlaps) · KICS Google Storage Bucket Level Access Disabled (overlaps) · Google Cloud Policy Library GCPStorageBucketPolicyOnlyConstraintV1 (overlaps) |
WGC105
Section titled “WGC105”Cloud SQL open to 0.0.0.0/0 — merge-worthy · guidance
Restrict authorizedNetworks to known sources.
| Authority | Google Cloud — Security best practices |
| Prior art | Checkov CKV_GCP_11 (overlaps) · KICS SQL DB Instance Publicly Accessible (overlaps) · Google Cloud Policy Library GCPSQLWorldReadableConstraintV1 (overlaps) |
WGC106
Section titled “WGC106”Missing deletion-policy annotation — report-only · guidance
Add the cnrm.cloud.google.com/deletion-policy annotation.
WGC107
Section titled “WGC107”Bucket versioning disabled — report-only · guidance
Enable object versioning.
| Prior art | Checkov CKV_GCP_78 (overlaps) · KICS Cloud Storage Bucket Versioning Disabled (overlaps) |
WGC108
Section titled “WGC108”Cloud SQL backups disabled — report-only · guidance
Enable backup configuration.
| Prior art | Checkov CKV_GCP_14 (overlaps) · KICS SQL DB Instance Backup Disabled (overlaps) · Google Cloud Policy Library GCPSQLBackupConstraintV1 (overlaps) |
WGC109
Section titled “WGC109”Firewall open to 0.0.0.0/0 — merge-worthy · guidance
Restrict sourceRanges to known sources.
| Authority | Google Cloud — Security best practices |
| Prior art | Google Cloud Policy Library GCPRestrictedFirewallRulesConstraintV1 (overlaps) · Checkov CKV2_GCP_12 (overlaps) |
WGC110
Section titled “WGC110”KMS key without rotation — merge-worthy · guidance
Set a rotationPeriod on the CryptoKey.
| Authority | Google Cloud — Security best practices |
| Prior art | Checkov CKV_GCP_43 (overlaps) · KICS High Google KMS Crypto Key Rotation Period (overlaps) · Google Cloud Policy Library GCPCMEKRotationConstraintV1 (overlaps) |
WGC111
Section titled “WGC111”Reference to an undefined resource — merge-worthy · guidance
Point the reference at a resource in the output.
WGC112
Section titled “WGC112”Missing or invalid apiVersion — merge-worthy · guidance
Set a valid cnrm.cloud.google.com apiVersion.
WGC113
Section titled “WGC113”Alpha API version — report-only · guidance
Move to a beta/GA API version.
WGC201
Section titled “WGC201”Missing managed-by label — report-only · guidance
Add the app.kubernetes.io/managed-by label.
WGC202
Section titled “WGC202”Cluster without Workload Identity — merge-worthy · guidance
Enable Workload Identity on the ContainerCluster.
| Authority | Google Cloud — Security best practices |
| Prior art | Google Cloud Policy Library GCPGKEEnableWorkloadIdentityConstraintV1 (overlaps) · Checkov CKV_GCP_69 (overlaps) |
WGC203
Section titled “WGC203”Node pool uses broad cloud-platform scope — merge-worthy · guidance
Use narrowly-scoped OAuth scopes instead of cloud-platform.
| Authority | Google Cloud — Security best practices |
| Prior art | Google Cloud Policy Library GCPGKEAllowedNodeSAConstraintV1 (overlaps) · Checkov CKV_GCP_31 (overlaps) · KICS VM With Full Cloud Access (overlaps) |
WGC204
Section titled “WGC204”Compute instance without Shielded VM — report-only · guidance
Enable Shielded VM configuration.
| Prior art | Checkov CKV_GCP_39 (overlaps) · KICS Shielded VM Disabled (overlaps) |
WGC301
Section titled “WGC301”No IAMAuditConfig found — report-only · guidance
Configure audit logging via IAMAuditConfig.
| Prior art | Google Cloud Policy Library GCPIAMAuditLogConstraint (overlaps) · Checkov CKV2_GCP_5 (overlaps) |
WGC302
Section titled “WGC302”No Service (enabled APIs) found — report-only · guidance
Declare the GCP APIs you depend on.
WGC303
Section titled “WGC303”No VPC Service Controls perimeter — report-only · guidance
Consider an AccessContextManager ServicePerimeter.
| Prior art | Google Cloud Policy Library GCPVPCSCEnsureProjectConstraintV1 (overlaps) |
WGC401
Section titled “WGC401”Unknown field in resource spec — merge-worthy · guidance
Remove the unknown spec field.
WGC402
Section titled “WGC402”Missing required spec field — merge-worthy · guidance
Add the required spec field.
WGC403
Section titled “WGC403”Spec field has wrong type/structure — merge-worthy · guidance
Fix the field’s type/structure.
WGC501
Section titled “WGC501”Org Policy guardrail not enforced — merge-worthy · guidance
Enable enforce on the rule (or remove the policy deliberately) — a disabled org policy constrains nothing.
| Authority | Google Cloud — Security best practices |
WGC502
Section titled “WGC502”Org Policy guardrail defines no rules — merge-worthy · guidance
Add rules to the OrgPolicyPolicy — without them the constraint binds nothing.
| Authority | Google Cloud — Security best practices |
WGC503
Section titled “WGC503”Audit logging dropped or scoped down — merge-worthy · guidance
Keep auditLogConfigs populated and remove exemptedMembers from the IAMAuditConfig.
| Authority | Google Cloud — Security best practices |
| Prior art | Google Cloud Policy Library GCPIAMAuditLogConstraint (overlaps) · Checkov CKV2_GCP_5 (overlaps) · KICS IAM Audit Not Properly Configured (overlaps) |
Helm (WHM)
Section titled “Helm (WHM)”Run against Helm charts (Chart.yaml + templates).
WHM005
Section titled “WHM005”Sub-chart wrapper with no templates — report-only · guidance
Deploy the upstream chart directly instead of an empty wrapper.
| Prior art | helm lint templatesDirExists (overlaps) |
WHM101
Section titled “WHM101”Chart.yaml missing required fields — merge-worthy · guidance
Set apiVersion (v2), name, and version in Chart.yaml.
| Prior art | helm lint Chartfile (validateChartName, validateChartAPIVersion, validateChartVersion) (equivalent) · chart-testing (ct) ct lint --chart-yaml-schema (overlaps) |
WHM102
Section titled “WHM102”Missing values.schema.json — report-only · guidance
Add a values.schema.json to validate values.
WHM103
Section titled “WHM103”Invalid Go template syntax — merge-worthy · guidance
Fix the unbalanced template braces.
| Prior art | helm lint Templates (render error) (equivalent) |
WHM104
Section titled “WHM104”Missing NOTES.txt — report-only · guidance
Add templates/NOTES.txt for application charts.
WHM105
Section titled “WHM105”Missing _helpers.tpl — report-only · guidance
Add templates/_helpers.tpl.
WHM201
Section titled “WHM201”Missing standard Helm labels — report-only · guidance
Add the recommended app.kubernetes.io labels.
WHM202
Section titled “WHM202”Hook weights undefined — report-only · guidance
Define hook weights when multiple hooks exist.
WHM203
Section titled “WHM203”Undocumented values — report-only · guidance
Document values via schema or comments.
WHM204
Section titled “WHM204”Dependencies pinned, not ranged — report-only · guidance
Use semver ranges for chart dependencies.
WHM301
Section titled “WHM301”No Helm test — report-only · guidance
Add at least one Helm test for application charts.
WHM302
Section titled “WHM302”Container resources not set — report-only · guidance
Set limits/requests via values or defaults.
| Prior art | kube-score container-resources (overlaps) · KubeLinter unset-cpu-requirements (overlaps) · Fairwinds Polaris cpuRequestsMissing (overlaps) |
WHM401
Section titled “WHM401”Container image uses :latest or no tag — merge-worthy · guidance
Pin the image to an explicit version tag.
| Authority | OSSF Scorecard — Pinned-Dependencies |
| Prior art | kube-score container-image-tag (equivalent) · KICS Invalid Image Tag (equivalent) · Datree ensure-image-pinned-version (equivalent) |
WHM402
Section titled “WHM402”Container may run as root — merge-worthy · guidance
Set runAsNonRoot in the security context.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | kubesec containers[] .securityContext .runAsNonRoot == true (equivalent) · KICS Container Running As Root (equivalent) · kube-score container-security-context-user-group-id (overlaps) |
WHM403
Section titled “WHM403”Root filesystem writable — merge-worthy · guidance
Set readOnlyRootFilesystem.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | kubesec containers[] .securityContext .readOnlyRootFilesystem == true (equivalent) · KICS Root Container Not Mounted Read-only (equivalent) · kube-score container-security-context-readonlyrootfilesystem (equivalent) |
WHM404
Section titled “WHM404”Privileged container — merge-worthy · guidance
Remove privileged mode.
| Authority | Kubernetes — Pod Security Standards |
| Prior art | kubesec containers[] .securityContext .privileged == true (equivalent) · KICS Container Is Privileged (equivalent) · kube-score container-security-context-privileged (equivalent) |
WHM405
Section titled “WHM405”Resource specs missing cpu/memory — report-only · guidance
Set cpu and memory in limits/requests.
| Prior art | Checkov CKV_K8S_10 (overlaps) · Checkov CKV_K8S_12 (overlaps) · kubesec containers[] .resources .limits .memory (overlaps) |
WHM406
Section titled “WHM406”CRDs in crds/ are never upgraded — report-only · guidance
Manage CRD upgrades outside Helm or via a separate chart.
WHM407
Section titled “WHM407”Inline Secret data — merge-worthy · guidance
Use ExternalSecret/SealedSecret instead of inline Secret data.
| Authority | Kubernetes — Good practices for Secrets |
| Prior art | KICS Using Kubernetes Native Secret Management (overlaps) |
WHM501
Section titled “WHM501”Unused values key — report-only · guidance
Remove values defined but never referenced.
WHM502
Section titled “WHM502”Deprecated/invalid Kubernetes API version — merge-worthy · guidance
Update to a supported apiVersion.
| Prior art | Pluto detect-files (equivalent) · helm lint validateNoDeprecations (equivalent) · kube-score stable-version (equivalent) |
WHM503
Section titled “WHM503”Pinned render carries Secret data — merge-worthy · guidance
Declare the value with runtimeSlot() or replace the Secret with HelmExternalSecret.
| Authority | Kubernetes — Good practices for Secrets |
| Prior art | KICS Using Kubernetes Native Secret Management (overlaps) |
WHM504
Section titled “WHM504”Dead value assignment — merge-worthy · guidance
Remove supplied values that never survive coalescing (shadowed, disabled subchart, or unknown subchart).
fountain (FTN)
Section titled “fountain (FTN)”Run against fountain manifests (apiVersion: fountain.dev/v1) — standalone fountain apply YAML is parsed back into the entity graph, so the same rules fire on chant build and chant audit.
FTN001
Section titled “FTN001”Literal credential in a fountain declaration — merge-worthy · guidance
Use a ${VAR} substitution reference or an environment secret; never a literal in source.
| Authority | OWASP Top 10 for LLM Applications — LLM01: Prompt Injection |
FTN010
Section titled “FTN010”Environment does not set networking_type explicitly — merge-worthy · guidance
Set networking_type — an open sandbox by silence is not a reviewed decision.
| Authority | fountain — Environment, Vault, Agent, Teammate, Schedule and Webhook primitives |
FTN011
Section titled “FTN011”Environment uses networking_type: unrestricted — merge-worthy · guidance
Prefer limited with an allowed_hosts allowlist; an empty list denies all egress.
| Authority | fountain — Environment, Vault, Agent, Teammate, Schedule and Webhook primitives |
FTN012
Section titled “FTN012”Cloud-credential-shaped key or value in Environment env_vars — merge-worthy · guidance
env_vars is plaintext config — move credentials to a secret, or serve the capability outside the sandbox.
| Authority | OWASP Top 10 for LLM Applications — LLM01: Prompt Injection |
FTN013
Section titled “FTN013”Agent ${VAR} reference does not resolve against its environment — report-only · guidance
Declare the key on the environment, or confirm a vault supplies it at conversation create.
FTN014
Section titled “FTN014”Vault key shadows a declared Environment key — report-only · guidance
Vault values win on key collision silently — rename the key or confirm the override is intended.
FTN015
Section titled “FTN015”Secret-shaped MCP env key is a literal, not a ${VAR} reference — merge-worthy · guidance
Reference the value with ${VAR} so it resolves at spawn instead of living in source.
| Authority | OWASP Top 10 for LLM Applications — LLM01: Prompt Injection |
| Prior art | agent-audit auth-bypass/env-secret-in-config (overlaps) · mcp-audit (APIsec) Secrets Detection (overlaps) |
FTN016
Section titled “FTN016”Agent runtime or model is not a valid value — merge-worthy · guidance
Use a known runtime and a canonical provider/model_id.
FTN017
Section titled “FTN017”Two declarations of one kind resolve to the same fountain name — merge-worthy · guidance
fountain reconciles by name — rename one, or the second silently overwrites the first.
FTN020
Section titled “FTN020”Schedule cron is not five- or six-field UTC cron syntax — merge-worthy · guidance
Fix the expression. fountain stores an unparseable cron and then never fires it. The @daily-style shorthands are refused too (#2195): chant validates and matches one cron notion, the five- or six-field one, so write the fields out.
FTN021
Section titled “FTN021”A typed reference names something the build does not declare — merge-worthy · guidance
Declare the Agent or Teammate being referenced, or fix the name. Auditing standalone YAML, check the reference is not simply in another file, since the audit reads one file at a time.
FTN022
Section titled “FTN022”Webhook url is http, or targets a loopback or private address — merge-worthy · guidance
Deliver over https to a public host; a private target makes the delivery worker an SSRF probe.
| Authority | OWASP Top 10 for LLM Applications — LLM01: Prompt Injection |
FTN023
Section titled “FTN023”Agent runtime “acp” is missing runtime_command, or another runtime carries one — merge-worthy · guidance
Pair the acp runtime with the command it speaks the protocol over, and drop the field elsewhere.
Terraform (TF)
Section titled “Terraform (TF)”Run against Terraform root modules (a directory of .tf files) parsed into the entity graph, so the same rules fire on chant build over terraform.roots and on chant audit (#2083).
Root module declares no remote backend — merge-worthy · guidance
Add a backend "\<type>" block (s3, gcs, azurerm, http) or a cloud \{} block to the root module’s terraform block, then terraform init -migrate-state.
Provider implied by the root has no required_providers entry — merge-worthy · guidance
Add the provider to the terraform block’s required_providers, with both source and version set, so a future provider release can’t silently change behavior.
| Prior art | tflint-ruleset-terraform terraform_required_providers (equivalent) · HashiCorp reference Sentinel policies require-all-providers-have-version-constraint (equivalent) · AWS prescriptive guidance for Terraform Add automated version checks (equivalent) |
Root module’s terraform block has no required_version — merge-worthy · guidance
Set required_version = ">= \<lowest supported version>" in the terraform block.
| Prior art | tflint-ruleset-terraform terraform_required_version (equivalent) · HashiCorp reference Sentinel policies restrict-terraform-versions (overlaps) · HashiCorp Terraform style guide Version pinning (overlaps) |
Registry-sourced module block has no version — merge-worthy · guidance
Add a version constraint to the module block (e.g. ~> 5.0).
| Prior art | tflint-ruleset-terraform terraform_module_version (equivalent) · Checkov CKV_TF_2 (equivalent) |
Git/hg module source is unpinned, or pinned to a mutable ref — merge-worthy · guidance
Pin the module’s ?ref= to a tag or a full commit SHA.
| Prior art | tflint-ruleset-terraform terraform_module_pinned_source (equivalent) · Checkov CKV_TF_1 (extends) · KICS 3a81fc06-566f-492a-91dd-7448e409e2cd (overlaps) |
Default value on a sensitive variable — merge-worthy · guidance
Delete the default and require the caller to supply the value at apply time, through a tfvars file kept out of version control, a TF_VAR_ entry in the environment, or a workspace input.
| Prior art | tflint-ruleset-avm (Azure Verified Modules) avm_terraform_sensitive_variable_default_disallowed (equivalent) |
Plaintext secret in a variable default or a locals value — merge-worthy · guidance
Remove the literal, mark the variable sensitive = true, and read the value from a secret manager data source or an input at apply time, then rotate the credential, which is already in version control history.
| Prior art | tfsec general-secrets-sensitive-in-variable (equivalent) · tfsec general-secrets-sensitive-in-local (equivalent) |
Provider block configures a hardcoded credential — merge-worthy · guidance
Delete the credential from the provider block and let the provider read it from the environment, a shared credentials file, or an OIDC role assumption. Rotate the credential.
| Prior art | Checkov CKV_AWS_41 (overlaps) · KICS d7b9d850-3e06-4a75-852f-c46c2e92240b (overlaps) · Semgrep Registry rules terraform.aws.security.aws-provider-static-credentials (overlaps) |
Credential-named variable is not marked sensitive — merge-worthy · guidance
Add sensitive = true to the variable so its value is not printed in plan and apply output. The value is still stored in plaintext in state, so keep the state remote and encrypted.
Variable declares no type constraint — report-only · guidance
Add a type to the variable (string, number, bool, list(string), object(\{...})).
| Prior art | tflint-ruleset-terraform terraform_typed_variables (equivalent) · KICS fc5109bf-01fd-49fb-8bde-4492b543c34a (equivalent) |
Undocumented variable — report-only · guidance
Add a description saying what the value is for and what a valid one looks like.
| Prior art | tflint-ruleset-terraform terraform_documented_variables (equivalent) · KICS 2a153952-2544-4687-bcc9-cc8fea814a9b (equivalent) · HashiCorp reference Sentinel policies validate-variables-have-descriptions (equivalent) |
Undocumented output — report-only · guidance
Write a description for the output, covering what the value is and what a caller can rely on it for.
| Prior art | tflint-ruleset-terraform terraform_documented_outputs (equivalent) · KICS 59312e8a-a64e-41e7-a252-618533dd1ea8 (equivalent) |
lifecycle ignore_changes is set to all — merge-worthy · guidance
Replace ignore_changes = all with the list of attributes that genuinely change outside Terraform, so every other attribute is still reconciled.
| Prior art | tflint-ruleset-redeploy terraform_ignore_changes_all (equivalent) |
Child module configures a provider block — merge-worthy · guidance
Move the provider configuration to the root module and pass it into the module with providers = \{ ... }, leaving at most an alias-only block in the module.
Child module declares a backend or cloud block — merge-worthy · guidance
Delete the backend/cloud block from the child module. State belongs to the root module that calls it, one state for the whole tree.
| Prior art | Google Cloud Terraform best-practices series Build reusable modules: state configuration belongs to the root module (equivalent) |
Attribute value is a quoted interpolation of a single expression — report-only · deterministic
Drop the quotes and the $\{}: write x = var.y, not x = "$\{var.y}".
| Prior art | tflint-ruleset-terraform terraform_deprecated_interpolation (overlaps) |
Module block uses depends_on — report-only · guidance
Remove depends_on from the module call and pass an attribute of the dependency into a module input, so Terraform derives the narrower edge itself.
| Prior art | tflint-ruleset-redeploy terraform_module_depends_on (equivalent) |
Output value is a whole resource or data source — report-only · guidance
Return the attribute the caller needs (.id, .arn, .endpoint) instead of the whole block.
| Prior art | tflint-ruleset-redeploy terraform_output_resource (equivalent) |
Meta-argument explicitly set to its default of false — report-only · deterministic
Deleting the line is the whole fix. sensitive, ephemeral, prevent_destroy and create_before_destroy are false unless set.
| Prior art | tflint-ruleset-redeploy terraform_redundant_default (equivalent) |
Declaration is never referenced in its module scope — report-only · guidance
Delete the variable, local, data source or aliased provider, or reference it where it was meant to be used.
| Prior art | tflint-ruleset-terraform terraform_unused_declarations (overlaps) |
count builds instance identities from count.index where for_each is safer — report-only · guidance
Switch to for_each over a map or set so each instance is addressed by a stable key, then terraform state mv the existing indexed instances onto their new keys.
| Prior art | tflint-ruleset-redeploy terraform_prefer_for_each (overlaps) · choudoufu RuleCountIndex (overlaps) · HashiCorp Terraform style guide Resources: use for_each for a dynamic resource count (overlaps) |
Credential-named resource attribute holds a plaintext literal — merge-worthy · guidance
Replace the constant with a lookup, either an input the caller supplies or a data source pointed at whatever vault owns the credential, and rotate what was committed.
| Prior art | tfsec general-secrets-no-plaintext-exposure (overlaps) · KICS a88baa34-e2ad-44ea-ad6f-8cac87bc7c71 (overlaps) |
Terraform state committed to the repository — merge-worthy · guidance
Delete the state file (or .terraform/) from version control, add it to .gitignore, move the state to a remote backend, and rotate every credential the file held.
Live root declares a backend or cloud block, which choudoufu refuses — merge-worthy · guidance
Remove the backend/cloud block from the live root’s terraform block; a live root’s prior state is a projection rebuilt from the live system every run, so there is no state to store.
| Prior art | choudoufu RuleStateBackend (equivalent) |
Live root references a non-default terraform.workspace, which choudoufu refuses — merge-worthy · guidance
Remove workspace from the root’s terraform.roots config, and remove any terraform.workspace reference from its HCL; choudoufu refuses any workspace but “default” on a live root.
Live root declares delete: “never” but its policy leaves undeclared_tagged at “delete” — merge-worthy · guidance
Add undeclared_tagged = “keep” (or “untag” or “report”) to the live root’s policy block, or change terraform.roots.<name>.delete to “owned-only” or “gated” if an owned orphan should be deleted after all.
Live root’s policy block sets undeclared_untagged = “delete” — merge-worthy · guidance
Remove undeclared_untagged = “delete” from the live root’s policy block. chant never proposes deleting a resource it does not own; narrow the estate’s own ownership answer (undeclared_tagged) instead of the account’s.
| Prior art | choudoufu RulePolicyScope (extends) |
Live root is watched by a TerraformWatchOp built without live: true — merge-worthy · guidance
Set live: true on the TerraformWatchOp that names this root, so the Plan phase runs choudoufuLivePlan and reports the unowned and adoptable counts as well as drift. Drop the root’s estate instead if it is not a live root.
Live root names its estate both in chant.config and in its own HCL — merge-worthy · guidance
Pick one. A root whose directory is shared across environments declares no estate in HCL and names it per root with terraform.roots.<name>.estate; a root with its own live block already has an estate and needs nothing in chant.config. The declaration wins today, so the config value is written down and never used.
Secrets & credentials (SEC)
Section titled “Secrets & credentials (SEC)”Lexicon-independent — scans the raw text of every scanned file for likely credentials, regardless of which audit lexicons are installed. Matched values are always redacted; see suppressing false positives.
SEC001
Section titled “SEC001”AWS access key ID found — merge-worthy · guidance
Remove the key from source, rotate it in IAM, and load it from a secret store or environment variable instead.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks aws-access-token (equivalent) · TruffleHog aws (overlaps) · detect-secrets AWSKeyDetector (equivalent) |
SEC002
Section titled “SEC002”AWS secret access key found — merge-worthy · guidance
Remove the key from source, rotate it in IAM, and load it from a secret store or environment variable instead.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks generic-api-key (overlaps) · TruffleHog aws (overlaps) · detect-secrets AWSKeyDetector (overlaps) |
SEC003
Section titled “SEC003”GitHub token found — merge-worthy · guidance
Remove the token from source and revoke it at github.com/settings/tokens; use a GitHub Actions secret instead.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks github-pat (overlaps) · TruffleHog github (equivalent) · detect-secrets GitHubTokenDetector (overlaps) |
SEC004
Section titled “SEC004”Slack token found — merge-worthy · guidance
Remove the token from source and revoke it in the Slack app’s OAuth settings.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks slack-bot-token (overlaps) · TruffleHog slack (overlaps) · detect-secrets SlackDetector (overlaps) |
SEC005
Section titled “SEC005”Google API key found — merge-worthy · guidance
Remove the key from source and regenerate it in the Google Cloud Console credentials page.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks gcp-api-key (equivalent) · TruffleHog googlegemini (overlaps) |
SEC006
Section titled “SEC006”Stripe live secret key found — merge-worthy · guidance
Remove the key from source and roll it in the Stripe dashboard immediately — this is a live-mode key.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks stripe-access-token (overlaps) · TruffleHog stripe (overlaps) · detect-secrets StripeDetector (overlaps) |
SEC007
Section titled “SEC007”Private key block found — merge-worthy · guidance
Remove the private key from source, rotate the keypair, and load the key from a secret store instead.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks private-key (equivalent) · TruffleHog privatekey (equivalent) · detect-secrets PrivateKeyDetector (equivalent) |
SEC008
Section titled “SEC008”Bearer/authorization token found — merge-worthy · guidance
Remove the token from source; if it’s long-lived, revoke and reissue it via the issuing service.
| Authority | GitHub — About secret scanning |
| Prior art | gitleaks curl-auth-header (overlaps) |
SEC009
Section titled “SEC009”Credentials embedded in a connection string — merge-worthy · guidance
Move the username/password out of the URI into a secret store, and rotate the credential.
| Authority | GitHub — About secret scanning |
| Prior art | detect-secrets BasicAuthDetector (equivalent) · TruffleHog uri (overlaps) · gitleaks curl-auth-user (overlaps) |
SEC010
Section titled “SEC010”High-entropy string — possible secret — merge-worthy · guidance
Confirm whether this is a live credential; if so, remove it from source and rotate it. If it’s a false positive, suppress with a chant-audit-ignore comment or an allowlist entry.
| Authority | GitHub — About secret scanning |
| Prior art | detect-secrets Base64HighEntropyString (overlaps) · detect-secrets HexHighEntropyString (overlaps) · gitleaks generic-api-key (overlaps) |
Wrangler config (WRG)
Section titled “Wrangler config (WRG)”Lexicon-independent, audit-only (#446) — scans wrangler.toml, Cloudflare Workers’ native deploy config, which the engine cannot otherwise parse (it is not YAML/JSON). No authoring surface: chant does not write Wrangler config, it only reads it for these checks.
WRG001
Section titled “WRG001”*Production environment exposed on .workers.dev — merge-worthy · guidance
Remove workers_dev (or set it to false) for this environment and rely on its custom domain/route instead of the shared public subdomain.
| Authority | Cloudflare Workers — workers.dev |
WRG002
Section titled “WRG002”Credential-shaped key stored in [vars] — merge-worthy · guidance
Move the value out of [vars] and into wrangler secret put \<name> so it isn’t committed to source or visible in wrangler dev/the dashboard.
| Authority | Cloudflare Workers — Secrets |
WRG003
Section titled “WRG003”Observability explicitly disabled — report-only · guidance
Set observability.enabled = true (or remove the override) so Workers Logs are recorded for this deployment.
WRG004
Section titled “WRG004”Unscoped wildcard route — merge-worthy · guidance
Scope the route pattern to the intended zone (e.g. “example.com/”) instead of a bare "" or ”/” that matches every zone on the account.
| Authority | Cloudflare Workers — Routes |
WRG005
Section titled “WRG005”Non-production environment shares a data store with production — merge-worthy · guidance
Give the non-production environment its own KV namespace/R2 bucket/D1 database id instead of reusing production’s.
| Authority | Cloudflare Workers — Wrangler environments |
WRG006
Section titled “WRG006”Static assets served from the project root — merge-worthy · guidance
Point [site].bucket / [assets].directory at a dedicated public output folder, not the project root, so non-public files (config, source maps, .git) aren’t served.
| Authority | Cloudflare Workers — Static assets |
nginx config (NGX)
Section titled “nginx config (NGX)”Lexicon-independent, audit-only (#1979) — parses nginx’s native directive/block config (nginx.conf and .conf files under nginx-ish directories, confirmed by content). No authoring surface: chant does not write nginx config, it only reads it for these checks.
NGX001
Section titled “NGX001”Deprecated TLS protocol enabled — merge-worthy · guidance
Remove SSLv2/SSLv3/TLSv1/TLSv1.1 from ssl_protocols and serve TLSv1.2 and TLSv1.3 only.
| Authority | Mozilla — Server Side TLS |
| Prior art | gixy-ng (maintained Gixy fork) weak_ssl_tls (overlaps) |
NGX002
Section titled “NGX002”Weak cipher suite enabled — merge-worthy · guidance
Remove the RC4/DES/MD5/NULL/EXPORT-class entries from ssl_ciphers and use a modern cipher list (e.g. Mozilla’s intermediate configuration).
| Authority | Mozilla — Server Side TLS |
| Prior art | gixy-ng (maintained Gixy fork) weak_ssl_tls (overlaps) |
NGX003
Section titled “NGX003”Directory listing enabled — merge-worthy · guidance
Remove autoindex on (or scope it to a directory that is genuinely meant to be enumerated) so file listings aren’t served to anyone who asks.
| Authority | CWE-548 — Exposure of Information Through Directory Listing |
NGX004
Section titled “NGX004”alias path traversal — merge-worthy · guidance
End the location prefix with ”/” so it matches the trailing slash of the alias target — without it, a request for “<prefix>../” escapes the aliased directory.
| Authority | Gixy — alias traversal |
| Prior art | Gixy alias_traversal (equivalent) · gixy-ng (maintained Gixy fork) alias_traversal (equivalent) |
NGX005
Section titled “NGX005”Status endpoint with no access restriction — merge-worthy · guidance
Restrict the stub_status location with allow/deny (or auth_basic/auth_request) so connection metrics aren’t public reconnaissance.
| Authority | nginx — ngx_http_stub_status_module |
| Prior art | gixy-ng (maintained Gixy fork) status_page_exposed (overlaps) |
NGX006
Section titled “NGX006”Server version disclosure — report-only · guidance
Add server_tokens off; in the http block so nginx stops advertising its exact version in the Server header and error pages.
| Prior art | gixy-ng (maintained Gixy fork) version_disclosure (equivalent) |
NGX007
Section titled “NGX007”Access logging disabled at server scope — report-only · guidance
Re-enable access_log at http/server scope (silencing a single noisy location is fine) so requests are recorded for incident investigation.
Agent configuration (AGT)
Section titled “Agent configuration (AGT)”Run by chant audit --agents against the agent configuration on a machine — instruction files, MCP servers, skills, plugins, and permissions at system, user, and project scope. Unlike every other family here, these do not fire on repository YAML.
AGT001
Section titled “AGT001”MCP server runs an unpinned package — merge-worthy · guidance
Pin the package spec to an exact version (server@1.2.3), so a new upstream release can’t execute on this machine unreviewed.
| Authority | OSSF Scorecard — Pinned-Dependencies |
AGT002
Section titled “AGT002”Literal credential in agent config — merge-worthy · guidance
Replace the value with an environment reference ($\{TOKEN}) and keep the secret in a secret store — agent config files sync, back up, and get shared.
| Authority | CWE-798 — Use of Hard-coded Credentials |
| Prior art | agent-audit auth-bypass/env-secret-in-config (equivalent) · mcp-audit (APIsec) Secrets Detection (overlaps) · Snyk Agent Scan (formerly mcp-scan) W008 (overlaps) |
AGT003
Section titled “AGT003”MCP server reached over cleartext HTTP — merge-worthy · guidance
Use an https:// endpoint. Tool arguments and results — including data the agent read locally — otherwise cross the network in the clear.
| Authority | CWE-319 — Cleartext Transmission of Sensitive Information |
AGT004
Section titled “AGT004”Remote skill or plugin is unpinned — merge-worthy · guidance
Pin the source to a tag or commit sha, so the instructions the agent follows can’t change upstream without a local edit.
| Authority | OSSF Scorecard — Pinned-Dependencies |
AGT005
Section titled “AGT005”Tool permission granted without constraint — merge-worthy · guidance
Scope the grant to the specific commands you run (Bash(git status:*)), and re-enable the confirmation prompt for dangerous operations.
AGT006
Section titled “AGT006”User-scope config applies to every project — report-only · guidance
Move project-specific instructions, MCP servers, and skills to that project’s own config so they don’t follow you into unrelated repos.
AGT007
Section titled “AGT007”MCP server declared in multiple files — report-only · guidance
Delete the shadowed declarations. The harness silently picks one, so the file you read may not be the one that decides what runs.
AGT008
Section titled “AGT008”Instruction file exceeds the attention budget — report-only · guidance
Move situational guidance into skills that load on demand, so the always-on instructions stay short enough to be followed reliably.
Prior art
Section titled “Prior art”chant’s rules were written against the output chant emits, but much of what they check was checked first by a dedicated tool. Each rule above that has a counterpart names it under Prior art, with the upstream rule id and how the two relate.
equivalentis the same condition at the same scope.overlapsshares the core condition, with one side narrower or broader, or expressed for a different dialect of the same control.extendsmeans chant checks a strict superset of the upstream rule.
This is credit rather than authority, and it never changes a rule’s tier or category. A credit counts once per upstream rule cited, so a chant rule that names two zizmor audits adds two.
| Tool | Kind | Licence | Credits |
|---|---|---|---|
| Checkov | scanner | Apache-2.0 | 66 |
| KICS | scanner | Apache-2.0 | 50 |
| zizmor | scanner | MIT | 38 |
| cfn_nag | scanner | MIT | 20 |
| GitLab CI/CD YAML reference | specification | CC-BY-SA-4.0 | 20 |
| AWS Guard Rules Registry | scanner | Apache-2.0 | 19 |
| Fairwinds Polaris | scanner | Apache-2.0 | 18 |
| KubeLinter | scanner | Apache-2.0 | 17 |
| kube-score | scanner | MIT | 15 |
| PSRule for Azure | scanner | MIT | 13 |
| Google Cloud Policy Library | scanner | Apache-2.0 | 12 |
| poutine | scanner | Apache-2.0 | 11 |
| OpenSSF Scorecard | scanner | Apache-2.0 | 11 |
| cfn-lint | scanner | MIT-0 | 10 |
| gitleaks | scanner | MIT | 10 |
| octoscan | scanner | GPL-3.0 | 10 |
| detect-secrets | scanner | Apache-2.0 | 9 |
| tflint-ruleset-terraform | scanner | MPL-2.0 | 9 |
| actionlint | scanner | MIT | 8 |
| TruffleHog | scanner | AGPL-3.0 | 8 |
| gixy-ng (maintained Gixy fork) | scanner | MPL-2.0 | 5 |
| kubesec | scanner | Apache-2.0 | 5 |
| tflint-ruleset-redeploy | scanner | 0BSD | 5 |
| Datree | scanner | Apache-2.0 | 4 |
| HashiCorp Terraform style guide | specification | n/a | 4 |
| helm lint | vendor-validator | Apache-2.0 | 4 |
| choudoufu | scanner | MPL-2.0 | 3 |
| Flux Kustomization API reference | specification | n/a | 3 |
| hadolint | scanner | GPL-3.0 | 3 |
| HashiCorp reference Sentinel policies | specification | MPL-2.0 | 3 |
| tfsec | scanner | MIT | 3 |
| agent-audit | scanner | MIT | 2 |
| ARM Template Toolkit (arm-ttk) | scanner | MIT | 2 |
| AWS prescriptive guidance for Terraform | specification | n/a | 2 |
| Bicep linter | scanner | MIT | 2 |
| Dockle | scanner | Apache-2.0 | 2 |
| Google Cloud Terraform best-practices series | specification | n/a | 2 |
| mcp-audit (APIsec) | scanner | MIT | 2 |
| tflint-ruleset-avm (Azure Verified Modules) | scanner | MIT | 2 |
| Snyk Agent Scan (formerly mcp-scan) | scanner | Apache-2.0 | 1 |
| chart-testing (ct) | vendor-validator | Apache-2.0 | 1 |
| Gixy | scanner | MPL-2.0 | 1 |
| Pluto | scanner | Apache-2.0 | 1 |
| Semgrep Registry rules | scanner | Semgrep Rules License v1.0 (proprietary, not an SPDX id) | 1 |