Skip to content

No Pre-Commit Validation Hook for Network Policy YAML Changes - IssueFinder - SN 21 #1445

@dinuduke

Description

@dinuduke

Problem Statement

The .pre-commit-config.yaml is comprehensive (gitleaks, hadolint, shellcheck) but has no validation hook for YAML network policy files. A malicious or accidental change to openclaw-sandbox.yaml (e.g., adding access: full to a new endpoint, or adding 0.0.0.0/0 as a host) would not be caught by any automated check before commit.

Impact

Policy changes that weaken security posture can be merged without automated detection.

Affected Area

  • File(s): .pre-commit-config.yaml, nemoclaw-blueprint/policies/

Steps to Reproduce

  1. Modify openclaw-sandbox.yaml to add host: "*" with access: full
  2. Run pre-commit run --all-files
  3. No hook catches the dangerous policy change

Expected Behavior

A pre-commit hook validates policy YAML against a security schema.

Actual Behavior

No validation occurs for policy YAML files.

Severity / Priority Suggestion

  • Medium

Proposed Design

Recommended Fix

Step 1 — Create scripts/validate-policies.js:

#!/usr/bin/env node
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
// SPDX-License-Identifier: Apache-2.0
"use strict";

const fs = require("fs");
const yaml = require("js-yaml");
const path = require("path");

const VALID_METHODS = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
const VALID_PROTOCOLS = new Set(["rest"]);
const VALID_ENFORCEMENTS = new Set(["enforce", "audit"]);
const VALID_ACCESS = new Set(["full"]);

function validatePolicy(filePath) {
  const content = fs.readFileSync(filePath, "utf-8");
  const doc = yaml.load(content);
  const errors = [];

  if (!doc.version) errors.push("Missing required field: version");

  const policies = doc.network_policies || {};
  for (const [name, policy] of Object.entries(policies)) {
    if (!policy.endpoints || !Array.isArray(policy.endpoints)) {
      errors.push(`${name}: endpoints must be an array`);
      continue;
    }
    for (const ep of policy.endpoints) {
      if (!ep.host) errors.push(`${name}: endpoint missing host`);
      if (!ep.port) errors.push(`${name}: endpoint missing port`);
      if (ep.protocol && !VALID_PROTOCOLS.has(ep.protocol))
        errors.push(`${name}: invalid protocol "${ep.protocol}"`);
      if (ep.access && !VALID_ACCESS.has(ep.access))
        errors.push(`${name}: invalid access "${ep.access}"`);
      if (ep.enforcement && !VALID_ENFORCEMENTS.has(ep.enforcement))
        errors.push(`${name}: invalid enforcement "${ep.enforcement}"`);
      if (ep.access && ep.rules)
        errors.push(`${name}: access:full and rules are mutually exclusive`);
      for (const rule of ep.rules || []) {
        const allow = rule.allow || {};
        if (allow.method && !VALID_METHODS.has(allow.method))
          errors.push(`${name}: invalid HTTP method "${allow.method}"`);
        if (allow.path && !allow.path.startsWith("/"))
          errors.push(`${name}: path must start with /: "${allow.path}"`);
      }
    }
  }
  return errors;
}

let exitCode = 0;
const files = process.argv.slice(2);
for (const f of files) {
  const errors = validatePolicy(f);
  if (errors.length > 0) {
    console.error(`\n❌ ${f}:`);
    errors.forEach((e) => console.error(`   - ${e}`));
    exitCode = 1;
  } else {
    console.log(`✅ ${path.basename(f)}`);
  }
}
process.exit(exitCode);

Step 2 — Add to .pre-commit-config.yaml (prek format):

  - id: validate-policy-yaml
    name: Validate NemoClaw policy YAML
    entry: node scripts/validate-policies.js
    language: node
    files: 'nemoclaw-blueprint/policies/.*\.yaml$'
    priority: 6
    additional_dependencies: ['js-yaml']

Step 3 — Add js-yaml as dev dependency:

npm install --save-dev js-yaml

Alternatives Considered

No response

Category

enhancement: feature

Checklist

  • I searched existing issues and this is not a duplicate
  • This is a design proposal, not a "please build this" request

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requeststatus: triageFor new items that haven't been reviewed yet.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions