FedRAMP Published Artifacts Representation of the FedRAMP Rules (FRRs), Key Security Indicator (KSI) _requirements_, and Rev 5 Baselines in OSCAL Format. Intended to include code for converting FedRAMP-published JSON to OSCAL. Baselines This page will continue to evolve as the TFG reaches consensus on the best representation. There are several draft efforts to produce appropriate OSCAL catalogs and profiles representing the FedRAMP Rules (FRR) and certification classes. These include (in no particular order): https://github.com/C1Secure-Development/OSCAL_20x https://github.com/Palladium-Innovations/fedramp-cr26-oscal https://github.com/brian-ruf/frr2oscal There has been some discussion around this mapping document, but it remains a draft work-in-progress. Suggested Hierarchy for OSCAL Catalog/Profile represeentation of FedRAMP's Consolidated Rules 2026 (CR26), including 20x path KSI and Rev 5 path certification baselines. For the Rev 5 certificaiton class baselines, FedRAMP defines a few parameters and provides guidance on a few controls. Where the defined parameters and guidance are the same for all certification class, they are represented in the Rev 5 Tailoring" profile . Where the defined parameters and guidance vary by certification baseline, they are represented in the appropriate Rev 5 Class profile. FedRAMP does not allow Class A certifications for the Rev 5 path, thus a Rev 5 Class A profile is not appropriate. Mapping: FedRAMP Rules → OSCAL DRAFT - PLEASE PROVIDE INPUT Updated: September 8, 2026 Latest Work Found Here This document maps every field defined in the FRR portion of fedramp-consolidated-rules.schema.json to its corresponding location in the OSCAL catalog produced by src/frr2oscal.py . Fields with no current mapping are marked NOT MAPPED and noted with a brief description of the data they contain. The catalog metadata also includes fixed roles, parties, and responsible-parties that are not derived from the source JSON; these are described in §9. 1. Schema Hierarchy Overview FRR (object, keyed by frr_document_key) └── {FRR-key} e.g. "AFC", "AGU" ├── info frr_document_info └── data data_container_frr ├── all frr_requirements_map ← processed ├── 20x frr_requirements_map ← processed └── rev5 frr_requirements_map ← processed └── {subset-key} frr_requirements_subset_group └── {rule-id} frr_requirement └── varies_by_class.{a|b|c|d} frr_requirement_level All three data scopes ( all , 20x , rev5 ) are now converted. Rules from each scope carry a path prop (FedRAMP namespace) identifying which scope they belong to. Child group IDs include a scope qualifier for 20x and rev5 to prevent collisions with all groups whose subset keys overlap (e.g. VDR/TFR appears in all three scopes). 2. FRR Document → OSCAL Top-Level Group Each top-level key in FRR (pattern ^[A-Z]{3}$ ) becomes a top-level group in the catalog. 2.1 FRR.{key} → group OSCAL field Value group.id "FRR-{key}" group.title info.name group.props[name=label].value "FRR-{key}" group.parts[name=overview].prose info.purpose group.parts[name=overview].title "Purpose" (set via dict workaround; see MISSING_FROM_OSCAL_LIBRARY.md §1) 2.2 FRR.{key}.info fields ( frr_document_info ) Schema field Required Type OSCAL mapping name ✓ string → group.title purpose ✓ string → group.parts[name=overview].prose short_name ✓ string ^[A-Z]{3}$ → group.props[name=label].value web_name ✓ string → group.props[name=web_name, ns=FRR_NS].value (FedRAMP extension) status ✓ "stable" | "placeholder" | "empty" → group.props[name=status, ns=FRR_NS].value (FedRAMP extension) tag — string → group.props[name=tag, ns=FRR_NS].value (FedRAMP extension) effective ✓ (or 20x + rev5 ) effective_entry NOT MAPPED — effective date and status for the ruleset subsets — frr_info_subsets Mapped as child controls — subset metadata (names, descriptions, applicability); see §2.3 flows — array NOT MAPPED — process-flow relationships 20x ✓ (when no top-level effective ) frr_document_info_certification NOT MAPPED — 20x-specific effective dates and subset overrides rev5 ✓ (when no top-level effective ) frr_document_info_certification NOT MAPPED — Rev5-specific effective dates and subset overrides 2.3 FRR.{key}.info.subsets ( frr_info_subsets ) Subset metadata describes each named group of rules within a ruleset. It is present in the info block but is not present in the current data for any ruleset. When present, each entry becomes a child control of the parent ruleset group (id = FRR-{key}-{subset-key} ). Schema field Required Type OSCAL mapping {subset-key}.name ✓ string → control.title (prefixed with "SUBSET: " ) {subset-key}.description ✓ string → control.parts[name=statement].prose {subset-key}.applicability.types ✓ ["20x" | "Rev5"] → one control.props[name=applicability-type, ns=FRR_NS] per item {subset-key}.applicability.paths ✓ ["Program" | "Agency"] → one control.props[name=applicability-path, ns=FRR_NS] per item {subset-key}.applicability.classes ✓ ["A"…"D"] → one control.props[name=applicability-class, ns=FRR_NS] per item {subset-key}.applicability.affects ✓ affected_party[] → one control.props[name=affects, ns=FRR_NS] per item 3. FRR.{key}.data → Data Scope Selection All three scopes are processed. Child group and control IDs reflect the scope they originate from. Schema key Type OSCAL mapping data.all frr_requirements_map → processed; child groups use FRR-{key}-{subset} ID data.20x frr_requirements_map → processed; child groups use FRR-{key}-{subset}-20x ID data.rev5 frr_requirements_map → processed; child groups use FRR-{key}-{subset}-rev5 ID 4. FRR.{key}.data.{scope}.{subset} → OSCAL Child Group Each subset key within a scope becomes a child group nested under the parent ruleset group. OSCAL field Value group.id "FRR-{key}-{subset}" (scope=all) or "FRR-{key}-{subset}-{scope}" (scope=20x/rev5) group.title Same as group.id for scope=all; "FRR-{key}-{subset} 20X Path" or "FRR-{key}-{subset} Rev 5 Path" for scoped groups group.parts[name=overview] Omitted (no info block present in current data) The frr_requirements_subset_group schema allows any frr_requirement_id as a property key alongside an optional info entry. When info is present, its title and purpose fields map to group.title and group.parts[name=overview].prose respectively. 5. FRR.{key}.data.{scope}.{subset}.{rule-id} → OSCAL Control Each rule entry ( frr_requirement ) maps to one OSCAL control . The schema enforces a mutual exclusion: a rule has either statement + force (simple rule) or varies_by_class (class-conditional rule), never both. 5.1 Simple Rule (has statement and force , no varies_by_class ) Schema field Required Type OSCAL mapping (key) — frr_requirement_id → control.id , props[name=label].value name ✓ string → control.title statement ✓ string → parts[name=statement, id={id}_smt].prose force ✓ force_enum → props[name=force, ns=FRR_NS].value (scope) — — → props[name=path, ns=FRR_NS].value = "all" | "20x" | "rev5" affects ✓ affected_party[] → one props[name=affects, ns=FRR_NS] per item danger — string → parts[name=guidance, title=Danger].prose (title set via workaround; see MISSING_FROM_OSCAL_LIBRARY.md §1) note — string → parts[name=guidance, title=Notes].prose notes — string[] (min 2) → parts[name=guidance, title=Notes].prose (items joined with blank lines) related — string[] → one links[rel=related, href=#{id}] per item artifacts.all — string[] → parts[name=assessment-method, props=[method=EXAMINE, path=all]].parts[name=assessment-objects].prose (one per item; see MISSING_FROM_OSCAL_LIBRARY.md §3) artifacts.20x — string[] → parts[name=assessment-method, props=[method=EXAMINE, path=20x]].parts[name=assessment-objects].prose artifacts.rev5 — string[] → parts[name=assessment-method, props=[method=EXAMINE, path=rev5]].parts[name=assessment-objects].prose corrective_actions — string[] → parts[name=remediation, ns=FRR_NS].prose (items joined with blank lines) examples — object[] ( id , key_tests , examples ) → parts[name=guidance, class=examples, title=Examples].prose schema — rule_schema ( name + url ) → parts[name=guidance, class=schema, title=Schema].prose following_information — string[] → parts[name=guidance, class=following_information, title=Following Information].prose updated ✓ updated_list → one props[name=updated, ns=FRR_NS, value=date, remarks=comment] per entry following_information_bullets — string[] → parts[name=statement, id={id}_smt].parts[name=item].prose (each item prefixed with - ; appended after statement ) reference — string → links[rel=reference].text (used as link text when reference_url is also present) reference_url — URI → links[rel=reference, href={url}] ; .text set to reference value when present effective_date — effective_dates → props[name=effective_date, ns=FRR_NS].value (JSON-serialised when value is an object) timeframe_type — enum ( bizdays | days | hours | weeks | months | years ) → props[name=timeframe_type, ns=FRR_NS].value timeframe_num — positive number → props[name=timeframe_num, ns=FRR_NS].value (number converted to string) notification — object[] ( party , method , target , name , url ) NOT MAPPED — structured notification requirements controls — control_id[] → one links[rel=related, href=#{NIST_RESOURCE_UUID}, resource-fragment={id}, text="NIST SP 800-53 Rev 5 {ID}"] per item (see §10) terms — string[] NOT MAPPED — FRD term references 5.2 Varies-by-Class Rule (has varies_by_class , no statement or force ) The rule becomes a parent control with a fixed statement, and each class variant becomes a child control nested in the parent's controls list (see MISSING_FROM_OSCAL_LIBRARY.md §4 for the library workaround). Parent control: Schema field Required Type OSCAL mapping (key) — frr_requirement_id → control.id , props[name=label].value name ✓ string → control.title (hardcoded) — — → parts[name=statement].prose = "Varies by Class" (scope) — — → props[name=path, ns=FRR_NS].value = "all" | "20x" | "rev5" related — string[] → one links[rel=related, href=#{id}] per item affects ✓ affected_party[] → one props[name=affects, ns=FRR_NS] per item note — string → parts[name=guidance, title=Notes].prose notes — string[] → parts[name=guidance, title=Notes].prose (items joined with blank lines) corrective_actions — string[] → parts[name=remediation, ns=FRR_NS].prose examples — object[] → parts[name=guidance, class=examples, title=Examples].prose schema — rule_schema → parts[name=guidance, class=schema, title=Schema].prose following_information — string[] → parts[name=guidance, class=following_information, title=Following Information].prose updated ✓ updated_list → one props[name=updated, ns=FRR_NS, value=date, remarks=comment] per entry following_information_bullets — string[] → parts[name=statement, id={id}_smt].parts[name=item].prose (each item prefixed with - ) reference — string → links[rel=reference].text (used as link text when reference_url is also present) reference_url — URI → links[rel=reference, href={url}] ; .text set to reference value when present effective_date — effective_dates → props[name=effective_date, ns=FRR_NS].value (JSON-serialised when value is an object) timeframe_type — enum → props[name=timeframe_type, ns=FRR_NS].value timeframe_num — positive number → props[name=timeframe_num, ns=FRR_NS].value (number converted to string) notification — object[] NOT MAPPED controls — control_id[] → one links[rel=related, href=#{NIST_RESOURCE_UUID}, resource-fragment={id}, text="NIST SP 800-53 Rev 5 {ID}"] per item (see §10) terms — string[] NOT MAPPED 6. varies_by_class.{a|b|c|d} → OSCAL Child Control ( frr_requirement_level ) Each class key ( a , b , c , d ) becomes a child control appended directly to the parent control's controls list. Schema field Required Type OSCAL mapping (key, uppercased) — "a" … "d" → control.id = "{parent-id}-{key}" , props[name=label].value = "Class {KEY}" (label as title) — — → control.title = "Class {KEY}" (class entries have no name field) (scope) — — → props[name=path, ns=FRR_NS].value (inherited from parent rule's scope) statement ✓ string → parts[name=statement, id={id}_smt].prose force ✓ force_enum → props[name=force, ns=FRR_NS].value note — string → parts[name=guidance, title=Notes].prose notes — string[] (min 2) → parts[name=guidance, title=Notes].prose (items joined with blank lines) artifacts.all — string[] → parts[name=assessment-method, props=[method=EXAMINE, path=all]].parts[name=assessment-objects].prose artifacts.20x — string[] → parts[name=assessment-method, props=[method=EXAMINE, path=20x]].parts[name=assessment-objects].prose artifacts.rev5 — string[] → parts[name=assessment-method, props=[method=EXAMINE, path=rev5]].parts[name=assessment-objects].prose following_information — string[] → parts[name=guidance, class=following_information, title=Following Information].prose following_information_bullets — string[] → parts[name=statement, id={id}_smt].parts[name=item].prose (each item prefixed with - ) rev5_controls_list — object (family → rev5_control_id[] ) → used for Rev5 profile control selection (not written to the catalog); control IDs are converted to OSCAL format and added to the appropriate Rev5 class profile's include list effective_date — effective_dates → props[name=effective_date, ns=FRR_NS].value (JSON-serialised when value is an object) timeframe_type — enum → props[name=timeframe_type, ns=FRR_NS].value timeframe_num — positive number → props[name=timeframe_num, ns=FRR_NS].value (number converted to string) pain_timeframes — object (PAIN level 1–5 → timeframe) NOT MAPPED — PAIN score-based response timeframe table 7. Supporting Types Summary Type Used in Description force_enum rule, class variant MUST | MUST NOT | SHOULD | SHOULD NOT | MAY affected_party rule, subset applicability Advisors | Agencies | Assessors | FedRAMP | Providers | Everyone certification_type subset applicability 20x | Rev5 certification_path subset applicability Program | Agency class_name subset applicability A | B | C | D timeframe_type rule, class variant bizdays | days | hours | weeks | months | years updated_list rule Array of {date, comment} changelog entries effective_entry document info {is, current_status, date, comments, warnings, signup_url} effective_dates rule, class variant {obtain, maintain, optional_adoption, grace} dates notification rule {party, method, target, name, url} — who to notify, how, and where rule_schema rule {name, url} — machine-readable schema governing artifacts pain_timeframes class variant PAIN severity 1–5 → response timeframe table rev5_controls_list class variant NIST SP 800-53 Rev5 family → control ID list artifact_list artifacts string[] — plain-text artifact descriptions control_id rule ^[a-z]{2}-\d+(\.\d+)?$ — NIST SP 800-53 control ID 8. Summary of Unaddressed Fields The following fields appear in the source data but are not yet mapped to OSCAL output. They are recorded in data/unhandled.json at runtime. Field Appears in Description notification rule Structured notification requirements (party, method, target, URL) terms rule References to defined terms in the FRD pain_timeframes class variant PAIN severity 1–5 → response timeframe lookup table 9. Catalog Metadata — Roles, Parties, and Responsible-Parties The following entries are written to the catalog metadata section by _add_catalog_contacts() regardless of source-JSON content. They are not derived from the FRR data. 9.1 Roles Role id title fedramp FedRAMP system-owner System Owner assessor Assessor agency Agency 9.2 Parties name type uuid constant Extra fields FedRAMP PMO organization _PARTY_UUID_FEDRAMP email-addresses: [info@fedramp.gov] , links[rel=website, href=https://www.fedramp.gov] Cloud Service Provider organization _PARTY_UUID_CSP — Assessing Organization organization _PARTY_UUID_AO — Federal Agency organization _PARTY_UUID_AGENCY — 9.3 Responsible-Parties role-id party-uuids fedramp [_PARTY_UUID_FEDRAMP] system-owner [_PARTY_UUID_CSP] assessor [_PARTY_UUID_AO] agency [_PARTY_UUID_AGENCY] 10. Catalog Back-Matter — NIST SP 800-53 Rev 5 Resource A single back-matter resource is added to the catalog by build_catalog() so that controls citations on rules can reference it via UUID fragment. The resource UUID is the stable module-level constant _NIST_800_53_REV5_RESOURCE_UUID . Field Value uuid _NIST_800_53_REV5_RESOURCE_UUID ( ffffffff-0000-4000-a000-000000000001 ) title "NIST SP 800-53 Rev 5" rlinks[0].href NIST_800_53_REV5_URL — OSCAL JSON on GitHub raw rlinks[1].href NIST_800_53_REV5_DOI_URL — canonical DOI ( https://doi.org/10.6028/NIST.SP.800-53r5 ) Each NIST control ID listed in a rule's controls array produces a link on the OSCAL control: links[ rel = "related", href = "#{NIST_RESOURCE_UUID}", resource-fragment = {control-id}, text = "NIST SP 800-53 Rev 5 {CONTROL-ID}", ← id uppercased ] The resource-fragment field identifies the specific control within the referenced catalog without requiring a separate per-control back-matter entry. The text field provides a human-readable label with the control ID in uppercase. Overview