mcpField
N
netbox-validation

netbox-validation

github.com/netboxlabsCloud & DevOps2148 installsUpdated 2w ago
Repository

About netbox-validation

NetBox Validation is a skill for validating infrastructure data against declarative policies with intent, configuration, and graph analysis. It helps NetBox operators run checks, review findings, and track compliance scores through the Validation plugin.

Key features

  1. 01Intent, config, and graph checks
  2. 02Scoped policies and configurable rules
  3. 03Per-device results and findings
  4. 04Compliance scores tracked over time
  5. 05Policy pack installation and YAML import/export

Use cases

  1. 01Check infrastructure data against standards
  2. 02Review critical or open validation findings
  3. 03Validate a change-request branch before merge
  4. 04Track device and policy compliance

MCP support

The skill notes that NetBox Platform MCP can provide five tools for running validation, querying compliance, and managing policies. NetBox MCP can provide read-only verification access.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/netboxlabs/skills --skill netbox-validation

After installing, type/netbox-validationin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
api-patterns.md
check-reference.md
policy-packs.md

Details

From the project README

NetBox Validation

NetBox Validation continuously validates infrastructure data against declarative policies using three engines — intent (NetBox data), config analysis (rendered configurations), and graph analysis (infrastructure dependencies). It produces per-device results, aggregated findings, and compliance scores.

Your knowledge of NetBox Validation may be outdated. Check names, API fields, policy pack contents, and engine capabilities evolve between releases. Prefer retrieval over pre-trained knowledge.

Current plugin: 1.14.3 (2026-10-06). NetBox 4.7 support arrived in 1.14.0; the plugin declares NetBox 4.4–4.7.x, and the docs require NetBox 4.5+ (NetBox Cloud). Run ≥ 1.14.0 on NetBox 4.7. See Version Notes.

Retrieval Sources

SourceURL / MethodUse for
Validation docshttps://netboxlabs.com/docs/validation/Full reference, engines, check catalog, policy packs
Validation REST APIhttps://netboxlabs.com/docs/validation/api-reference/Endpoint details
NetBox Platform MCPIf configured — 5 validation toolsRun validation, query compliance, manage policies
NetBox MCP serverIf configured — read-only accessVerify devices, policies, scores

FIRST: Verify Connectivity

Confirm the Validation plugin is installed and your token has access:

curl -s -H "Authorization: Bearer $NETBOX_TOKEN" \
  "$NETBOX_URL/api/plugins/validation/policies/" | python -m json.tool

You should see a paginated list of policies (or empty results). If you get 404, the Validation plugin is not installed. If 403, your token lacks validation permissions.


Core Concepts

Object Hierarchy
Policy (scope + rules + triggers)
  -> Run (execution of a policy against devices)
    -> Results (per-device, per-check pass/fail/warning/error/skip)
      -> Findings (aggregated failures, actionable items)
        -> Compliance Scores (per-device, per-policy, 0-100%)
Policy

A Validation Policy defines what to check and where. Scope filters: sites, regions, site groups, device roles, platforms, tags. Contains rules and controls engine toggles, triggers, and cron schedule.

Rules

Each rule specifies:

FieldDescription
engineintent, config, or graph
categoryCheck grouping — addressing, redundancy, standards, completeness, security_intent, topology, reachability, power, infrastructure, routing, security, baseline, overlay
check_nameSpecific check to run (e.g., no_duplicate_ips)
severitycritical, high, medium, low, or info
parametersCheck-specific config (thresholds, patterns, expected values)

Rules can optionally override the policy scope with their own roles and platforms filters (lists of IDs).

Three Engines
EngineChecksEvaluatesData SourceKey Strength
Intent44NetBox data relationshipsNetBox ORMFast, no external dependencies
Config35Rendered device configurationsConfig analysis engine (from NetBox Config Templates)Structural analysis, reachability
Graph16Infrastructure dependency graphNetBox ORMBlast radius, failure domains

All three can coexist in a single policy. Config and graph engines are available to Premium tier customers. The config engine analyzes configurations rendered from NetBox Config Templates — assign templates to devices (via device, platform, or role) before enabling it.

Run Statuses
StatusMeaning
pendingCreated, waiting for execution
runningChecks are executing
passedAll checks passed
failedOne or more checks failed
errorEngine error during execution

Since plugin 1.12.0 each run is linked to its NetBox background job, bounded by a job timeout, and orphaned runs (worker lost mid-run) are reaped rather than left in running.

Each run exposes job_id (the core background Job). The plugin settings job_timeout (default 3600s) and run_retention_days (default 180; <= 0 disables) govern this: completed runs older than the window are pruned by the hourly housekeeping job, which never prunes in-flight runs and always keeps each policy's most recent run.

Result Statuses

Each per-device, per-check result: pass, fail, skip, warning, or error. Results carry expected, actual, message, remediation and extra (engine-specific detail).

Finding Lifecycle
open -> acknowledged -> resolved
                    \-> suppressed
StatusWhen to use
openNew, needs review
acknowledgedReviewed, remediation planned
resolvedFixed and confirmed by passing run
suppressedIntentional exception, risk accepted
Compliance Score
score = passed / (passed + failed + error) x 100

Skipped checks excluded. Scores are per (device, policy, run) and tracked over time.


Quick Reference — Common Workflows

Create and Execute a Run

Creating a run does NOT execute it. Two-step process:

# Step 1: Create the run — policy, trigger AND status are required (400 without "status")
RUN=$(curl -s -X POST "$NETBOX_URL/api/plugins/validation/runs/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"policy": 1, "trigger": "manual", "status": "pending"}')

RUN_ID=$(echo $RUN | python -c "import sys,json; print(json.load(sys.stdin)['id'])")

# Step 2: Execute it (synchronous — returns when complete)
curl -X POST "$NETBOX_URL/api/plugins/validation/runs/$RUN_ID/execute/" \
  -H "Authorization: Bearer $NETBOX_TOKEN"

The execute endpoint is synchronous — it returns the completed run (status, counts, score). Do not poll. Only pending (or error) runs can be executed; re-executing a finished run returns 400.

Install a Policy Pack
# List available packs (a bare JSON array)
curl "$NETBOX_URL/api/plugins/validation/policy-packs/" \
  -H "Authorization: Bearer $NETBOX_TOKEN"

# Install a pack (creates policy + all rules)
curl -X POST "$NETBOX_URL/api/plugins/validation/policy-packs/addressing-ipam/install/" \
  -H "Authorization: Bearer $NETBOX_TOKEN"
Query Compliance Scores
# Fleet-wide latest scores
curl "$NETBOX_URL/api/plugins/validation/compliance/" \
  -H "Authorization: Bearer $NETBOX_TOKEN"

# Scores for a specific device, newest first
curl "$NETBOX_URL/api/plugins/validation/compliance/?device_id=10&ordering=-measured_at" \
  -H "Authorization: Bearer $NETBOX_TOKEN"

# Scores for a specific policy
curl "$NETBOX_URL/api/plugins/validation/compliance/?policy_id=1" \
  -H "Authorization: Bearer $NETBOX_TOKEN"
Filter Findings
# Open critical findings from the latest run of each policy
curl "$NETBOX_URL/api/plugins/validation/findings/?latest=true&status=open&severity=critical" \
  -H "Authorization: Bearer $NETBOX_TOKEN"

# Acknowledge a finding
curl -X PATCH "$NETBOX_URL/api/plugins/validation/findings/42/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "acknowledged"}'
Run Against a Branch
curl -X POST "$NETBOX_URL/api/plugins/validation/runs/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"policy": 1, "trigger": "manual", "status": "pending", "branch_id": 5}'

The validation engines read rules from main and execute checks in branch context, seeing branch-overlay data.

Targeted Run (Narrow Scope)
# Target specific site(s)
curl -X POST "$NETBOX_URL/api/plugins/validation/runs/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"policy": 1, "trigger": "api", "status": "pending", "target_sites": [9]}'

# Validate a single device across all matching policies
curl -X POST "$NETBOX_URL/api/plugins/validation/runs/validate-device/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"device": 101}'
YAML Import/Export
# Export a single policy
curl -X POST "$NETBOX_URL/api/plugins/validation/policies/1/export/" \
  -H "Authorization: Bearer $NETBOX_TOKEN"

# Import a policy from YAML
curl -X POST "$NETBOX_URL/api/plugins/validation/policies/import/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d @my-policy.yaml

Policy Management

Policy Scoping

Policies scope devices via any combination of:

Scope FieldAPI fieldEffect
SitessitesOnly devices at these sites
RegionsregionsOnly devices at sites in these regions
Site Groupssite_groupsOnly devices at sites in these groups
Device RolesrolesOnly devices with these roles
PlatformsplatformsOnly devices on these platforms
Tagsdevice_tagsOnly devices with these tags

Each is a list of NetBox object IDs. Scope fields are AND-combined. An empty scope means all active devices. Unknown fields are silently ignored: a body with scope_sites creates an unscoped policy with no error, so read sites / roles back from the response after writing.

curl -X POST "$NETBOX_URL/api/plugins/validation/policies/" -H "Authorization: Bearer $NETBOX_TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "Leaf Baseline", "sites": [1, 2], "roles": [3], "device_tags": [7]}'

Choice fields (engine, category, severity on rules; trigger, status on runs; status, severity on results; severity, category, status on findings) read back as {"value", "label"} objects; writes take bare strings. The status/trigger inside a policy's latest_run summary are bare strings. Compare x["status"]["value"], not x["status"].

Engine Toggles
Policy FieldDefaultEffect
enable_config_enginefalseEnable config analysis checks for this policy
enable_graph_enginefalseEnable graph resilience checks for this policy
trigger_on_cr_submittrueRun when a change request is submitted
trigger_on_branch_mergefalseRun when a branch is merged

Intent checks always run. Config and graph checks require their engine to be enabled on the policy AND available at the deployment level.

Policy Packs

Pre-built policy packs provide one-click installation:

  • 14 starter packs (113 rules) — addressing, cabling, data quality, naming, redundancy, security intent, leaf/spine baselines, config analysis, pre-change config, BGP attributes, power/network/full resilience
  • 9 compliance frameworks (177 rules; Premium) — CLOS Fabric, TIA-942, NIS2/DORA, NIST 800-53, NERC CIP, PCI-DSS, MANRS, ISO 27001, HIPAA Security Rule (2026)

Starter packs are listed by default; framework packs appear (and can be installed) only when the plugin setting enabled_policy_packs includes "compliance" (default ["starter"]) — installing a disabled category returns 403. GET /policy-packs/ returns a bare JSON array (no count/results); each entry carries slug, name, description, category (starter | compliance), policy_count, rule_count, engines, installed, installed_policy_ids. Installed packs create regular policies and rules. After installation, customize scope, parameters, triggers, and schedule. See references/policy-packs.md.

Delete Rules and Policies

Since plugin 1.13.0, DELETE /rules/{id}/ and DELETE /policies/{id}/ preserve historical run results. Results keep rule_name and check_name snapshots, and runs and compliance scores keep policy_name; after a deletion the rule / policy FK fields are null, so read the *_name fields rather than assuming the FK is set. Policy-pack uninstall is no longer refused when runs exist — the pack's policies are removed and their run history is retained under the snapshotted policy name. Deleting a run (DELETE /runs/{id}/) is the one destructive path: it cascades the run's results, findings and compliance scores.

Clone and Import
# Clone a policy (copies all rules and scoping)
curl -X POST "$NETBOX_URL/api/plugins/validation/policies/1/clone/" \
  -H "Authorization: Bearer $NETBOX_TOKEN"

# Import from YAML
curl -X POST "$NETBOX_URL/api/plugins/validation/policies/import/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d @my-policy.yaml

Validation Triggers

TriggerHowNotes
ManualAPI create + execute, or "Run Now" in the UITwo-step: create (trigger: "manual", status: "pending"), then execute
Branch mergetrigger_on_branch_merge: trueRuns when a NetBox Branching branch is merged to main; catches regressions in the merged data
Change request submittrigger_on_cr_submit: true (default on)Runs when a NetBox Changes change request is submitted; targets the CR's branch for pre-merge safety
Scheduledcron in schedule — 0 2 * * * (daily 02:00), 0 */6 * * * (every 6 hours), 0 0 * * 0 (weekly)Targets main (no branch context); minimum interval 5 minutes

Run trigger values: manual, api, schedule, branch, merge, cr.

Run Scoping

All runs support optional target narrowing:

FieldTypeEffect
target_sitesList of site IDsOnly devices at these sites
target_devicesList of device IDsOnly these specific devices
target_tagsList of tag IDsOnly devices with these tags

Target fields AND-combine with the policy scope. They can only narrow, never widen. (The public API reference shows tag slugs for target_tags; the endpoint takes NetBox Tag IDs like the other target fields.)


Compliance and Findings

Score Dimensions

Compliance scores can be queried by device (across policies), policy (across devices), site/role (?site_id=, ?role_id=), and time (7d/30d/90d trend via the compliance dashboard and /compliance/trend/).

Finding Aggregation

Findings group related failures into actionable items. For example, if no_duplicate_ips fails for 5 devices, one finding groups all 5. Graph engine findings group by failure point (one finding per power feed or shared failure domain). Each finding carries affected_devices, is_new, recurrence_count, first_seen, policy_id/policy_name and has_blast_radius.

Severity Escalation

Graph engine findings automatically escalate severity based on blast radius:

Unprotected DevicesEscalation
1--2No change
3--5medium -> high
6--10high -> critical
10+Always critical
Finding Triage
  1. Filter findings by severity (critical first); use ?latest=true for current findings only
  2. Review detail: affected devices, expected vs actual, remediation
  3. For graph findings, check blast radius card
  4. Acknowledge findings you plan to fix
  5. Fix the underlying issue in NetBox
  6. Re-run validation to confirm
  7. Mark finding as resolved

Integration Patterns

Pre-Change Validation Pipeline
1. Create Branch          (netbox-branching)
2. Make changes           (normal NetBox API with X-NetBox-Branch header)
3. Submit Change Request  (netbox-changes) -> validation auto-runs
4. Review validation results
5. Approve CR, merge branch
6. Post-merge validation auto-runs (optional)

Set trigger_on_cr_submit: true for pre-merge safety. Set trigger_on_branch_merge: true for post-merge verification.

Branch Context

When running validation against a branch, pass branch_id on the run. The engines read rules from main and execute checks in branch context (seeing proposed additions, modifications, deletions).

Config analysis renders configs from both main and branch for differential analysis (lost reachability, broken BGP sessions, routing regressions).

Agentic Integration via MCP

The NetBox Labs Platform MCP Server provides 5 validation tools:

ToolPurpose
run_validationCreate + execute a run for a policy, optionally targeting a branch or devices
get_compliance_analyticsCompliance scores, trends, score-by-dimension
get_findings_analyticsFindings filtered by severity, status, category, policy
import_validation_policyImport policy from YAML
clone_validation_policyClone policy with all rules and scoping

Agents that prefer direct API access can use the REST endpoints with bearer token authentication.

Agentic Workflow Pattern
Agent creates branch -> makes changes -> runs validation
  Pass -> creates change request for human review
  Fail -> reads findings, self-corrects, re-validates

Validation provides the automated safety net ensuring agents operate within the same policy framework as human engineers.


Anti-Patterns

MistakeWhy It FailsDo This Instead
Create a run and assume it executesCreating a run sets status to pendingPOST to /runs/{id}/execute/ after creation
Omit trigger or status when creating runsBoth are required — 400 {"status": ["This field is required."]} (the public API reference omits status; the endpoint still requires it)Body is always {"policy": <id>, "trigger": "manual", "status": "pending"} (trigger may be "api" or "schedule")
Scope a policy with scope_sites / scope_roles / scope_tagsUnknown fields are silently dropped — the policy is created unscoped (all devices)Use sites, regions, site_groups, roles, platforms, device_tags (ID lists) and read sites/roles back from the response
Compare a choice field to a bare stringstatus, trigger, engine, category, severity read back as {"value", "label"}Compare ["value"]; write bare strings
Use branch integer ID for branch validationbranch_id on run creation expects the branch's integer ID, but X-NetBox-Branch header uses schema_idUse the correct identifier for each context
Install config/graph packs without enabling engineConfig/graph rules produce skip resultsSet enable_config_engine / enable_graph_engine on the policy
Install a compliance pack when only starter packs are enabledPOST .../install/ returns 403Add "compliance" to the plugin setting enabled_policy_packs
Treat skip as a failureSkips are excluded from scores and never create findingsRead the result message — no Config Template, no power ports, engine unavailable
Expect target scoping to widen policy scopeTarget fields AND-combine with policy scopeTargets can only narrow — devices outside policy scope are excluded
Poll for run completion after executeExecute is synchronous — returns when doneRead the response directly; no polling needed
Run graph checks with device targeting expecting savingsGraph engine loads all site devices regardlessUse site-scoped runs for graph-heavy policies

API Endpoints Summary

EndpointMethodsPurpose
/policies/GET, POSTList and create policies
/policies/{id}/GET, PUT, PATCH, DELETEManage a policy
/policies/{id}/clone/POSTClone with all rules and scoping
/policies/{id}/export/POSTExport as YAML
/policies/import/POSTImport from YAML
/policies/export-all/POSTExport all policies
/policies/{id}/run-for-site/POSTTargeted run for site(s) — {"sites": [...]}; creates and executes
/policies/{id}/run-for-devices/POSTTargeted run for device(s) — {"devices": [...]}; creates and executes
/rules/GET, POSTList and create rules (filter by policy_id, engine, category, severity, is_active)
/rules/{id}/GET, PUT, PATCH, DELETEManage a rule
/runs/GET, POSTList and create runs (filter by policy_id, status, trigger, branch_id, has_branch, created_after/before)
/runs/{id}/GET, DELETERun status and summary; DELETE removes the run and cascades its results, findings and scores
/runs/{id}/execute/POSTExecute a pending run
/runs/validate-device/POSTRun all matching policies for a device
/results/GETResults (filter by run_id, device_id, rule_id, status, severity, engine)
/findings/GET, POSTFindings (filter by run_id, severity, status, category, policy_id, device_id, site_id, role_id, branch_id, is_new, latest, q)
/findings/{id}/GET, PUT, PATCHUpdate finding status
/findings/summary/GETFinding counts by status, severity, category (respects filters)
/findings/bulk-update-status/POST{"ids": [...], "status": "..."} — bulk status change
/findings/matrix/GETCategory × severity counts of open findings (?site_id=, ?role_id=)
/compliance/GETCompliance scores (filter by device_id, policy_id, run_id, site_id, role_id)
/compliance/summary/GETFleet score, device count, finding counts
/compliance/trend/?days=NGETDaily compliance scores over time
/compliance/breakdown/?group_by=site|role|policyGETScores grouped by dimension (deleted policies keep their history under the snapshotted name)
/compliance/distribution/GETHistogram of device compliance scores
/compliance/worst-performers/?limit=NGETLowest-scoring devices
/policy-packs/GETBare array of packs (slug, category, rule_count, engines, installed, installed_policy_ids)
/policy-packs/{slug}/GETPack details plus policies[] and rules[]
/policy-packs/{slug}/install/POSTInstall a pack (403 if its category is not enabled)
/policy-packs/{slug}/uninstall/POSTUninstall a pack

All endpoints under /api/plugins/validation/.


Version Notes

Plugin 1.14.x (2026-09 – 2026-10)
  • 1.14.0: NetBox 4.7 support (declares 4.4–4.7.x).
  • 1.14.1: plugin-catalog metadata only.
  • 1.14.2: rule category gains routing, security, baseline and overlay (used by the shipped packs alongside addressing, redundancy, standards, completeness, security_intent, topology, reachability, power, infrastructure).
  • 1.14.3 (2026-10-06): no user-visible change.
NetBox 4.7 (2026-09-02)
  • Requires plugin 1.14.0+. Checks evaluate NetBox data server-side, so check names and parameters are unchanged.
  • What changes is the core REST API an agent uses to remediate findings: selection custom fields read as {"value", "label"} (write the raw value — relevant after custom_field_populated / asset_documentation_complete failures), config_context is present by default (omit it with ?omit=config_context on 4.7.3+) on device reads (?exclude=config_context ignored — use ?fields=), and services use port_mappings (["tcp/443"]) instead of protocol + ports. Failed bulk fixes return per-object errors by index. See netbox-api-integration.
  • Branch-context runs on 4.7 need netbox-branching 1.2.x (1.1.x for NetBox 4.4–4.6) — see netbox-branching.
Plugin 1.12–1.13 (2026-08)
  • 1.12.0: run lifecycle hardening (job timeout, orphaned-run reaper, run↔job linkage). 1.13.0: rules and policies deletable without losing run history.

References

ReferenceWhen to Load
references/api-patterns.mdNeed full API examples for policy/run/result lifecycle
references/check-reference.mdNeed check names, parameters, or engine details for all 95 checks
references/policy-packs.mdNeed pack catalog, slugs, install/customize guidance, framework details

Comments

Markdown supported