The free compliance library — a fast, browser-friendly home for DISA STIGs, SCAP benchmarks, NIST 800-53 controls, CCIs, RMF reference data, and a 20-family RMF plan generator.
Live: cyber.trackr.live
Stack: Symfony 7.4 LTS · PHP 8.2+ · Twig 3 · custom CSS design system · jQuery 3 + Bootstrap 5 + DataTables for interactive surfaces
License: GNU AGPL-3.0-or-later — see License and NOTICE.md for the full attribution
cyber.trackr.live is a single-developer side project that turns the official DoD compliance corpus into something you can actually browse:
- 1,076 STIG titles across 3,970 version-instances (DISA Security Technical Implementation Guides)
- 91 SCAP benchmarks across hundreds of version-instances (XCCDF + OVAL automation content)
- NIST SP 800-53 revisions r4 and r5, fully cross-linked, with an
r4 → r5mapping page that harvests withdrawal targets from r5's own catalog - 14 control baselines loaded from OSCAL profiles (NIST L/M/H/Privacy + FedRAMP L/M/H/LI-SaaS + CNSSI 1253 L/M/H/Privacy/Classified/Space)
- The complete CCI list (Control Correlation Identifiers, both 2014 and 2024 catalogs)
- A side-by-side STIG version diff engine plus a per-version Digest of Updates with an Atom feed
- A 20-family RMF Plan Generator (CM, AC, AU, IA, IR, CP, SI, CA, SC, RA, SA, PE, PS, MA, MP, AT, PL, SR, PT, PM) that produces assessable Word documents with ODV substitution and enhancement-tailoring traceability
- A CKL / CKLB viewer that runs entirely in the browser, edits any field, applies SCAP scan results, and re-exports CKLB
- A baseline coverage heat map (20 families × 4 NIST baselines) for scoping
- A REST API that returns the same data as JSON
It exists because the official sources — cyber.mil, the DISA STIG Viewer, the NIST 800-53 PDF — are heavy, hard to link to, and don't cross-reference each other. This site stitches them together and keeps them in sync.
DoD compliance work involves jumping between four authoritative sources:
| Source | Format | Pain |
|---|---|---|
| DISA STIGs | XCCDF XML zips | One zip per STIG, no search across versions, no permalinks |
| DISA SCAP | XCCDF + OVAL XML | Same shape as STIGs but a separate download silo |
| NIST 800-53 | Authoritative PDF + OSCAL | Hard to link to a single control |
| DISA CCI list | One huge XML | Useless without the STIG mappings |
Cyber Trackr unifies them:
- Every STIG, SCAP benchmark, and 800-53 control has its own permalink.
- Cross-references between rules ↔ CCIs ↔ controls are followed automatically.
- The browser does the heavy lifting for editor-style tools (CKL viewer, plan wizards); the server just renders read-only HTML and JSON over a flat XML/JSON dataset (no database, no user accounts).
- The whole thing is a static-feeling site that loads in a single round trip and reads cleanly on mobile.
Cyber.Trackr.Live/ # ← this repo
└── cyber.trackr.live/ # ← the Symfony app (mapped to the live domain)
├── bin/ # Symfony console entrypoint
├── config/ # Symfony bundle + service config
├── public/ # Web root (index.php, css/, js/, fonts/, images/, og/)
├── resources/data/ # The compliance corpus (XML + JSON tocs + plan schemas)
├── src/ # Application code
│ ├── Command/ # Console commands (toc + index + version + deploy)
│ ├── Controller/ # Route handlers
│ ├── Service/ # Toc builders, overlay loader, mappers, plan + search engines
│ └── Twig/ # Custom Twig filters
├── templates/ # Twig views
├── tests/ # Test bootstrap (suite is minimal)
├── translations/ # i18n scaffolding
├── composer.json
└── TODO.md # Active backlog + deferred items
The repo root only holds the app directory. The two-level layout exists because the on-disk path cyber.trackr.live/ maps to the production virtual host, so deploys are a git pull and nothing else.
All compliance data lives under cyber.trackr.live/resources/data/. Sizes as of last sync:
| Path | Source | Size | Notes |
|---|---|---|---|
stig/ |
DISA STIG releases (XCCDF XML) | ~1.2 GB | Per-version XML files, named U_<title>_V<n>R<m>_STIG.xml. Lazy .digest.json files live alongside (gitignored, regenerated from source). |
scap/ |
DISA SCAP benchmarks (XCCDF + OVAL) | ~444 MB | Same naming pattern as STIGs |
cci/U_CCI_List.xml, U_CCI_List_2024.xml |
DISA CCI catalog | ~5 MB | Both catalogs kept; new mappings live in 2024 |
rmf/800-53v4-controls.xml, 800-53v5-controls.xml |
NIST SP 800-53 | ~3 MB | Hand-converted from OSCAL. r5 carries <status>withdrawn</status> + <incorporated-into> for retired controls — harvested by the r4 → r5 mapping page. |
rmf/r4-to-r5-mapping.json |
Curated overrides | <2 KB | Optional rationale text on top of the mechanical r4 ↔ r5 inference; empty by default. |
overlays/*_profile.json |
OSCAL Profile JSON | ~3 MB | 14 baseline profiles (NIST + FedRAMP + CNSSI 1253). Drop a new one in and it appears in chips, plan wizards, and the baseline heat map automatically. |
plans/*.json |
Plan-generator schemas | ~500 KB | One file per RMF family (20 total) plus _shared.json. Schema-driven — adding a family is a JSON file, not a code change. |
800-53r4.json |
NIST SP 800-53 r4 | ~3.6 MB | JSON form for the API |
stig_toc.json, scap_toc.json |
Generated indexes | ~2 MB combined | See Updating the data |
vulns_toc.json |
IAVM/CTO/CVE refs harvested from STIG + SCAP XML | <1 MB | Generated by app:vulns:rebuild-toc. Feeds /vulnerabilities/iavm. |
kev/known_exploited_vulnerabilities.json |
CISA KEV catalog mirror | ~1.5 MB | Generated by app:kev:refresh. Feeds /vulnerabilities/kev. |
companion_zip_index.json |
XCCDF-XML → companion-ZIP map | ~150 KB | Built by app:companion-zip:rebuild-index. Resolves DISA's inconsistent ZIP filenames (e.g. U_ASD_V6R4_STIG.zip) back to the canonical STIG title. Feeds the Supporting documents section on STIG view pages. |
bulk_download_index.json |
Per-version XML/ZIP presence + size | ~1.1 MB | Built by app:bulk-download:rebuild-index. Lets the bulk-download table render without stat()ing thousands of files per request and powers the 500-MB chunk planner. |
search/ |
Inverted search index | up to 100+ MB | Sharded JSON. Generated by app:search:rebuild. Gitignored. |
sync_status.json |
Manual sync timestamp | <1 KB | Drives the footer's "DISA sync · NIST sync" line |
zips/ |
Original DISA download zips | ~2.1 GB | Source-of-truth archive; *Compilation*.zip is gitignored |
The *_toc.json files are pre-computed indexes (title, version, release, release date, severity counts) so the index pages don't have to parse the XML on every request.
| Route | Page |
|---|---|
/ |
Homepage — hero, recent STIGs (top 100 by release date), trust strip with live counts, common-workflows chip strip |
/stig |
Full STIG library, filterable, paginated 50/page — with a collapsed Bulk download panel for grabbing any combination of XML + companion ZIP across every version |
/stig/bulk |
Standalone bulk-download view — virtual-scrolled table of all 3,970 versions with independent XML / ZIP checkbox columns, streams ≤500 MB chunks sequentially |
/stig/{title}/{version}/{release} |
Single STIG view — overview, all rules, severity mix, CCI cross-refs, Supporting documents (DISA companion PDFs when archived), Digest of Updates vs the previous version |
/stig/{title}/{v1}/{r1}/{v2}/{r2} |
Side-by-side diff between two versions of the same STIG |
/stig/{title}/{version}/{release}/download |
Original DISA STIG XCCDF XML |
/stig/{title}/{version}/{release}/companion.zip |
DISA companion bundle (overview, revision history, readme PDFs) — streamed from the zips/ archive when present |
/stig/{title}/{version}/{release}/companion.pdf?file=… |
Individual PDF entry from the companion bundle |
/stig/feed.atom |
Atom feed of the 25 most recent STIG versions with full digests (added/removed/severity-changed/content-changed rules) |
/scap |
Full SCAP benchmark library, paginated 50/page |
/scap/{title}/{version}/{release} |
Single SCAP view — XCCDF rules, OVAL definitions, severity mix |
/scap/{title}/{version}/{release}/download |
Original DISA zip |
/cci |
Full CCI list (DataTables, ~3,000 rows) |
/rmf/5 |
NIST 800-53 r5 controls with baseline-membership chips (NIST + FedRAMP + CNSSI 1253) |
/rmf/4 |
NIST 800-53 r4 controls |
/rmf/4-to-5 |
Side-by-side r4 → r5 mapping with withdrawal targets harvested from r5's own catalog metadata |
/baselines |
20×4 coverage heat map — which families contribute heaviest at NIST Low / Moderate / High / Privacy |
/vulnerabilities |
Vulnerabilities landing — KEV summary stats, IAVM/CTO/CVE harvest stats, DoD-users blurb, links into the catalogs |
/vulnerabilities/kev |
Full CISA KEV catalog (DataTable, ~1,500 entries) |
/vulnerabilities/kev/{cve} |
Single KEV entry — CISA description, BOD 22-01 due date, related STIG/SCAP rules, related 800-53 controls |
/vulnerabilities/iavm |
IAVMs / CTOs harvested from the public STIG/SCAP corpus |
/vulnerabilities/iavm/{id} |
Single bulletin with rule backlinks and co-occurring CVEs |
/vulnerabilities/cve/{cve} |
Unifying CVE view — works whether or not the CVE is in KEV; joins KEV info + STIG/SCAP refs |
/search/{query} |
Cross-corpus search (STIGs, SCAPs, controls, CCIs, vulns) |
/plans |
Plan Generator landing page — 20 family cards, PT and PM badged as privacy-baseline plans |
/plans/{family} |
Per-family wizard — system metadata, baseline picker (grouped by source with friendly labels), structured family questions, per-control cards with ODV substitution + enhancement disposition pickers |
/plans/{family}/preview |
HTML preview of the rendered plan (POST) |
/plans/{family}/download |
DOCX export via PHPWord (POST) |
/ckl-viewer |
Browser-only CKL/CKLB editor with editable asset header, severity stat cards, status donut + severity-status bar charts (hand-rolled SVG), per-rule editor, SCAP XCCDF overlay, CKLB export |
/report_generator |
Legacy CKL/CKLB → POAM/RAR converter (predates the dedicated CKL viewer) |
/contactus, /mission |
Contact + about |
The API mirrors the browseable library at /api/... and returns JSON. No auth, no rate limiting, no headers required.
| Endpoint | Returns |
|---|---|
GET /api |
Summary of available endpoints + dataset counts |
GET /api/stig |
List of all STIG titles + versions |
GET /api/stig/tip |
Just the latest version of every STIG (the "tip") |
GET /api/stig/{title}/{version}/{release} |
Full rule list for a single STIG |
GET /api/stig/{title}/{version}/{release}/{vuln} |
A single vulnerability detail (V-ID) |
GET /api/scap |
List of all SCAP benchmarks |
GET /api/scap/{title}/{version}/{release} |
Full rule list for a benchmark |
GET /api/scap/{title}/{version}/{release}/{vuln} |
Single SCAP vuln |
GET /api/rmf/5 |
NIST 800-53 r5 control list |
GET /api/rmf/5/{con} |
Single 800-53 r5 control (e.g. AC-2) |
GET /api/rmf/4 |
NIST 800-53 r4 control list |
GET /api/rmf/4/{con} |
Single 800-53 r4 control |
GET /api/cci |
Full CCI list |
GET /api/cci/{item} |
Single CCI (e.g. CCI-000196) |
GET /api/vulns |
Vulnerabilities root — KEV summary, corpus stats, related-control map, endpoint index |
GET /api/vulns/kev |
Full CISA KEV catalog (mirrored locally) |
GET /api/vulns/kev/{cve} |
Single KEV entry + corpus backlinks |
GET /api/vulns/iavm |
IAVMs and CTOs from the STIG/SCAP corpus |
GET /api/vulns/iavm/{id} |
Single bulletin with rule backlinks |
GET /api/vulns/cve/{cve} |
Unified CVE view (KEV record if any + corpus refs) |
GET /plans/{family}/schema.json |
Per-family plan schema (consumed by the wizard JS but readable directly) |
The cyber.mil download catalog is scraped via a single DisaCatalogSyncer service exposed three ways:
- Console:
bin/console app:disa:sync-stigandbin/console app:disa:sync-scap(the dailybin/refresh-data.shcron calls both). - Web routes:
/stig/disa_downloadand/scap/disa_downloadfor interactive admin runs — stream live progress to the browser as the sync proceeds. - Dry-run: both console commands accept
--dry-runto fetch the catalog and report what would be downloaded without writing anything to disk. Useful for verifying the API hasn't changed.
New ZIPs land in resources/data/zips/ and any XCCDF XML inside is extracted into resources/data/{stig,scap}/. Existing files are skipped, so the steady-state cron cost is small (only new bundles).
The plan generator sits at the assessability floor — produced plans aren't just structurally compliant, they prompt the assessor-relevant content the user needs to author:
- Schema-driven. Every family is a JSON file under
resources/data/plans/. Adding a new one is data, not code. - ODV substitution. Catalog statement text like
[Assignment: organization-defined frequency]is parsed out, surfaced as inputs, and substituted at render time. Position-indexed IDs survive catalog updates. - Enhancement tailoring. Every enhancement in scope of a selected base control gets a Selected / Inherited / Tailored Out picker with rationale. Out-of-baseline enhancements pre-default to Tailored Out.
- Per-control guidance. Schemas can declare prompts (checklist items), evidence suggestions (one-click chips that pre-populate the evidence list), and structured extra fields per high-impact control.
- BYOJSON persistence. Drafts autosave to
localStorage, and the wizard supports saving/loading them as JSON files. No server-side state. - Word + JSON output. Final plans render as
.docxvia PHPWord with a TOC, glossary, and acronyms appendix.
/ckl-viewer is a polished browser-only checklist editor:
- Drop a
.ckl(XML) or.cklb(JSON) — both parse into a unified internal model. - Hand-rolled SVG charts for status distribution (donut with
% compliantcenter label) and severity × status (grouped bars). - Editable host/asset metadata + per-rule editor (status, finding details, comments, severity override + justification).
- Drop a SCAP XCCDF result on the loaded checklist to overlay scan statuses (pass → NotAFinding, fail → Open, etc.) with a
[SCAP <result> — date]stamp appended to the finding details. - Re-export as CKLB JSON that DISA STIG Viewer 3.x reads natively.
# Rebuild the STIG index from scratch (re-parses every XML in resources/data/stig/)
bin/console app:stig:rebuild-toc
# Rebuild the SCAP index (includes pre-computed severity counts per benchmark)
bin/console app:scap:rebuild-toc
# Re-scan the STIG + SCAP corpus for IAVM/CTO/CVE references
# (output: resources/data/vulns_toc.json — feeds /vulnerabilities)
bin/console app:vulns:rebuild-toc
# Pull the latest CISA Known Exploited Vulnerabilities catalog into
# resources/data/kev/known_exploited_vulnerabilities.json
bin/console app:kev:refresh
# Sync any new STIG / SCAP bundles from the DISA cyber.mil catalog
# (downloads ZIPs into resources/data/zips/, extracts XCCDF XML into
# resources/data/{stig,scap}/). Append --dry-run to preview without
# writing anything.
bin/console app:disa:sync-stig
bin/console app:disa:sync-scap
# Build the XCCDF-XML → companion-ZIP map (resolves DISA's inconsistent
# zip filenames) used by the "Supporting documents" section on each STIG.
bin/console app:companion-zip:rebuild-index
# Build the per-version XML/ZIP presence + size index that drives the
# /stig/bulk table and the chunk planner.
bin/console app:bulk-download:rebuild-index
# Meta: run app:stig:rebuild-toc + app:scap:rebuild-toc + app:vulns:rebuild-toc
# in one shot (use after a bulk DISA refresh)
bin/console app:stig:rebuild
# Rebuild the inverted search index (sharded JSON under resources/data/search/)
bin/console app:search:rebuild
# Freeze the version string into a /VERSION file for deploys
bin/console app:version:freezeRun the toc rebuilds after dropping new DISA files into the data dir. The site auto-detects new XML files on the next request anyway, but a full rebuild is faster than thousands of incremental parses. app:stig:rebuild is the convenience wrapper when you've just done a bulk drop and want every dependent index refreshed in one command.
- PHP 8.2 or newer (8.4 is what production runs on)
- Composer 2
- ImageMagick (for regenerating the OG-image PNGs from
public/og/src/*.svg) - ~5 GB free disk for the data directory
- Symfony CLI is convenient but not required
git clone git@github.com:CyberSecDef/Cyber.Trackr.Live.git
cd Cyber.Trackr.Live/cyber.trackr.live
composer install# Symfony CLI
symfony serve
# Or PHP's built-in server
php -S localhost:8000 -t public/Then open http://localhost:8000. There is no database to set up, no migrations to run, and no environment variables required for local dev.
If you edit a STIG XML by hand (or unpack a new release zip), refresh the indexes:
# Quick path: one command does stig + scap + vulns toc rebuilds
bin/console app:stig:rebuild
# Or run each individually
bin/console app:stig:rebuild-toc
bin/console app:scap:rebuild-toc
bin/console app:vulns:rebuild-toc
bin/console app:search:rebuild
# CISA KEV is independent (network call)
bin/console app:kev:refreshAfter a fresh DISA / NIST pull, edit cyber.trackr.live/resources/data/sync_status.json so the footer reflects reality:
{
"disa": "2026-04-29T00:00:00Z",
"nist": "2026-04-18T00:00:00Z"
}Social-share images at /og/<surface>.png are rendered from SVG sources at public/og/src/. To update visuals or copy:
bash cyber.trackr.live/public/og/src/build.shThe site is "git is the database" by design. To add or refresh content:
- STIGs — drop new
U_*_STIG.xmlfiles intocyber.trackr.live/resources/data/stig/(or runbin/console app:disa:sync-stig/ hit/stig/disa_downloadto pull from DISA), thenbin/console app:stig:rebuild-toc. After a bulk drop, preferbin/console app:stig:rebuildso the SCAP toc andvulns_toc.jsonrefresh too. - SCAP — drop new
U_*_Benchmark.xmlfiles intocyber.trackr.live/resources/data/scap/(orbin/console app:disa:sync-scap//scap/disa_download), thenbin/console app:scap:rebuild-toc(orapp:stig:rebuildfor the bundled refresh). - CCIs — replace
cyber.trackr.live/resources/data/cci/U_CCI_List_2024.xml. No rebuild needed; reads happen on every request. - 800-53 — replace the
rmf/800-53v[45]-controls.xmlfiles. Same — read on demand. - Baselines — drop a new
*_profile.jsonintoresources/data/overlays/. The chip strip on/rmf/5, the wizard dropdown on every plan, and the baseline heat map all pick it up automatically. - Plan families — drop a new
<family>.jsonintoresources/data/plans/. The plan-generator landing page and wizard machinery handle it. - Daily cron (
bin/refresh-data.sh) — pulls everything that changes on its own and rebuilds every dependent index, in order: CISA KEV (app:kev:refresh), new STIG / SCAP bundles from cyber.mil (app:disa:sync-stig,app:disa:sync-scap), the stig / scap / vulns tocs (app:stig:rebuildmeta), the XML→ZIP companion map (app:companion-zip:rebuild-index), the bulk-download presence/size index (app:bulk-download:rebuild-index), the inverted search index (app:search:rebuild, incremental), and an IndexNow ping for new STIGs + the vulns landing pages.bin/ship.shruns the same content-side set at deploy time. Run any individually withbin/console <name>for a one-off rebuild. - Sync timestamps — edit
resources/data/sync_status.json. - Commit and push. Production deploy is
git pullfollowed by./bin/deploy.shon prod.
Note: any zip with the word "Compilation" in its name is
.gitignored. The DISA SRG-STIG sunset compilation bundle is 150 MB and exceeds GitHub's per-file limit; this rule prevents it from being accidentally re-committed.
Three scripts under cyber.trackr.live/bin/ form the end-to-end content + code pipeline. Each one's header comment lists its steps in detail.
| Script | Where it runs | When | What |
|---|---|---|---|
bin/ship.sh |
dev | when shipping new code or data | Refreshes KEV; rebuilds the stig / scap / vulns tocs, companion-ZIP index, and bulk-download index from current XML; freezes version + changelog; rsyncs everything (except .env) to prod. |
bin/deploy.sh |
prod, after rsync | every deploy | Full rebuild of the inverted search index; clears the prod + dev caches so Symfony picks up the new compiled container; best-effort IndexNow ping for recently-changed pages; runs fix-perms.sh last to normalise file modes. |
bin/refresh-data.sh |
prod cron, 04:00 daily | nightly | Pulls the CISA KEV catalog + any new STIG / SCAP bundles from cyber.mil; rebuilds every toc + sidecar index; incremental search-index sync; IndexNow ping for new STIGs + vulns landing pages. Network-dependent steps are wrapped in || true so a cyber.mil / CISA outage can't kill the cron and skip the downstream rebuilds. |
A typical dev → prod deploy:
./bin/ship.sh # on dev
ssh prod 'cd /path/to/cyber.trackr.live && ./bin/deploy.sh'Out-of-band utility: bin/fix-perms.sh resets directory / file modes to the standard PHP-site pattern (755 / 644, with .env files at 600). Already wired into deploy.sh step 5, but safe to re-run any time prod starts returning 403/500 from permission-denied errors.
- Read-only by design. No database, no user accounts, no admin panel. The dataset is a directory of XML/JSON files. State changes happen by editing those files and pushing a commit.
- No Doctrine, no ORM. Symfony's framework bundle is loaded; the persistence stack is not.
- Pre-computed indexes.
stig_toc.jsonandscap_toc.jsoncarry title / version / release / release-date / severity counts so the index pages render without parsing thousands of XML files per request. The inverted search index underresources/data/search/is similar — built once, queried at request time. - Schema-driven for variation. OSCAL Profile JSON drives baseline membership; per-family plan JSON drives the plan generator. Adding either is data, not code.
- Browser-only editor surfaces. The Plan Generator wizard, CKL Viewer, and Report Generator do all their parsing/editing/export in the browser. The server emits HTML and a JSON schema endpoint; user input never persists server-side.
- 8 themes via CSS custom properties.
paper,ink,mono,solarized-light,solarized-dark,nord,dracula,high-contrast. Stored inlocalStorage; a synchronous<script>in<head>applies the theme before first paint to avoid FOUC. - Self-hosted variable fonts. Fraunces and IBM Plex Sans/Mono ship as latin-subset WOFF2 in
public/fonts/— no Google Fonts request, no CDN dependency. - Per-page Open Graph + Twitter Card + JSON-LD. Eight 1200×630 og:images (rendered from SVG via ImageMagick) cover home / stig / scap / cci / rmf / baselines / plans / ckl. Detail pages emit BreadcrumbList structured data.
- Lazy on-disk caches. STIG digests cache as
{xml}.digest.jsonnext to the source; invalidate on source-mtime change. Both this and the search-index cache are gitignored.
| File | Role |
|---|---|
Controller/HomeController.php |
/, /contactus, /report_generator, /search, /mission, /ckl-viewer |
Controller/StigController.php |
/stig* routes including the diff engine, the /stig/{...} view (with embedded digest), and /stig/feed.atom |
Controller/ScapController.php |
/scap* routes including DISA scrape |
Controller/RmfController.php |
/rmf/4, /rmf/5, /rmf/4-to-5, /baselines |
Controller/CciController.php |
/cci |
Controller/PlansController.php |
/plans, /plans/{family}, /plans/{family}/{schema,controls,preview,download} |
Controller/VulnsController.php |
/vulnerabilities* — KEV catalog, IAVM/CTO list, single CVE/IAVM/KEV detail |
Controller/ApiController.php |
All /api/* JSON endpoints (including /api/vulns/*) |
Service/AppVersion.php |
Reads /VERSION; exposed as a Twig global |
Service/OverlayLoader.php |
OSCAL Profile JSON discovery, control → overlay membership map, family × baseline matrix for /baselines |
Service/R4ToR5Mapper.php |
Builds the r4 ↔ r5 mapping by reading both catalogs + harvesting <incorporated-into> from r5's withdrawn entries |
Service/StigCompanionZipFinder.php |
Resolves the DISA companion ZIP for a STIG via the XML-inside-ZIP index, lists its PDF entries, and streams individual PDFs |
Service/StigDigestBuilder.php |
Diffs current vs previous STIG version into a digest; on-disk cache via .digest.json |
Service/StigTocBuilder.php |
Parses STIG XML → toc entries with severity counts |
Service/ScapTocBuilder.php |
Same shape, for SCAP benchmarks |
Service/BulkDownloadIndex.php |
Sidecar bulk_download_index.json reader + builder — per-version XML/ZIP presence + size for the bulk-download table |
Service/BulkDownloadPlanner.php |
Validates a user's selection, dedupes shared-bundle paths, greedy-packs into ≤500 MB chunks, streams each chunk as a ZIP via ZipStream-PHP |
Service/DisaCatalogSyncer.php |
Single engine behind both /{stig,scap}/disa_download web routes and the app:disa:sync-{stig,scap} console commands — pulls the cyber.mil catalog, filters for STIG vs SCAP, downloads new ZIPs, extracts XCCDF XML, marks sync_status.json |
Service/SyncStatus.php |
Reads sync_status.json; exposed as Twig global |
Service/Plans/PlanRegistry.php |
Discovers plan schema files, exposes availablePlans() |
Service/Plans/ControlResolver.php |
Family + baseline → ordered list of controls + enhancements with in_baseline flags |
Service/Plans/PlanBuilder.php |
Schema + answers → renderable Plan structure (handles ODV substitution, dispositions, extras) |
Service/Plans/OdvExtractor.php |
Parses [Assignment: …], [Selection: …], [Selection (one or more): …] placeholders out of catalog text |
Service/Plans/Renderer/HtmlRenderer.php |
Plan → HTML preview |
Service/Plans/Renderer/DocxRenderer.php |
Plan → .docx via PHPWord |
Service/Search/IndexBuilder.php |
Builds the inverted search index (sharded JSON) |
Service/Search/Searcher.php |
Query-time index consumer (phrase + fuzzy fallback) |
Service/Vulns/KevLoader.php |
Reads the local CISA KEV mirror; CVE lookup + summary stats |
Service/Vulns/VulnsTocBuilder.php |
Walks STIG/SCAP XML, extracts IAVM/CTO/CVE refs into vulns_toc.json |
Service/Vulns/VulnsRegistry.php |
Read-side facade: combines KEV + corpus refs, builds in-memory pivot tables for the controller |
Twig/AppExtension.php |
Filters: regex_replace, sha1, editorial_title, freshness_tag, rel_time |
Command/StigRebuildTocCommand.php |
app:stig:rebuild-toc |
Command/ScapRebuildTocCommand.php |
app:scap:rebuild-toc |
Command/VulnsRebuildTocCommand.php |
app:vulns:rebuild-toc |
Command/StigRebuildCommand.php |
app:stig:rebuild (meta — runs stig + scap + vulns toc rebuilds) |
Command/KevRefreshCommand.php |
app:kev:refresh |
Command/CompanionZipRebuildIndexCommand.php |
app:companion-zip:rebuild-index |
Command/BulkDownloadRebuildIndexCommand.php |
app:bulk-download:rebuild-index |
Command/DisaSyncStigCommand.php |
app:disa:sync-stig (supports --dry-run) |
Command/DisaSyncScapCommand.php |
app:disa:sync-scap (supports --dry-run) |
Command/SearchRebuildCommand.php |
app:search:rebuild |
Command/AppVersionFreezeCommand.php |
app:version:freeze |
| File | Role |
|---|---|
public/css/app.css |
Full custom design system (~6,600 lines: tokens, components, layout, 8 themes, plus per-feature blocks for plans, CKL viewer, baselines, digests, saved searches, share button) |
public/js/app.js |
Vanilla JS for theme toggle, hamburger nav, sortable tables, paginated lists, Cmd/Ctrl+K search shortcut, share-this-page, save-search wiring |
public/js/saved_searches.js |
localStorage-backed saved-search bookmarks (dropdown + save/unsave toggle) |
public/js/plans.js |
Plan-generator wizard — autosave, BYOJSON, lazy controls fetch, ODV/disposition/extras collection |
public/js/ckl_viewer.js |
CKL/CKLB parser, XCCDF overlay, hand-rolled SVG charts, rule editor, CKLB export |
public/js/bulk_download.js |
Bulk-download selection state, header "select all of kind" toggles (operate on the full 3,970-row set, not just the Scroller viewport), plan request, sequential chunked download with progress |
public/js/report_generator.js (within the legacy template) |
Legacy report-generator pipeline |
public/og/*.png |
8 generated 1200×630 social-share images, with SVG sources + a build.sh regenerator under public/og/src/ |
templates/base.html.twig |
Layout shell — sticky header (search + share + theme + nav), footer, font preload, theme preflight, OG/Twitter/JSON-LD metadata blocks |
templates/macros.html.twig |
Reusable UI primitives: ident(), sev(), sev_bar(), freshness(), cci_link(), rmf_link() |
JavaScript dependencies the project ships (all self-hosted, no CDN): jQuery 3.7, Bootstrap 5 bundle, DataTables (incl. the Scroller plugin used by the bulk-download table), diff_match_patch, Masonry, js-cookie, moment.js, plus xlsx + zip + jmespath for the legacy report generator.
Server-side: maennchen/zipstream-php streams the bulk-download chunks without ever buffering them to disk or RAM — the only non-Symfony PHP dependency added since launch.
The test suite is intentionally minimal — a tests/bootstrap.php and the PHPUnit config. Adding coverage is on the to-do list; the read-only architecture means the bug surface is mostly "did the XML parse correctly", which is best caught by snapshot-style fixtures rather than unit tests of business logic that doesn't really exist.
To run what's there:
cd cyber.trackr.live
bin/phpunitBuilt and maintained by Robert Weber (@CyberSecDef). For corrections, broken links, or new STIG releases that haven't appeared yet, open an issue or use the contact form.
The application code in this repository is licensed under the GNU Affero General Public License, version 3 or later (AGPL-3.0-or-later). The full license text is in LICENSE.
The compliance datasets it serves (STIGs, SCAP benchmarks, CCI catalog, NIST 800-53, OSCAL profiles) are public-domain works of the U.S. Government and are redistributed unmodified — the AGPL on the surrounding code does not apply to them. Self-hosted typefaces (Fraunces, IBM Plex) ship under the SIL Open Font License 1.1, and bundled JavaScript libraries each carry their upstream licenses (MIT, Apache-2.0, BSD-3-Clause).
The full attribution table — every code path, every dataset, every font, every JS library, with its license — is in NOTICE.md.
Practical summary: you can read, run, fork, and modify this code. If you run a modified version as a network service, the AGPL requires you to publish your changes under the same license. The goal is to keep improvements in the commons.
The terms governing use of the hosted service at cyber.trackr.live are separate from the code license and live at cyber.trackr.live/terms.
- DISA Cyber Exchange — for publishing the STIG and SCAP corpus openly.
- NIST — for the 800-53 catalog and OSCAL profile format.
- The Symfony team — for the framework that made the read-only architecture so easy.
- PHPOffice / PHPWord — for the DOCX writer powering the plan generator.
- CTuX, Inspec, OpenRMF, and the broader DoD compliance tooling community — for proving that the official sources weren't the last word on usability.