npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mitre/hdf-extension-graph

v3.2.0

Published

Bidirectional extension graph processing for HDF profile/baseline hierarchies

Downloads

241

Readme

@mitre/hdf-extension-graph

Bidirectional extension graph processing for HDF baseline hierarchies.

Why this exists

HDF baseline documents can represent 'overlay' structures that form extension chains of parent baselines and their children. For example, a DISA STIG baseline defines hundreds of requirements; an organizational overlay on that DISA baseline can modify a subset for organization-specific policies; a project overlay can further tighten thresholds for a specific system. When an HDF results file contains multiple baselines linked via parentBaseline, understanding what each layer changed requires walking these chains bidirectionally.

Without this library, answering "did this overlay change the impact of SV-238196, or inherit it unchanged?" requires manually cross-referencing requirements across baselines by ID. The extension graph provides:

  • root — jump from any overlay requirement to the original base definition
  • modifications — which fields (impact, title, severity, effectiveImpact, disposition) an overlay changed relative to its parent
  • isRedundant — whether an overlay re-declares a control without actually changing it
  • fullCode — the complete code from all layers in one string
  • extensionChain — the ordered list of baselines from root to leaf

This is the same graph algorithm that powers Heimdall's control detail panel, extracted as a standalone library.

Installation

pnpm add @mitre/hdf-extension-graph

Requires @mitre/hdf-schema as a peer dependency.

Usage

Build the graph

import { buildExtensionGraph } from '@mitre/hdf-extension-graph';
import type { HdfResults } from '@mitre/hdf-schema';

const hdfResults: HdfResults = JSON.parse(fileContents);
const graph = buildExtensionGraph(hdfResults);

Navigate baselines

// Find root baselines (no parent)
const roots = graph.rootBaselines;

// Find a specific baseline
const stig = graph.findBaseline('rhel9-stig-baseline');

// See what extends it
for (const overlay of stig.extendedBy) {
  console.log(`${overlay.data.name} extends ${stig.data.name}`);
}

Navigate requirements

// Find all instances of a control across all baselines
const controls = graph.findRequirements('SV-238196');

// Get the root (base) control
const root = controls[1].root; // walks up the chain

// Get the full code with all layers
console.log(controls[1].fullCode);
// # my-overlay
// describe sshd_config do
//   its("ClientAliveInterval") { should cmp <= 300 }
// end
//
// # rhel9-stig-baseline
// describe sshd_config do
//   its("ClientAliveInterval") { should cmp <= 600 }
// end

Detect changes

const overlay = graph.baselines[1].requirements[0];

// Is this overlay just inheriting, or did it change something?
if (!overlay.isRedundant) {
  console.log('This overlay modifies the base control');
}

// What specifically changed?
for (const mod of overlay.modifications) {
  console.log(`${mod.field}: ${mod.originalValue} → ${mod.newValue}`);
}
// impact: 0.5 → 0.9
// title: SSH timeout → SSH timeout (project)

Walk the chain

// Ordered list of baselines from root to current
const chain = overlay.extensionChain;
console.log(chain.map(b => b.data.name));
// ['disa-rhel7-stig', 'cms-rhel7-overlay', 'project-overlay']

API

buildExtensionGraph(results: HdfResults): ExtensionGraph

Builds a bidirectional extension graph from an HDF Results file. Links baselines via parentBaseline and requirements by matching id across linked baselines.

ExtensionGraph

| Property / Method | Type | Description | |---|---|---| | baselines | ContextualizedBaseline[] | All baselines in the graph | | requirements | ContextualizedRequirement[] | All requirements across all baselines | | rootBaselines | ContextualizedBaseline[] | Baselines with no parent | | findBaseline(name) | ContextualizedBaseline \| undefined | Find baseline by name | | findRequirements(id) | ContextualizedRequirement[] | Find all requirements with given id |

ContextualizedBaseline

| Property | Type | Description | |---|---|---| | data | EvaluatedBaseline | Original baseline data | | sourcedFrom | HdfResults | The results file this came from | | extendsFrom | ContextualizedBaseline[] | Parent baselines | | extendedBy | ContextualizedBaseline[] | Child baselines | | requirements | ContextualizedRequirement[] | Wrapped requirements |

ContextualizedRequirement

| Property | Type | Description | |---|---|---| | data | EvaluatedRequirement | Original requirement data | | sourcedFrom | ContextualizedBaseline | Owning baseline | | extendsFrom | ContextualizedRequirement[] | Parent requirements | | extendedBy | ContextualizedRequirement[] | Child requirements | | root | ContextualizedRequirement | Base requirement at bottom of chain | | isRedundant | boolean | True if code is empty or matches root | | fullCode | string | Concatenated code from all layers | | extensionChain | ContextualizedBaseline[] | Baselines from root to leaf | | modifications | Modification[] | Fields changed vs immediate parent |

Modification

interface Modification {
  field: string;        // 'impact', 'title', or 'severity'
  originalValue: unknown;
  newValue: unknown;
  inBaseline: string;   // Name of the baseline making the change
}

Notes

License

Apache-2.0