
Jokainen OSCAL-validaattori väittää ”validoivansa OSCALia”. Lähes mikään niistä ei osaa kertoa, mitä tuo lause tarkoittaa.
NIST:n OSCAL-mallit on laadittu Metaschemalla – kahdeksan juurimoduulia sekä yhteiset tuonnit, tuhansia rivejä XML:ää, joka määrittelee dokumentin muodon lisäksi myös semantiikan: sallitut arvosanastot, yksikäsitteisyyssäännöt, ristiviittausindeksit ja kardinaliteettivaatimukset. JSON Schema tunnistaa muodon. Semantiikassa vaatimustenmukaisuusdokumentit kuitenkin todellisuudessa menevät pieleen – ja siellä ”validoimme OSCALin” muuttuu hiljaa muotoon ”validoimme osan OSCALista, emmekä ole varmoja mistä osasta”.
Halusimme olla varmoja siitä, mistä osasta. Siksi rakensimme validaattorimme samalla tavalla kuin järjestelmä auditoidaan: aloitetaan lähteistä, luetellaan kaikki ja tilitetään jokainen kohta.
Ensimmäinen päätös oli se tärkein: NIST:n lähteet ovat auktoriteetti – eivät referenssitoteutus. Kiinnitimme usnistgov/OSCAL-repositorion committiin 21403b4a… (v1.2.2), tallensimme jokaisen Metaschema-tavun tarkasti välimuistiin SHA-256-tiivisteineen ja kohtelimme kunnianarvoisaa Java OSCAL CLI:tä sinä, mitä se todella on: vertailukohtana, jota ristikuulustellaan, ei totuutena, jota kopioidaan. (Siihen on ensinnäkin upotettu OSCAL 1.2.1 -sidokset – se pystyy käsittelemään 1.2.2-dokumentteja, mutta se ei puhu 1.2.2:ta.)
Sen jälkeen inventoimme leksikaalisesti jokaisen rajoitteen esiintymän kiinnitetyissä lähteissä. Emme rajoitetyyppejä – vaan esiintymiä, jotka yksilöidään tiedoston ja rivin perusteella, jotta kaksi rajoitetta, joilla sattuu olemaan sama tunniste, eivät koskaan sulaudu yhdeksi. Määräksi tuli 348.
Jokaisen esiintymän osalta buildimme on pidettävä täsmälleen yksi kolmesta tuomiosta, ja sen valvoo generaattori, joka laskee kirjanpidon uudelleen jokaisella ajolla:
Tilittämättä: nolla.
Viimeinen ryhmä – poissulkemiset – osoittautui kiinnostavaksi.
Kun 348 rajoitetta tarkistetaan yksi kerrallaan, asioita löytyy. Kolme poissulkemisistamme on virheitä itse NIST:n lähteissä:
oscal_mapping-common_metaschema.xml rivi 657 rajoittaa flagia, joka määritellään viisi riviä aiemmin – ja johon ei sen jälkeen viitata mistään. Mikään mahdollinen dokumentti ei sisällä tätä flagia. Rajoitetta on mahdoton täyttää.inventory-item-elementin prop-nimiä koskeva sääntö soveltuu vain, kun @type on software, hardware tai service – mutta inventory-item ei määrittele lainkaan type-flagia. (Sen naapuri asset-id on itsekin kommentoitu lähteessä pois.) Predikaatti ei voi koskaan täsmätä.with-child-controls-elementille. Lähdettä lukeva ihminen näkee ne; käännetty skeema ei koskaan valvo niitä. Kaikki kolme havaintoa on raportoitu ylävirtaan: usnistgov/OSCAL#2254, #2255, #2256.Ja auditointi toimi molempiin suuntiin: omassa evaluaattorissamme oli bugi, jossa flageihin kohdistuvat rajoitteet (kuten action/@type-attribuutin sallitut arvot) käännettiin inventaarioon mutta eivät koskaan lauenneet. Emme löytäneet sitä onnella – sulkeumaportti kieltäytyi hyväksymästä näyttöä näiden kahden esiintymän osalta, mikä on juuri se vikaantumistapa, jonka paljastamiseen koko järjestelmä on suunniteltu.
Väite, että ”referenssitoteutukselta jää asioita huomaamatta”, pelkän lähdekoodin tarkastelun perusteella on juuri sellainen todistamaton väite, jota tämä projekti on olemassa kitkemään. Siksi latasimme Java OSCAL CLI 3.2.0:n Maven Centralista, todensimme sen tiivisteen ja ajoimme molemmat validaattorit testiaineistoperheen yli, jonka lähtötason dokumentit läpäisevät validoinnin puhtaasti molemmilla puolilla – jolloin jokainen erimielisyys voidaan jäljittää yhteen injektoituun muutokseen.
OSCAL 1.2.2 muutti versionumeroiden päivitysten lisäksi täsmälleen kahta rajoitetta (molemmat SSP-mallissa). Java CLI – johon on upotettu 1.2.1-sidokset – on väärällä puolella jokaisessa havaittavassa seurauksessa:
rel="validation"-komponenttilinkki, rikkoo 1.2.2:ta. Java: validi, exit 0.rel="validated-by"-linkki, on 1.2.2:n mukaan kunnossa (rajoite poistettiin). Java: ei validi.responsible-role ilman valinnaista party-uuid-kenttää on 1.2.2:n mukaan kunnossa – NIST lisäsi predikaatin nimenomaan tämän korjaamiseksi. Java antaa virheen, kirjaimellisesti Key reference [null] not found.Sitten yksi, joka ei liity lainkaan versioeroon: katalogi, jonka metadatan action ilmoittaa "type": "invented-type" – kielletty metadata-Metaschemen rivillä 877 sekä 1.2.2:ssa että Javaan upotetuissa 1.2.1-lähteissä. Java julistaa sen validiksi sekä JSON- että XML-muodossa. Rajoite kohdistuu flagiin; flageihin kohdistuvien rajoitteiden hiljainen laukeamatta jääminen on juuri se bugiluokka, jonka kattavuusporttimme havaitsi omassa evaluaattorissamme. Referenssitoteutuksessa on sama bugiluokka – eikä sulkeumaporttia sen havaitsemiseksi. Raportoimme sen ylävirtaan: metaschema-framework/oscal-cli#279. (Kartoitimme luokan mekaanisesti: täsmälleen 2 kahdestasadasta allowed-values-esiintymästä kohdistuu flageihin, ja ainoa virhetason jäsen on se, jonka testasimme livenä. Testaamatonta jäännöstä ei ole.)
Ja rehellisyyden hetki, koska ajo toimi molempiin suuntiin: validaattorimme hylkäsi NIST:n oman SP 800-53 rev5 -katalogin. Kaksikymmentä virhettä, kaikki saman vian aiheuttamia – indeksievaluaattorimme käsitteli puuttuvaa valinnaista avainkenttää rikkomuksena, vaikka Metaschema-spesifikaation mukaan se on null-avain. Java hyväksyi tiedoston; me olimme väärässä; korjasimme sen samana päivänä, ja 800-53 validoituu nyt puhtaasti. Ajo löysi myöhemmin toisenkin: valvoimme OSCALin action-type-sanastoa silloinkin, kun action/@system ilmoitti mukautetun URI:n – juuri sitä organisaatiokohtaista segmentointia, jota NIST:n omat huomautukset edellyttävät. Sekin korjattu. Vertailuympäristö, joka löytää vain vastapuolen bugeja, ei ole vertailuympäristö, se on markkinointia.
(Myös kategoriassa ”molemmat puolet”: kumpikaan resolveri ei validoinut omaa tuotostaan semanttisesti. Javan resolve-profile kirjoittaa mielellään katalogin, jonka Javan oma validate sitten hylkää – ja meidän resolverimme teki saman, skeematarkistettuna mutta ei semanttisesti tarkistettuna. Meidän resolverimme kieltäytyy nyt kirjoittamasta semanttisesti virheellisiä resoluutioita; Java ei vieläkään pysty siihen, koska aukon sulkeminen edellyttää semanttista kerrosta, johon luotat.)
Toinen asia, joka olemassa olevista työkaluista puuttuu: OSCAL-dokumentit eivät elä yksin. Arviointitulos tuo arviointisuunnitelman, joka tuo SSP:n, joka tuo profiilin, joka resolvoidaan katalogeja vasten. Mallien dokumentaatio on täynnä suhteita, joita mikään yksittäistä tiedostoa käsittelevä validaattori ei pysty tarkistamaan – ”tämän havainnon kohteen on resolvoiduttava baselinen lausekkeeseen”, ”tämän POA&M:n on yksilöitävä järjestelmänsä”.
Siksi rakensimme dokumenttien välisen validoinnin, joka resolvoi nämä suhteet oikeasti. Kun pyydät sitä tarkistamaan SSP:n, se resolvoi tuodun baselinen koko (luonnosspesifikaation mukaisen) profiiliresoluutioputken läpi katalogeihin asti, laskee valittujen kontrollien joukon ja kertoo sinulle:
{
"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'"
}
Yhdellä ratkaisevalla suunnittelusäännöllä: nämä suhdetarkistukset ovat dokumentoidun proosan tulkintoja, ja kohtelemme niitä sellaisina – oletuksena pois päältä, varoituksia eikä virheitä, jokaisen kentän resoluutiolaajuus kiinnitettynä lähderiviinsä, ja kaikki pelkästään pääteltävissä oleva rajattu nimeltä pois. Kun standardi jättää asian avoimeksi, validaattorin ei pidä bluffata. (Suosikkiesimerkkimme: POA&M-spesifikaation mukaan SSP-tuonti tai system-id vaaditaan – ”Both may be present.” Siksi varoitamme vain, kun kumpaakaan ei ole. Ei keksittyä poissulkevaa tai-ehtoa.)
Koska dokumentit elävät selaimissa, serverless-funktioissa, CLI-työkaluissa ja tietokannoissa – ja halusimme yhden validaattorin kaikkiin niihin, emme JVM-sivuvaunua jokaisen viereen. Validaattorit ovat valmiiksi käännettyjä Ajv standalone -moduuleja: tavallista generoitua JavaScriptiä, ei ajonaikaista skeeman kääntämistä, tavutasolla vakaa tuotos. Sama koodi, joka pyörittää validointipintojamme, toimii muuttumattomana selaimesi välilehdellä ja CLI:ssämme. Eikä determinismi ole pelkkä operoinnin mukavuus – se on se, mikä ylipäätään mahdollistaa tiivisteillä kiinnitetyn näytön.
import { createDiagnosticsOscalProcessor } from "@secani/oscal/diagnostics";
const result = createDiagnosticsOscalProcessor({ maxIssues: 50 }).validate(doc);
validate --resolve-imports --interpretive all)Koko tekninen raportti – auktoriteettimalli, kattavuuden sulkeuma, vertailun kuittitaulukko ja se, mitä emme tietoisesti väitä – löytyy validaattorin dokumentaatiosta. Validaattori on yksityisessä esijulkaisuvaiheessa ennen avoimen lähdekoodin julkaisua; isännöity validointi-API tarjoaa skeematason jo tänään, ja semanttinen kerros seuraa myöhemmin.
Secani yhdistää rajaukset, todisteet, tehtävät ja tekoälyagentit yhteiseen työtilaan.
OLIR tarjoaa vastaavuussisällön ja sen hallinnan. OSCAL tarjoaa koneluettavan rakenteen, jonka avulla näitä vastaavuuksia voidaan käyttää puuteanalyysissa, näytön uudelleenkäytössä ja muutosvaikutusten työnkuluissa.
OSCAL muuttaa vaatimustenmukaisuusasiakirjat jäsennellyksi dataksi: kahdeksan asiakirjamallia, kolme tiedostomuotoa ja ekosysteemi, josta on tulossa sääntelyn standardi.
RFC-0024:n ja Consolidated Rules 2026 -sääntöjen myötä FedRAMP tekee jäsennellystä valtuutusdatasta pakollista. Määräajat on porrastettu – suunta on yksiselitteinen.