Engineering Log
We're Automating CMMC 2.0 Hardening — and We Won't Trust It Until Our Own Box Survives It
ScopeHunter tracks CMMC 2.0 maturity for its users. Here's what building real automation for it actually looks like, including the part where we run it against ourselves first.
Scope: what this covers, and what it doesn't
Two different things get run together in this space, and they have opposite data-handling answers, so both are worth being blunt about before anything else.
The hardening automation runs on your infrastructure. It's a Salt formula applied to your own systems. By default it doesn't call home, and ScopeHunter never sees what lives on those boxes — so nothing stops you running it on hosts that sit inside a CUI enclave.
Reporting results back to us is opt-in, and you choose how much. The formula can send its findings here so evidence updates itself instead of someone re-typing it. There are four levels, each a superset of the last, set in your own pillar:
- off — nothing is transmitted, even with a token configured.
- results (the default) — check and control verdicts only: a list of check identifiers, each with a pass, fail or skipped result.
- findings — adds what the host observes about itself: running services, listening sockets, firewall rules, and which published security advisories apply to its installed software. The advisory matching runs on the host, against public data we send it; only the verdicts come back.
- inventory — adds the full installed-package map. Everything above describes the host; this level enumerates it. In exchange we can tell you which of your hosts a CVE published this morning affects, without waiting for them to report again.
Worth knowing before you raise it on a host inside an enclave. At results, each check carries a detail string from its own output, which can name a port, a path, a service or an account. At findings, you are sending a description of what runs on the box and what it exposes. At inventory, you are sending an exact patch level for every package installed — useful to you, and useful to anyone attacking you. None of that is CUI, but on a system that holds CUI it is a description of that system's security posture, and each step up deserves a deliberate decision rather than a default. That is why the default is the lowest level that reports anything at all, and why the choice is yours rather than ours.
The boundary rule this rests on, stated plainly: a system assessed at CMMC Level 2 may transmit CUI only to another system authorized to protect it at Level 2 or higher. Sending CUI — or data that describes a CUI system's security configuration — to a system that hasn't been assessed to that standard (a commercial SaaS, a lower-tier or non-CMMC system, anything outside your authorization boundary) is a spillage, not a shortcut. ScopeHunter is commercial-scope and sits outside any CUI boundary — which is exactly why reporting is off by default and why we spell out what the detail string can contain. The moment a Level 2 host reports here, data is leaving your assessed boundary, and it is on you to ensure nothing in that stream is CUI. We hold none and the design keeps it that way, but honoring the boundary is your call to make deliberately, which is why the switch is yours and starts off.
ScopeHunter itself is commercial-scope and holds compliance metadata only. ScopeHunter is not an authorized system for storing actual Controlled Unclassified Information (CUI) or Federal Contract Information (FCI). Use this tool to document and track your compliance program — never enter actual CUI, FCI, or other controlled content into any field here. That isn't only a request: every compliance surface in the product is gated behind a one-time, org-level attestation, and answering "yes, we need to store real CUI or FCI here" is a hard stop rather than a warning you can dismiss. Your tracking can still live with us; the controlled content has to stay in a separately authorized system.
And on the certification question, since it's the one most often blurred: this is hardening automation and program tracking, not a path to a certificate. CMMC Level 2 certification is awarded after an assessment by an authorized C3PAO, against your system and your SSP. Nothing here substitutes for that — a distinction worth confirming with any tool you evaluate, ours among them.
That question has a wrinkle as of August 2026: the Department of Defense has suspended CMMC Phase II third-party assessment requirements, so there is no immediate need to engage a C3PAO. It would be easy to read that as pressure coming off. It is not. The suspension targets third-party auditing — Phase I self-assessment requirements remain fully active and legally binding, NIST SP 800-171 is still a contractual requirement under DFARS 252.204-7012, and the SPRS score is still a number submitted to the government. The freeze changes who checks, not what is required.
Which, if anything, raises the stakes for a tool like this one. An assessor is a second pair of eyes: a company being assessed has someone to catch an overstatement before it becomes a false claim. A self-attesting company does not, and the officer who signs carries it under the False Claims Act. Under an audited regime, a tool that flatters its user produces an embarrassment an assessor corrects. Under self-attestation, it produces a liability. That is the reason this platform reports unassessed controls as costing full weight rather than quietly leaving them out of the denominator — and why a number it cannot evidence is one it will not display.
If you've used ScopeHunter's Compliance tools to track CMMC 2.0 or SOC 2 milestones (preview the workspace — controls, tests, evidence, and policies in one place), you already know the gap we're talking about here: it's easy to track that a control needs to be met, and much harder to actually enforce it on a real box. So a sister project — an infrastructure-hardening Salt formula covering the OS-enforceable subset of NIST SP 800-171, the requirements underneath CMMC Level 2's technical practices — has been getting built out, and we're documenting the process honestly, the same way we label our own feature maturity on the status page: what's live, what's staged, and what's deliberately not turned on yet.
Not every control is code's job
Of NIST SP 800-171's 110 requirements, roughly half are organizational — personnel screening, physical security, written incident response plans — and staple exactly zero lines of Salt to anything. We use the same three honest labels our own compliance tracking uses internally for this:
Of those 110 requirements, 47 are enforceable at the operating-system layer. All 47 have a real Salt state behind them — not most of them, and not approximately: the formula's own test suite fails the build if a requirement its control map calls automatable has no state implementing it. The other 63 are organizational and are labeled Manual, not folded into a percentage. We used to publish a figure here instead ("~95% of the automatable subset"). It was a hand estimate, it was wrong in both directions, and it was exactly the kind of number this page criticizes elsewhere. Counts you can recompute from the control maps are harder to round.
Three operating systems have had the formula genuinely applied, which is a different claim from rendering cleanly against them:
- Debian 13 — two live production hosts, one of them serving this page.
- Rocky Linux 9.8 (Red Hat family) — first full apply on 2026-08-10. It found eight defects that static checking could not see, including a control that failed on every Red Hat host because it matched a commented-out line in the stock sudoers file.
- Windows Server 2022 — Level 1 and all eight Level 2 families, validated on a real host with each control broken on purpose to confirm it notices.
Three things are built but not validated, and we would rather say so than let the list above imply them: Windows workstations (implemented, never run on a real client OS), domain-joined Windows (controls owned by Group Policy deliberately refuse to apply locally, and the verify-only paths are unwritten), and Ubuntu (same package family as Debian, not separately exercised — we listed it here before, on the strength of family resemblance rather than a run).
We run it on our own box before we ship it to anyone else
First, the model, since it's the whole point: this is automation you run on your own gear. We ship the Salt formula; you apply it inside your own boundary, under your own IAM, on your own schedule. We never run it on your systems and never reach into them — the same posture as the "doesn't call home" commitment above.
What we do run it on is ourselves. The formula is applied against two real, live systems today — one of them is the box serving this page right now. Not a lab VM built for a demo: real production infrastructure, with our own SSH access, our own IAM, our own uptime on the line.
That's not a marketing detail — it's how the bugs actually got caught: a wrong package name for a password-quality tool on Debian, a stale firewall rule that would have quietly left a port exposed after a "fix," a false positive against a cloud provider's own managed sudo configuration. Small, boring bugs, individually. The kind that pass code review and fail in production. Every one of them got caught on our box first, instead of surfacing in your environment after you'd already trusted it.
The control we refused to ship on a guess
The single highest-risk change in the whole formula is also one of the simplest-sounding requirements: limit failed login attempts. On one OS family, the standard way to wire that in touches a PAM authentication stack's own internal control-flow logic. Get one number wrong there and the failure mode isn't "attackers get one more try" — it's every login, including root's, denied at once, on every service that uses that stack.
We wouldn't ship that from documentation and hope. Instead, we found the actual system tool responsible for composing that stack safely, patched a copy of it to run against scratch, throwaway directories — never a live system's real configuration — and used it to prove, not assume: a correct password reaches the accept path, an incorrect one is denied immediately, and removing the change cleanly reverts to the original stack. Multi-factor authentication for privileged access got the same treatment: fully built, deliberately left switched off behind an explicit two-stage flag until every account is actually enrolled and a non-SSH recovery path is confirmed open.
Neither is enabled in enforcement mode on our own production boxes yet, on purpose. Staged and verified isn't the same claim as "flipped on everywhere," and we're not going to blur that distinction just because the code is done.
Why this matters if you're the one being assessed
A compliance report that can't verify something from inside a system — MFA enforced by your cloud provider's identity layer instead of the OS, say — shouldn't quietly mark it "met" either. The honest move is to say exactly what was checked, flag what wasn't, and point at where the rest of the evidence actually has to live: your SSP, with real proof behind it. That's the same standard ScopeHunter holds its own feature list to, and it's the standard this formula is being held to before it's trusted with anyone else's audit.
That holds whether you're a contractor whose C3PAO assessment is on hold, one self-attesting under Phase I, or a commercial organization adopting 800-171 as a security baseline with no CUI obligation at all. The technical work is the same either way — the same accounts locked down, the same logging, the same firewall posture. What differs is the evidence burden and who eventually checks it. A good deal of what gets sold as "CMMC compliance" is really just competent Linux hardening with a certificate stapled to the end, and it's worth knowing which half you're buying.
Get started on ScopeHunter → Preview the compliance workspace Compliance & security FAQ Build log Want help implementing it? Talk to L-IT