Zennoxa Shield
Coverage, in full

Every layer, every language, and where it stops.

Shield runs nine analysis layers from one offline binary — over your code, your dependencies, the images you push, the infrastructure you declare and the pull requests you merge. This page lists exactly what each layer covers, which languages get deep rules versus lighter preview coverage, and the gaps we haven’t closed. Every claim is ground-truthed against the engine.

SAST · your code

340 rules across 24 languages

Fourteen languages get comprehensive deep rule coverage; the rest get lighter preview rules. Each bar is the real rule count in the engine — nothing rounded up.

rules per language
JavaScript / TypeScript36
Ruby26
Python26
Java22
PHP22
C#21
C++21
C21
Kotlin18
Swift17
Rust17
Dart14
Go12
Shell6
PowerShell6
Objective-C6
Groovy6
VB.NET6
Scala4
Perl4
Lua3
deep coverage preview
Also parsed

Smart contracts: Solidity, Vyper. Query: SQL. Templates: JSP, ERB, Razor, Twig, Jinja, FreeMarker. Config: Dockerfile, Helm, CI-YAML.

7 framework packs
ExpressNext.jsReactRailsDjango / Flask / FastAPISolana / AnchorCI/CD

Spring rules live inside the Java pack.

What it can’t do

Regex + intra-file taint + dataflow (constant-fold, key-sensitive) — not full AST, not interprocedural yet. Taint that crosses a method boundary is a known blind spot, which is why SQL injection is our weakest OWASP category (see below).

Dependencies (SCA) · your code

10 ecosystems, 18 manifest formats

ecosystem → lockfiles
EcosystemManifests / lockfiles parsed
npmpackage.json, package-lock.json, yarn.lock, pnpm-lock.yaml
PyPIrequirements.txt, Pipfile.lock, poetry.lock
Gogo.mod
RubyGemsGemfile.lock
Mavenpom.xml, gradle.lockfile
crates.ioCargo.lock
Packagistcomposer.lock
NuGetpackages.lock.json, packages.config, *.csproj
Pubpubspec.lock
Hexmix.lock

Advisories come from OSV.dev (GHSA / CVE / PYSEC aliases). It resolves your actual installed versions, so it won’t flag packages you’ve already patched. Emits a CycloneDX 1.4 SBOM (see below).

What it misses. go.sum isn’t parsed (go.mod declared versions only). pom.xml parent/BOM-inherited versions are skipped. No Swift Package.resolved, Conda, Bazel, Bun or Nix yet.
Secrets · your code

26 patterns + a high-entropy fallback (27 detectors)

Cloud

AWS key + secret, Azure connection string, GCP service-account key

Version control

GitHub (classic / fine-grained / OAuth), GitLab, npm

Payments & comms

Stripe, Twilio, SendGrid, Slack (webhook + token), Discord

AI

OpenAI, Anthropic, Linear

Private keys

RSA, PKCS#8, OpenSSH, PGP

Other

DB connection strings, JWT signing keys, generic API-key / password, high-entropy unknowns

Tuned hard against false positives. Guards like connStringHasRealPassword, pemHeaderHasKeyMaterial, valueIsRealSecret and notSQLPasswordClause, plus optional live credential validation, keep placeholder and template secrets out of your results.
Containers · what you ship

Container images, from any registry

25 config checks, always on

Every Dockerfile, docker-compose and Kubernetes manifest in a connected repo is scanned — 14 Dockerfile/compose rules and 11 Kubernetes rules — plus 6 image-config rules that read the pushed image’s metadata.

example findings
Dockerfile Runs as root — no USER directiveHIGH
Dockerfile Base image pinned to :latestHIGH
deploy.yaml securityContext.privileged: trueHIGH
deploy.yaml Added capability SYS_ADMINHIGH

Pull & scan a pushed image

Point Shield at an image in any registry. It reads the manifest, config and build history — not the multi-gigabyte layer blobs — so it stays fast and light. Private repos and Harbor robot accounts included.

HarborDocker HubGHCRGitLabOCI / v2
$ shield image-scan ghcr.io/acme/api:1.4 --format sarif

Opt-in: OS-package CVEs in the layers

When you want the layer contents too, add a flag and Shield inventories the installed OS packages and checks them for known CVEs:

$ shield image-scan … --os-cve  # pure-Go: 6 distro families (dpkg/apk/rpm) → OSV
$ shield image-scan … --cve  # delegates to Trivy if it’s on PATH
What it can’t do. The default image scan reads image config, not layer filesystems — application code inside the image isn’t re-scanned. Layer OS-package CVEs are opt-in (--os-cve / --cve), not part of the default pass.
Infrastructure as Code · what you ship

16 IaC checks across three formats

Terraform 6 · Kubernetes 7 · CloudFormation 3

Every Terraform file, Kubernetes manifest and CloudFormation template in a connected repo is scanned automatically — catching the misconfigs that quietly become breaches: wildcard IAM, public buckets, privileged pods, unencrypted storage.

What it can’t do. IaC is string and regex, not a full HCL/YAML graph parse. CloudFormation is filename-gated. There’s no real Helm template rendering yet (helm/ files are matched as Kubernetes YAML).
example findings
main.tf Wildcard IAM policyHIGH
s3.tf Public S3 bucketHIGH
deploy.yaml Privileged podHIGH
template.yaml RDS storage unencryptedHIGH
PR gating · what you ship

Gate every pull request, on what matters

From your CI job, shield gate-report posts a pass/fail commit status and a PR / MR comment back to your git provider. On GitHub it also posts a Check Run with inline file-and-line annotations on the new findings a PR introduces (up to 50). Break the build on what the priority engine says actually matters — not on a wall of noise.

Providers

GitHubGitLabBitbucketAzure DevOps

Reports export as text, HTML, JSON and SARIF 2.1.0. The CLI exits 0 on pass and 2 on a gate violation, so CI stops the build; --staged scopes a pre-commit hook to staged files only.

How it fits. gate-report runs from your pipeline and posts back to the provider. It’s one-directional (CI → provider), and a provider API hiccup never fails your scan — it logs and moves on.
$ shield scan . --fail-on-severity high
$ shield gate-report --provider github
# → commit status: fail (2 above threshold)
# → PR comment + Check Run posted
# → results.sarif written · exit 2
Reachability & priority · intelligence

How the priority score is computed

score(0–100)
score = CVSS ×0.30 + EPSS ×0.30 + KEV ×0.25 + reachability ×0.15
SignalWeightSource
CVSS×0.30severity, NVD 0–10
EPSS×0.3030-day exploit probability, FIRST.org
KEV×0.25CISA known-exploited (boolean)
reachability×0.15is the finding’s file reachable from an entry point

Tiers: ≥80 critical · ≥60 high · ≥40 medium · ≥20 low.

Reachability here is a file-level signal (is the finding’s file reachable from an entry point), built from an import-graph pass for Go, JavaScript/TypeScript and Python. For dependency CVEs it goes a step further — scoring whether the vulnerable package is merely imported versus whether a known-vulnerable symbol is actually referenced in your source. It is separate from the intra-file taint the SAST engine uses to connect a source to a sink — we don’t conflate the two.

DAST pre-check · intelligence

A pre-deploy check, in two parts

Shield’s DAST layer is a pre-check, not a full dynamic scanner. Part one runs inside every scan; part two runs when you point it at a live URL.

1 · Static config pre-check always on

Shield reads your nginx / apache / .htaccess config and source and flags 11 web-exposure mistakes (DAST-001…011): weak or disabled TLS, wildcard CORS, non-HTTPS endpoints, missing security headers, directory listing, open redirects, disabled CSRF, insecure cookies, no rate limiting, and debug mode left on.

2 · Live-endpoint probe opt-in

Aim Shield at a running endpoint — your staging host, before a deploy — and it probes for the mistakes that only appear at runtime, across four families:

7 security headers

HSTS, CSP, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy and Permissions-Policy — present, and set safely.

TLS configuration

Flags TLS below 1.2, and certificates that are expired or expiring within 30 days, on the live endpoint.

8 sensitive paths

Probes /.env, /.git/config, /debug, /server-status, /phpinfo.php, /wp-admin/, /actuator and /graphql, and reports any that answer 200 without auth.

HTTP → HTTPS

Checks the plain-HTTP variant actually redirects to HTTPS instead of serving content in the clear.

This is a pre-check, not a DAST suite. The live probe hits only the URL you give it — it does not crawl the app, fuzz inputs, inject payloads or handle auth (unauthenticated GET only). Requests are SSRF-guarded — private-network and DNS-rebinding targets are blocked — with a 10-second timeout. Think of it as a last look before you ship.
Grades & gate · intelligence

Two grades, one gate

Every scan produces two independent A–F grades on the same 0–100 scale — one for security risk, one for maintainability — and either can gate a pull request.

Security grade

Starts at 100 and deducts a penalty per finding — −45 critical, −18 high, −6 medium, −1.5 low — each scaled 0.6–1.4× by that finding’s priority (exploitability). A single critical floors the grade at F.

Code grade

A maintainability read from lines of code, a complexity proxy, duplicate blocks (≥6 lines), long functions (>60 lines), deep nesting and a test-ratio signal.

Don’t confuse the two. The code grade is maintainability only — a clean A there says nothing about vulnerabilities. Security posture is the security grade and the findings, not the code grade. Complexity is a keyword-based proxy, not true cyclomatic complexity.
score → grade
GradeScore (0–100)
A≥ 90
B≥ 80
C≥ 65
D≥ 50
F< 50

A configurable quality gate (per org or per project, scoped to branches like main or release/*) can fail the build on a severity count, a specific CWE, a minimum grade or a minimum score.

SBOM · intelligence

A bill of materials in 2 formats

CycloneDX 1.4 · SPDX 2.3

From the versions Shield resolved out of your lockfiles, shield sbom emits a machine-readable inventory in both CycloneDX 1.4 (the default) and SPDX 2.3 — each component carrying a Package URL (PURL) so downstream tooling can identify it exactly, deduplicated across manifests. Runs fully offline.

CycloneDX 1.4SPDX 2.3PURLs
What it does and doesn’t carry. It inventories the declared dependencies from your lockfiles. It does not include component hashes, and license fields are emitted as NOASSERTION — offline generation doesn’t populate them. Treat it as a dependency inventory, not a license audit.
Connect · integrations

Where it runs

Repositories

Connect a public or private repo on GitHub (native App), GitLab, Bitbucket or Azure DevOps. Webhooks auto-scan on push for GitHub, GitLab and Bitbucket; self-hosted GitHub Enterprise and GitLab are supported.

CLI, offline

One self-contained Go binary, 12 commands (scan, image-scan, sbom, gate-report, hooks…). Secrets, SAST, container and IaC run fully offline; dependency CVEs (--deps) reach OSV over the network.

Output

Four formats: a readable table, JSON for your tooling, SARIF 2.1.0 for code scanning, and a full-page HTML report.

Deep CLI, API and CI reference lives in the docs.

AI assist · one helper, not a layer

Plain-language explanations, on review

A local model (Ollama / Qwen) writes a plain-language explanation and a suggested fix for each finding, which you review. When the model is off or unreachable it falls back cleanly to 20 hand-written templates covering the common rule types, so you always get context. Everything from the scanned repo is neutralized against prompt injection before it reaches the model.

It runs on your side, it is not one of the nine scan layers, and it never patches your code or opens a pull request. A separate, fully deterministic assistant answers questions about findings from the rule catalog and your own finding summary — no scanned source leaves your tenant. It explains; you decide.
OWASP Benchmark v1.2 · proof

Per-category scores, zeros included

0.582Benchmark Score
92.5%precision
64%recall
2740Java cases
per-category (Youden’s J)
CategoryScoreStatus
weak random1.000● detected
insecure cookie1.000● detected
crypto0.808● detected
hash0.690● detected
XSS0.516● detected
LDAP injection0.499● detected
XPath injection0.467● detected
command injection0.451● detected
path traversal0.445● detected
SQL injection0.303our current laggard
trust boundary0.237● detected
Read this honestly. The OWASP Benchmark tests Java source analysis only. It does not exercise Shield’s Secrets, SCA, Container or IaC layers, or any other language. 0.582 is the Java-SAST subset of the 340-rule engine, not the whole product. Two categories (LDAP injection, insecure cookie) are still 0.000. They’re in the table above.
$ git clone --depth 1 https://github.com/OWASP-Benchmark/BenchmarkJava
$ OWASP_BENCH=$PWD/BenchmarkJava make bench-owasp

Measured on release v0.3.0 · commit 043d1cf · 2026-08-04 · 340-rule build.

Zennoxa Shield Features: 340 rules, 24 languages, 5 scan layers