Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,620 changes: 1,620 additions & 0 deletions frameworks/NIST_CSF_v2.0_catalog.json

Large diffs are not rendered by default.

8,720 changes: 8,720 additions & 0 deletions frameworks/NIST_SP-800-53_rev5_catalog.json

Large diffs are not rendered by default.

1,053 changes: 1,053 additions & 0 deletions frameworks/NIST_SP800-171_rev3_catalog.json

Large diffs are not rendered by default.

484 changes: 484 additions & 0 deletions frameworks/NIST_SP800-218_ver1_catalog.json

Large diffs are not rendered by default.

237 changes: 237 additions & 0 deletions frameworks/secure-controls-framework-scf-2025-3-1.json

Large diffs are not rendered by default.

109 changes: 109 additions & 0 deletions source/Oscal-to-episki.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const fs = require("fs");
const path = require("path");

function loadJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, "utf8"));
}

function saveJson(filePath, data) {
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf8");
}

function convertOscalControl(oscalCtrl) {
const ref = oscalCtrl.id || oscalCtrl["control-id"] || "unknown";

const title =
oscalCtrl.title ||
(oscalCtrl["control-title"] ? oscalCtrl["control-title"] : "");

const description =
oscalCtrl.description && oscalCtrl.description[0]
? oscalCtrl.description[0].text
: "";

const subcontrols = (oscalCtrl.controls || []).map(c =>
convertOscalControl(c)
);

return {
ref: ref,
control: title,
description: description,
testingProcedures: [],
controls: subcontrols
};
}

function convertOscalCatalog(oscal) {
if (!oscal.catalog) {
throw new Error("File does not contain .catalog (not a valid OSCAL file)");
}

const catalog = oscal.catalog;

if (!catalog.groups && !catalog.controls) {
throw new Error("OSCAL catalog has no groups or controls");
}

let controls = [];

if (catalog.groups) {
for (const group of catalog.groups) {
if (group.controls) {
controls = controls.concat(group.controls);
}
}
}

if (catalog.controls) {
controls = controls.concat(catalog.controls);
}

return {controls: controls.map(convertOscalControl)};
}

async function main() {
const inputPath = process.argv[2];

if (!inputPath) {
console.error("Usage: node OSCAL-to-Episki.js <oscal-file.json>");
process.exit(1);
}

const fullPath = path.resolve(inputPath);

console.log("Loading:", fullPath);

let json;

try {
json = loadJson(fullPath);
} catch (err) {
console.error("❌ Failed to read JSON:", err.message);
process.exit(1);
}

console.log("Converting OSCAL → Episki…");

let result;

try {
result = convertOscalCatalog(json);
} catch (err) {
console.error("❌ Conversion error:", err.message);
process.exit(1);
}

const inputName = path.basename(fullPath, ".json");
const outPath = path.join(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix indentation

path.dirname(fullPath),
`${inputName}_episki.json`
);


saveJson(outPath, result);

console.log("✅ Done! Saved to:", outPath);
}

main();
101 changes: 101 additions & 0 deletions source/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
Episki Framework Converters
This folder contains a JavaScript-based converter that transforms external security frameworks into the Episki Security Format (ESF) required by the Episki application.

NIST OSCAL Catalogs (e.g., SP 800-53, 800-171, CSF 2.0) Oscal-to-Episki.ts JSON (OSCAL XML/JSON converted to JSON)

1. ⚙️ Requirements
You must install the following tools:
Node.js

Required version: 16+
Download: https://nodejs.org/

Files

All input JSON files must be placed in the same directory as the converter scripts.

2. 📥 Obtaining Original Framework Files
🔹 Where to get OSCAL JSON catalogs

Official NIST OSCAL repository:
👉 https://github.com/usnistgov/OSCAL

OSCAL catalogs (JSON files) are in:

/nist.gov/OSCAL-content/content/NIST/


Direct examples:

Framework OSCAL JSON File
NIST SP 800-53 Rev5 /NIST_SP-800-53_rev5/json/NIST_SP-800-53_rev5_catalog.json
NIST SP 800-171 Rev3 /NIST_SP-800-171_rev3/json/NIST_SP-800-171_rev3_catalog.json
NIST Cybersecurity Framework 2.0 /NIST_CSF/json/NIST_CSF_2.0.json
NIST SP 800-218 (SSDF) /NIST_SP-800-218/json/...

Download them into your local folder.

3. ▶️ Running the Converters
Convert OSCAL → Episki
node Oscal-to-Episki.ts SP800-53.json

Output
Each script generates a new file:

<originalName>-episki.json

Example:

Input: SP800-53.json
Output: SP800-53-episki.json

4. 📦 Expected Folder Structure
/your-folder/
├── Oscal-to-Episki.ts
├── SP800-53.json ← Input
└── SP800-53-episki.json ← Output

5. 🧩 Script Behavior
OSCAL → Episki

Extracts controls from catalog.groups[] and catalog.controls[]

Normalizes:

id → ref

title → control

extracts text from .description[0].text

Ensures Episki output structure:

{
ref: string,
control: string,
description: string,
testingProcedures: [],
controls: []
}

SCF → Episki

Accepts JSON produced by exporting .xlsx SCF sheets

Supports flexible column names:

"SCF Identifier"

"SCF Domain"

"Principle Intent"

"Cybersecurity & Data Privacy by Design (C|P) Principles"

6. 🔧 Development Notes

No external NPM dependencies are required.

The script runs under Node.