
Alle OSCAL-validatorer hævder at „validere OSCAL“. Næsten ingen af dem kan fortælle dig, hvad den sætning betyder.
NIST's OSCAL-modeller er skrevet i Metaschema – otte rodmoduler plus fælles imports, tusindvis af linjer XML, der ikke kun definerer dokumenternes form, men også deres semantik: tilladte værdiordforråd, entydighedsregler, krydsreferenceindekser, krav til kardinalitet. Et JSON Schema fanger formen. Det er i semantikken, at compliance-dokumenter faktisk går galt – og hvor „vi validerer OSCAL“ stille og roligt bliver til „vi validerer noget af OSCAL, vi er ikke helt sikre på hvilken del“.
Vi ville være sikre på, hvilken del. Så vi byggede vores validator, sådan som man ville auditere et system: Start fra kilderne, opregn alt, og gør rede for hvert eneste element.
Den første beslutning var den vigtige: NIST-kilderne er autoriteten – ikke referenceimplementeringen. Vi låste usnistgov/OSCAL fast på commit 21403b4a… (v1.2.2), cachede hvert Metaschema bytenøjagtigt med SHA-256-hashes og behandlede den hæderkronede Java OSCAL CLI som det, den faktisk er: en sammenligningspart at krydsforhøre, ikke en sandhed at kopiere. (Den indlejrer for det første OSCAL 1.2.1-bindings – den kan behandle 1.2.2-dokumenter, men den kan ikke tale 1.2.2.)
Derefter lavede vi en leksikalsk opgørelse over alle constraint-forekomster i de fastlåste kilder. Ikke constraint-typer – forekomster, identificeret ved fil og linje, så to constraints, der tilfældigvis deler et ID, aldrig falder sammen til én. Optællingen endte på 348.
For hver forekomst skal vores build have præcis én af tre afgørelser, håndhævet af en generator, der genberegner hovedbogen ved hver kørsel:
Ikke redegjort for: nul.
Den sidste kategori – udelukkelserne – var der, hvor det blev interessant.
Når man kontrollerer 348 constraints én for én, finder man ting. Tre af vores udelukkelser er fejl i selve NIST-kilderne:
oscal_mapping-common_metaschema.xml linje 657 begrænser et flag, der er defineret fem linjer tidligere – og som derefter aldrig refereres af noget. Intet dokument, der kan eksistere, bærer dette flag. Constraint'en kan ikke opfyldes.inventory-item-prop-navne gælder kun, når @type er software, hardware eller service – men inventory-item erklærer slet ikke noget type-flag. (Naboen, asset-id, er selv kommenteret ud i kilden.) Prædikatet kan aldrig matche.with-child-controls. Et menneske, der læser kilden, ser dem; det kompilerede skema håndhæver dem aldrig. Alle tre fund er rapporteret upstream: usnistgov/OSCAL#2254, #2255, #2256.Og auditten skar begge veje: Vores egen evaluator havde en fejl, hvor constraints rettet mod flag (som de tilladte værdier for action/@type) blev kompileret ind i opgørelsen, men i stilhed aldrig blev udløst. Vi fandt den ikke ved held – lukningsporten nægtede at acceptere evidens for de to forekomster, og det er præcis den fejltype, hele systemet er designet til at afsløre.
At påstå, at „referenceimplementeringen overser ting“, alene ud fra en gennemlæsning af kilden er præcis den slags ubeviste påstand, dette projekt findes for at gøre op med. Så vi downloadede Java OSCAL CLI 3.2.0 fra Maven Central, verificerede dens hash og kørte begge validatorer over en familie af fixtures, hvis basisdokumenter består fejlfrit på begge sider – så enhver uenighed kan henføres til én indsat ændring.
OSCAL 1.2.2 ændrede præcis to constraints ud over versionsopdateringer (begge i SSP-modellen). Java CLI'en – som indlejrer 1.2.1-bindings – står på den forkerte side af hver eneste observerbar konsekvens:
rel="validation"-komponentlink overtræder 1.2.2. Java: gyldig, exit 0.rel="validated-by"-link er i orden ifølge 1.2.2 (constraint'en blev slettet). Java: ugyldig.responsible-role uden det valgfrie party-uuid er i orden ifølge 1.2.2 – NIST tilføjede prædikatet netop for at rette dette. Java fejler med, helt bogstaveligt, Key reference [null] not found.Så kom der en, der slet ikke handler om versionsforskelle: et katalog, hvis metadata-action erklærer "type": "invented-type" – forbudt i linje 877 i metadata-Metaschemaet i både 1.2.2 og de 1.2.1-kilder, Java indlejrer. Java erklærer det gyldigt, i JSON og XML. Constraint'en er rettet mod et flag; at flag-rettede constraints i stilhed ikke bliver udløst, er præcis den fejlklasse, vores fuldstændighedsport fangede i vores egen evaluator. Referenceimplementeringen har samme fejlklasse – og ingen lukningsport til at fange den. Vi rapporterede den upstream som metaschema-framework/oscal-cli#279. (Vi kortlagde klassen mekanisk: Præcis 2 af 200 allowed-values-forekomster er rettet mod flag, og det eneste medlem på fejlniveau er det, vi testede live. Ingen utestet rest.)
Og så ærligheden, for kørslen skar begge veje: Vores validator afviste NIST's eget SP 800-53 rev5-katalog. Tyve fejl, alle med samme årsag – vores indeksevaluator behandlede et manglende valgfrit nøglefelt som en overtrædelse, hvor Metaschema-specifikationen siger, at det er en null-nøgle. Java accepterede filen; vi tog fejl; vi rettede det samme dag, og 800-53 validerer nu fejlfrit. Kørslen fangede senere endnu en: Vi blev ved med at håndhæve OSCAL's ordforråd for action-typer, selv når action/@system erklærede en brugerdefineret URI – præcis den organisationsspecifikke opdeling, som NIST's egne bemærkninger lægger op til. Også rettet. Et differentialtestsystem, der kun nogensinde finder den anden sides fejl, er ikke et testsystem, det er markedsføring.
(Også under „begge sider“: Ingen af resolverne validerede deres eget output semantisk. Javas resolve-profile skriver gladeligt et katalog, som Javas egen validate derefter afviser – og vores gjorde det samme, skemakontrolleret, men ikke semantisk kontrolleret. Vores nægter nu at skrive semantisk ugyldige resolutioner; Java kan stadig ikke, fordi lukningen af det hul kræver et semantisk lag, man har tillid til.)
Det andet, der mangler i eksisterende værktøjer: OSCAL-dokumenter lever ikke alene. Et assessment result importerer en assessment plan, som importerer en SSP, som importerer en profil, som resolveres mod kataloger. Modeldokumentationen er fuld af relationer, som ingen validator for enkeltfiler kan kontrollere – „dette funds target skal kunne resolveres til et statement i baselinen“, „denne POA&M skal identificere sit system“.
Så vi byggede validering på tværs af dokumenter, der resolverer disse kanter for alvor. Bed den om at kontrollere en SSP, og den resolverer den importerede baseline gennem den fulde profilresolutionspipeline (efter udkastspecifikationen) helt ned til katalogerne, beregner det valgte kontrolsæt og fortæller dig:
{
"ruleId": "SSP-003.b",
"severity": "warning",
"path": "/…/implemented-requirements/1/control-id",
"message": "implemented control 'ac-99' is not supplied by the resolved import-profile 'file:///…/baseline.json'"
}
Med én afgørende designregel: Disse relationskontroller er fortolkninger af dokumenteret prosa, og vi behandler dem som sådan – slået fra som standard, advarsler og ikke fejl, hvert felts resolutionsområde låst fast til dets kildelinje, og alt, der blot kan udledes, udelukket ved navn. Hvor standarden tager forbehold, bør en validator ikke bluffe. (Vores yndlingseksempel: POA&M-specifikationen siger, at en SSP-import eller et system-id er påkrævet – „Both may be present.“ Så vi advarer kun, når ingen af dem findes. Intet opfundet eksklusivt eller.)
Fordi dokumenterne lever i browsere, serverless-funktioner, CLI'er og databaser – og vi ville have én validator i dem alle, ikke en JVM-sidecar ved siden af hver. Validatorerne er prækompilerede Ajv standalone-moduler: almindelig genereret JavaScript, ingen skemakompilering ved kørsel, bytestabilt output. Den samme kode, der driver vores valideringsflader, kører uændret i din browserfane og i vores CLI. Og determinisme er ikke bare en driftsmæssig finesse – det er det, der overhovedet gør hash-låst evidens mulig.
import { createDiagnosticsOscalProcessor } from "@secani/oscal/diagnostics";
const result = createDiagnosticsOscalProcessor({ maxIssues: 50 }).validate(doc);
validate --resolve-imports --interpretive all)Den fulde tekniske rapport – autoritetsmodel, fuldstændighedslukning, tabellen med differentialkvitteringer og det, vi bevidst ikke påstår – findes i validatordokumentationen. Validatoren er i privat staging forud for en open source-udgivelse; det hostede validerings-API eksponerer skemaniveauet i dag, og det semantiske lag følger.
Secani forbinder scopes, dokumentation, opgaver og AI-agenter i ét fælles arbejdsområde.
OLIR leverer mappingindhold og governance. OSCAL leverer den maskinlæsbare struktur, der gør mappings brugbare i gap-analyser, genbrug af evidens og workflows for konsekvensanalyse af ændringer.
OSCAL gør compliance-dokumenter til strukturerede data: otte dokumentmodeller, tre formater og et økosystem, der er ved at blive standarden for regulering.
Med RFC-0024 og Consolidated Rules 2026 gør FedRAMP strukturerede autorisationsdata obligatoriske. Fristerne er forskudte, men retningen er utvetydig.