Skip to content

Repository files navigation

cybedtools cybedtools website

R-CMD-check test-coverage Codecov test coverage Lifecycle: experimental License: MIT R >= 4.1 DOI Context7

Concordance renders the framework data, the cross-framework comparisons, and the working scenarios without requiring R. Cite Concordance for site content, and cybedtools for the methodology and any element-level analysis.

A corpus of cybersecurity workforce and learning frameworks. Each carries a different schema and a different vocabulary. Comparing them (what’s specified where, where they overlap, how their structural commitments differ) has historically meant rebuilding the comparison from scratch every time, in a spreadsheet.

cybedtools makes the comparison one simple query.

The package ingests eight workforce competency frameworks (NICE, DCWF, SFIA, ENISA ECSF, the Czech CyQUAL, the Canadian Cyber Security Skills Framework, Singapore’s OTCCF, and Saudi Arabia’s SCyWF) and six pedagogical, learning-standards or body-of-knowledge frameworks (Cyber.org K-12, CSTA K-12 CS (2017), CSTA PK-12 CS (2026), ACM/IEEE CSEC2017, JRC DigComp 3.0, and the UK’s CyBOK). All fourteen are expressed in a shared cybed: semantic schema. A small set of R helpers queries across them as if they were one corpus.

It does not propose a replacement framework or attempt to re-author framework content. Existing frameworks retain their structure and vocabulary. The package adds a comparison layer.

A native Python package mirroring the R API is available: pip install cybedtools (see PyPI).

The documentation is indexed in Context7 and published as llms.txt for AI assistants.

Who it’s for:

  • cybersecurity education researchers comparing curricula across frameworks
  • workforce-development analysts mapping job roles to training requirements
  • framework authors and revisers checking structural coverage against peer frameworks
  • doctoral students writing dissertations that need cross-framework empirical claims

Framework

Type

Jurisdiction

Top-level units

Elements

License

NICE v2.2.0

workforce

US

53

2,225

US public domain + NIST worldwide grant

DCWF v5.1

workforce

US

74

4,052

US Government work, no US copyright

ECSF v1

workforce

EU

12

390

CC BY 4.0 (report); data files unmarked

SFIA 9

workforce

global

147

821

SFIA Foundation licence required

Cyber.org K-12 v1.0

pedagogy

US

116

492

CC BY-NC 4.0

CSTA K-12 CS (Rev 2017)

pedagogy

US

25

258

CC BY-NC-SA 4.0

ACM/IEEE CSEC2017

pedagogy

global

8

40

All rights reserved; educational use

DigComp 3.0

pedagogy

EU

26

884

CC BY 4.0

CyQUAL 1.2.0

workforce

CZ

161

3,340

Open data, attribution required

CCSSF 2022

workforce

CA

59

1,345

Government of Canada copyright

OTCCF v1.1

workforce

SG

61

1,612

CSA copyright; non-commercial academic

CSTA PK-12 CS (2026)

pedagogy

US

53

983

CC BY-NC-SA 4.0

SCyWF 1.5

workforce

SA

81

1,419

NCA written permission

CyBOK v1.1.0

pedagogy

UK

21

596

OGL v3.0

The “Top-level units” column reports each framework’s own top-level enumerated unit, and those units are not the same kind of thing. NICE, DCWF, ECSF, CyQUAL, the Canadian framework, OTCCF, and SCyWF declare roles. SFIA declares skills, CSEC2017 and CyBOK declare Knowledge Areas, DigComp 3.0 declares competence areas and competences, and Cyber.org K-12 and both CSTA editions use unnamed groupings that cybedtools labels StandardGroup. All of them subclass cybed:OrganizingUnit, so cross-framework queries reach them uniformly. How the “Elements” column counts, and how framework_summary reports strict, augmented, and per-role totals, is in docs/framework-data-sources.md.

What you could not do before

Counting what is in a framework is easy. Download it and count. The harder questions run across frameworks, and those used to mean parsing a NIST JSON file, a DoD spreadsheet, a SQLite database, an open-data export and two PDFs into one shape before the first comparison. cybedtools does that part. Three examples follow. Each runs in about a second.

Which frameworks are made of the same sentences?

library(cybedtools)
library(dplyr)
library(stringr)

rdf <- load_combined_ntriples_graph()

statements <- element_framework_bindings(rdf) |>
  anti_join(subpoint_framework_bindings(rdf), by = c("element" = "subpoint")) |>
  anti_join(example_framework_bindings(rdf), by = c("element" = "example")) |>
  inner_join(element_text(rdf), by = "element") |>
  mutate(
    text = text |>
      str_to_lower() |>
      str_remove("^\\s*\\*\\s+") |>
      str_remove("[[:punct:]\\s]+$") |>
      str_squish()
  ) |>
  filter(nchar(text) > 15) |>
  distinct(framework_name, text)

statements |>
  inner_join(statements, by = "text", suffix = c("", "_2"),
             relationship = "many-to-many") |>
  filter(framework_name < framework_name_2) |>
  count(framework_name, framework_name_2, sort = TRUE) |>
  slice_head(n = 6)
#> # A tibble: 6 × 3
#>   framework_name                                 framework_name_2              n
#>   <chr>                                          <chr>                     <int>
#> 1 CyQUAL 1.2.0                                   DCWF v5.1                  1400
#> 2 NICE v2.2.0 (NIST SP 800-181 Rev 1 components) SCyWF – 1.5: 2026           766
#> 3 CyQUAL 1.2.0                                   ECSF v1                     132
#> 4 CyQUAL 1.2.0                                   NICE v2.2.0 (NIST SP 800…   100
#> 5 DCWF v5.1                                      NICE v2.2.0 (NIST SP 800…   100
#> 6 DCWF v5.1                                      SCyWF – 1.5: 2026            78

The largest block of shared text in the corpus is between CyQUAL, the Czech national framework, and DCWF, the US Department of Defense framework: 1,400 statements, word for word. Neither names the other as a source. Each shares only 100 statements with the current NICE Framework. What they have in common is the 2017 NICE Framework. Checked against NIST’s 2017 release, nearly all of what the two share is 2017 NICE text, and under 5 percent of that 2017 text survives in NICE v2.2.0. The 2017 edition is better preserved in Prague and at the Pentagon than at NIST. Canada’s framework describes itself as an adaptation of NICE and shares under 1 percent of its statements with anything. The second-largest block belongs to Saudi Arabia’s SCyWF, which shares 766 statements with NICE v2.2.0.

Which frameworks have nothing to say about a topic?

library(purrr)

topics <- c(
  ai           = "machine learning|artificial intelligence|neural network",
  ethics       = "ethic|moral",
  cryptography = "cryptograph|encrypt",
  supply_chain = "supply chain|third.party"
)

all_text <- element_framework_bindings(rdf) |>
  inner_join(element_text(rdf), by = "element")

imap(topics, \(pattern, topic) {
  all_text |>
    summarise(
      "{topic}" := sum(str_detect(text, regex(pattern, ignore_case = TRUE))),
      .by = framework_name
    )
}) |>
  reduce(left_join, by = "framework_name") |>
  left_join(
    count(all_text, framework_name, name = "statements"),
    by = "framework_name"
  ) |>
  relocate(statements, .after = framework_name) |>
  arrange(desc(statements)) |>
  print(n = Inf)
#> # A tibble: 14 × 6
#>    framework_name              statements    ai ethics cryptography supply_chain
#>    <chr>                            <int> <int>  <int>        <int>        <int>
#>  1 DCWF v5.1                         4052    24     12           52           18
#>  2 CyQUAL 1.2.0                      3340     1      9           29           18
#>  3 NICE v2.2.0 (NIST SP 800-1…       2225     2      3           26           22
#>  4 Operational Technology Cyb…       1612     1      6           31           12
#>  5 SCyWF – 1.5: 2026                 1419     8      1           18           12
#>  6 Canadian Cyber Security Sk…       1345     0      5           36           29
#>  7 2026 CSTA PK-12 Computer S…        983    34     46            9            1
#>  8 DigComp 3.0                        884     6     79            0            0
#>  9 SFIA 9                             821     6     15            0           11
#> 10 CyBOK v1.1.0                       596     1      1           29            0
#> 11 Cyber.org K-12 Learning St…        492     0      8           10            0
#> 12 ECSF v1                            390     0      4            0            1
#> 13 CSTA K-12 Computer Science…        258     2      8            3            0
#> 14 CSEC2017 Curricular Guidel…         40     0      3            1            1

Four of the fourteen frameworks contain no statement that mentions artificial intelligence or machine learning. DCWF has 24 such statements, more than the other seven workforce frameworks combined (18). The 2026 CSTA standards, which add a machine learning subconcept at every foundational level, have 34. NICE has three statements that mention ethics, out of 2,225. SFIA, ECSF and DigComp have none that mention cryptography.

This measures the words a framework uses. It does not measure what a framework covers. OTCCF is a framework about operational technology and scores zero on the phrase “operational technology”, because CSA writes “OT”. A zero in this table is a reason to go and read the framework.

Which frameworks reuse statements across roles?

role_element_bindings(rdf) |>
  semi_join(role_framework_bindings(rdf), by = "role") |>
  count(element, name = "n_roles") |>
  inner_join(element_framework_bindings(rdf), by = "element") |>
  summarise(
    statements    = n(),
    mean_roles    = round(mean(n_roles), 1),
    max_roles     = max(n_roles),
    used_once_pct = round(100 * mean(n_roles == 1)),
    .by = framework_name
  ) |>
  arrange(desc(mean_roles))
#> # A tibble: 7 × 5
#>   framework_name                   statements mean_roles max_roles used_once_pct
#>   <chr>                                 <int>      <dbl>     <int>         <dbl>
#> 1 CyQUAL 1.2.0                           3151        5          50            33
#> 2 SCyWF – 1.5: 2026                      1418        3.4        40            36
#> 3 NICE v2.2.0 (NIST SP 800-181 Re…       1877        2.9        41            51
#> 4 DCWF v5.1                              4052        2.4        74            55
#> 5 ECSF v1                                 390        1           1           100
#> 6 Canadian Cyber Security Skills …       1345        1           1           100
#> 7 Operational Technology Cybersec…        270        1           1           100

Four of the role-based frameworks attach one statement to many roles. Three never do. In DCWF, 8 statements are attached to all 74 work roles, which makes them a common core the framework does not name. In CyQUAL the most widely shared statement reaches 50 of 102 roles. In SCyWF, 4 statements are attached to all 40 job roles. In ECSF, CCSSF and OTCCF every statement belongs to exactly one role, so “how many roles need this skill” cannot be answered from those frameworks’ own data, and an element count does not show the difference. OTCCF’s row counts the key tasks attached to its job roles. Its skill statements attach to skills.

Finding things with cybedtools

The frameworks in the corpus were authored independently, for different audiences, at different times and with different units of analysis (work role, skill level, competence, learning standard, Knowledge Area, competence area). They specify in different formats and under different licenses. They do not agree on what to count. cybedtools makes them queryable in one graph anyway. Three findings follow.

Per-unit density varies by 13x across the corpus

DCWF v5.1 expresses 54.8 elements per top-level unit. Cyber.org K-12 v1.0 expresses 4.2. The spread reflects design philosophy more than completeness. NICE and DCWF are granular by intent, as the basis for hiring and training pipelines. ENISA’s ECSF and JRC’s DigComp are high-level by intent, as an interoperability frame and a citizen self-assessment instrument. Per-unit density is a comparison aid across unlike denominators. It is not a quality claim. framework_summary also carries a _strict variant for analyses that prefer each framework’s own count.

US frameworks are about 43 percent of the corpus, and NICE’s reach is wider than that

The corpus spans 8 jurisdictions and 18,457 elements, counted with parsed examples included. US frameworks (NICE v2.2.0, DCWF v5.1, Cyber.org K-12 v1.0, CSTA K-12 CS (Rev 2017), CSTA PK-12 CS (2026)) contribute 8,010 of them. The two EU-level frameworks (ECSF v1 and DigComp 3.0) contribute 1,274, which reflects design intent: ECSF profiles point to e-CF 4.0 competences instead of restating them, and DigComp is an intentionally high-level citizen self-assessment instrument. Counting by jurisdiction understates how far one framework travels. Canada’s framework describes itself as an adaptation of NICE for the Canadian labour market and cites NICE work roles throughout. CyQUAL says its structure and elements were adopted from NICE, and its task list carries the 2017 NICE task codes. Both describe the borrowing openly. The graph makes it countable. Element counts used as a coverage metric are evidence of lineage and design, and they do not measure how much work a framework represents.

Five NICE work roles carry a disproportionate share of the specification

Security Control Assessment (304 elements), Secure Systems Development (237), Cybersecurity Architecture (218), Defensive Cybersecurity (205), Systems Security Management (201). Curricula that “cover NICE” by surveying these five look thorough. Curricula that cover the long tail of 42 work roles look thin by element count alone. This describes NICE’s internal weighting and says nothing about the rest of the corpus.

Each finding is one query and a few lines of dplyr. See below.

Quick check after install

make_demo_graph() returns an in-memory two-framework synthetic graph that exercises every domain helper without staged data. If this runs cleanly, your install is sound:

library(cybedtools)
library(dplyr)

rdf <- make_demo_graph()

# One row per framework with jurisdiction, sector, and specificity attached.
framework_metadata(rdf) |>
  arrange(jurisdiction, name)
#> # A tibble: 2 × 5
#>   framework                                name  jurisdiction sector specificity
#>   <chr>                                    <chr> <chr>        <chr>  <chr>      
#> 1 https://w3id.org/cybed/ontology#framewo… Demo… EU           gener… general-IT 
#> 2 https://w3id.org/cybed/ontology#framewo… Demo… US           civil… cybersecur…

The same helpers run against the staged framework graph by swapping make_demo_graph() for load_combined_ntriples_graph().

A query against the framework corpus

Once the combined graph is staged (see Getting started), one expression returns per-unit density per framework, sorted descending:

rdf <- load_combined_ntriples_graph()

organizing_unit_framework_bindings(rdf) |>
  count(framework_name, name = "top_level_unit_count") |>
  left_join(
    element_framework_bindings(rdf) |>
      count(framework_name, name = "element_count"),
    by = "framework_name"
  ) |>
  mutate(elements_per_unit = round(element_count / top_level_unit_count, 1)) |>
  arrange(desc(elements_per_unit))
#> # A tibble: 14 × 4
#>   framework_name            top_level_unit_count element_count elements_per_unit
#>   <chr>                                    <int>         <int>             <dbl>
#> 1 DCWF v5.1                                   74          4052              54.8
#> 2 NICE v2.2.0 (NIST SP 800…                   53          2225              42  
#> 3 DigComp 3.0                                 26           884              34  
#> 4 ECSF v1                                     12           390              32.5
#> 5 CyBOK v1.1.0                                21           596              28.4
#> 6 Operational Technology C…                   61          1612              26.4
#> 7 Canadian Cyber Security …                   59          1345              22.8
#> 8 CyQUAL 1.2.0                               161          3340              20.7
#> # ℹ 6 more rows

Jurisdiction pivots, top-load NICE roles, pairwise framework comparisons, and the librdf single-BGP discipline are covered in the cross-framework-analysis vignette. Extending the schema to a new framework is covered in adding-a-framework.

Getting started

Install the package, then fetch the public data release: hash-verified per-framework files, downloaded once and cached locally. No source framework text needs to be staged for this path.

R

# install.packages("remotes")
remotes::install_github("ryanstraight/cybedtools")

Python

pip install cybedtools

Fetch data and load a graph

R:

library(cybedtools)

# Downloads and hash-verifies every shipped framework's release file into
# the R user cache directory, then parses them into one rdf object.
rdf <- load_graph()

framework_summary

Python:

from cybedtools import load_graph, framework_summary

graph = load_graph()
framework_summary()

load_graph() calls cybed_fetch() internally (a no-op for files already cached with a verified hash). Both accept either the versioned framework slug ("nice-v2") or the short release-file slug ("nice"); see cybed_fetch()’s documentation for the two-vocabulary mapping. The data release backing this package version is archived on Zenodo: 10.5281/zenodo.22884320.

Three queries

R:

# 1. What's in the corpus?
framework_summary |>
  dplyr::select(framework_slug, framework_name, jurisdiction, organizing_unit_count)

# 2. Which elements does an organizing unit carry?
unit_element_bindings(rdf) |>
  head(10)

# 3. Where do two frameworks say the same thing?
framework_similarity(rdf, from = "nice", to = "ecsf", n = 3)

Python:

# 1. What's in the corpus?
framework_summary()[["framework_slug", "framework_name", "jurisdiction", "organizing_unit_count"]]

# 2. Which elements does an organizing unit carry?
from cybedtools import unit_element_bindings
unit_element_bindings(graph).head(10)

# 3. Where do two frameworks say the same thing?
from cybedtools import framework_similarity
framework_similarity(graph, from_="nice", to="ecsf", n=3)

The function reference indexes the full public API for both languages.

Rebuilding the graph from source (maintainers)

Fetching the public release (above) is the path for using the corpus. Rebuilding it from primary sources is a separate, maintainer-only path: the package does not redistribute source framework text, so this requires cloning the repository and staging each framework’s source file at data/raw/<framework>/ per docs/framework-data-sources.md.

git clone https://github.com/ryanstraight/cybedtools
cd cybedtools

# Stage source files, then:
Rscript scripts/000-build.R   # ingestion + verification + assembly + export

scripts/000-build.R is the pipeline’s entry point: it runs ingestion, verification, JSON-LD assembly, and N-Triples export in order (see scripts/README.md for the full stage list). The getting-started vignette walks through each stage.

Citing

If you use cybedtools in published work, see CITATION.cff or run citation("cybedtools") for the canonical citation. Dropping me a line would also be appreciated!

License

Package code is MIT (see LICENSE.md). Each framework retains its upstream license, and source text is not bundled. Users stage source files locally per docs/framework-data-sources.md, and each ingestion script writes a per-framework provenance.yml. See LICENSING.md for layered guidance on academic vs. commercial use.

Three frameworks here come on terms narrower than MIT, all represented by written permission of their stewards. Those terms were given to cybedtools and do not pass to you.

  • Derived from the Operational Technology Cybersecurity Competency Framework (OTCCF), published by the Cyber Security Agency of Singapore (CSA). Available at: https://www.csa.gov.sg/resources/publications/operational-technology-cybersecurity-competency-framework--otccf-/ CSA’s permission covers the framework’s structure, for non-commercial, academic and research use.
  • Canadian Centre for Cyber Security, The Canadian Cyber Security Skills Framework (ITSM.00.039), 2022 edition. Copyright Government of Canada. Used with permission of the Canadian Centre for Cyber Security.
  • CyQUAL, the Czech national cybersecurity qualifications framework, developed at Masaryk University. Open data, version 1.2.0, https://platform.cyqual.cz/.

Code of Conduct

Please note that the cybedtools project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.

About

Reproducible pipeline for ingesting and analyzing cybersecurity workforce and learning frameworks via JSON-LD and SPARQL

Topics

Resources

Code of conduct

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages