network-config-validation

Pre-deployment checks for router and switch configuration, including dangerous commands, duplicate addresses, subnet overlaps, stale references,…

INSTALLATION
npx skills add https://github.com/affaan-m/everything-claude-code --skill network-config-validation
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

Network Config Validation

Use this skill to review network configuration before a change window or before

an automation run touches production devices.

When to Use

  • Reviewing Cisco IOS or IOS-XE style snippets before deployment.
  • Auditing generated config from scripts or templates.
  • Looking for dangerous commands, duplicate IP addresses, or subnet overlaps.
  • Checking whether ACLs, route-maps, prefix-lists, or line policies are referenced

but not defined.

  • Building lightweight pre-flight scripts for network automation.

How It Works

Treat config validation as layered evidence, not as a complete parser. Regex

checks are useful for pre-flight warnings, but final approval still needs a

network engineer to review intent, platform syntax, and rollback steps.

Validate in this order:

  • Destructive commands.
  • Credential and management-plane exposure.
  • Duplicate addresses and overlapping subnets.
  • Stale references to ACLs, route-maps, prefix-lists, and interfaces.
  • Operational hygiene such as NTP, timestamps, remote logging, and banners.

Dangerous Command Detection

import re

DANGEROUS_PATTERNS: list[tuple[re.Pattern[str], str]] = [

    (re.compile(r"\breload\b", re.I), "reload causes downtime"),

    (re.compile(r"\berase\s+(startup|nvram|flash)", re.I), "erases persistent storage"),

    (re.compile(r"\bformat\b", re.I), "formats a device filesystem"),

    (re.compile(r"\bno\s+router\s+(bgp|ospf|eigrp)\b", re.I), "removes a routing process"),

    (re.compile(r"\bno\s+interface\s+\S+", re.I), "removes interface configuration"),

    (re.compile(r"\baaa\s+new-model\b", re.I), "changes authentication behavior"),

    (re.compile(r"\bcrypto\s+key\s+(zeroize|generate)\b", re.I), "changes device SSH keys"),

]

def find_dangerous_commands(lines: list[str]) -> list[dict[str, str | int]]:

    findings = []

    for line_number, line in enumerate(lines, start=1):

        stripped = line.strip()

        for pattern, reason in DANGEROUS_PATTERNS:

            if pattern.search(stripped):

                findings.append({

                    "line": line_number,

                    "command": stripped,

                    "reason": reason,

                })

    return findings

Duplicate IPs And Subnet Overlaps

import ipaddress

import re

from collections import Counter

IP_ADDRESS_RE = re.compile(

    r"^\s*ip address\s+"

    r"(?P<ip>\d{1,3}(?:\.\d{1,3}){3})\s+"

    r"(?P<mask>\d{1,3}(?:\.\d{1,3}){3})\b",

    re.I | re.M,

)

def extract_interfaces(config: str) -> list[dict[str, str]]:

    results = []

    current = None

    for line in config.splitlines():

        if line.startswith("interface "):

            current = line.split(maxsplit=1)[1]

            continue

        match = IP_ADDRESS_RE.match(line)

        if current and match:

            ip = match.group("ip")

            mask = match.group("mask")

            network = ipaddress.ip_interface(f"{ip}/{mask}").network

            results.append({"interface": current, "ip": ip, "network": str(network)})

    return results

def find_duplicate_ips(config: str) -> list[str]:

    ips = [entry["ip"] for entry in extract_interfaces(config)]

    counts = Counter(ips)

    return sorted(ip for ip, count in counts.items() if count > 1)

def find_subnet_overlaps(config: str) -> list[tuple[str, str]]:

    networks = [ipaddress.ip_network(entry["network"]) for entry in extract_interfaces(config)]

    overlaps = []

    for index, left in enumerate(networks):

        for right in networks[index + 1:]:

            if left.overlaps(right):

                overlaps.append((str(left), str(right)))

    return overlaps

Management-Plane Checks

Parse VTY blocks by section so access-class checks do not spill across unrelated

lines.

import re

def iter_blocks(config: str, starts_with: str) -> list[str]:

    blocks = []

    current: list[str] = []

    for line in config.splitlines():

        if line.startswith(starts_with):

            if current:

                blocks.append("\n".join(current))

            current = [line]

            continue

        if current:

            if line and not line.startswith(" "):

                blocks.append("\n".join(current))

                current = []

            else:

                current.append(line)

    if current:

        blocks.append("\n".join(current))

    return blocks

def check_vty_blocks(config: str) -> list[str]:

    issues = []

    for block in iter_blocks(config, "line vty"):

        if re.search(r"transport\s+input\s+.*telnet", block, re.I):

            issues.append("VTY allows Telnet; require SSH only.")

        if not re.search(r"\baccess-class\s+\S+\s+in\b", block, re.I):

            issues.append("VTY block has no inbound access-class source restriction.")

        if not re.search(r"\bexec-timeout\s+\d+\s+\d+\b", block, re.I):

            issues.append("VTY block has no explicit exec-timeout.")

    return issues

Security Hygiene Checks

SECURITY_PATTERNS = [

    (re.compile(r"\bsnmp-server community\s+(public|private)\b", re.I),

     "default SNMP community configured"),

    (re.compile(r"\bsnmp-server community\s+\S+", re.I),

     "SNMPv2 community string configured; prefer SNMPv3 authPriv"),

    (re.compile(r"\bip ssh version 1\b", re.I),

     "SSH version 1 enabled"),

    (re.compile(r"\benable password\b", re.I),

     "enable password is present; use enable secret"),

    (re.compile(r"\busername\s+\S+\s+password\b", re.I),

     "local username uses password instead of secret"),

]

BEST_PRACTICE_PATTERNS = [

    (re.compile(r"\bntp server\b", re.I), "NTP server"),

    (re.compile(r"\bservice timestamps\b", re.I), "log timestamps"),

    (re.compile(r"\blogging\s+\S+", re.I), "logging destination or buffer"),

    (re.compile(r"\bsnmp-server group\s+\S+\s+v3\s+priv\b", re.I), "SNMPv3 authPriv group"),

    (re.compile(r"\bbanner\s+(login|motd)\b", re.I), "login banner"),

]

def check_security(config: str) -> list[str]:

    return [message for pattern, message in SECURITY_PATTERNS if pattern.search(config)]

def check_missing_hygiene(config: str) -> list[str]:

    return [

        f"Missing {description}"

        for pattern, description in BEST_PRACTICE_PATTERNS

        if not pattern.search(config)

    ]

Examples

Change-Window Preflight

  • Run dangerous-command checks on the exact snippet to be pasted.
  • Run duplicate IP and subnet overlap checks against the full candidate config.
  • Confirm every referenced ACL, route-map, and prefix-list exists.
  • Confirm rollback commands and out-of-band access before any management-plane

change.

Automation Preflight

Use validation as a blocking gate before Netmiko, NAPALM, Ansible, or vendor API

automation pushes a generated config. Fail closed on dangerous commands and

credentials. Warn on best-practice gaps that are outside the change scope.

Anti-Patterns

  • Treating regex validation as a device parser.
  • Applying generated config without a dry-run diff.
  • Recommending SNMPv2 community strings as a monitoring requirement.
  • Checking VTY blocks with regex that can accidentally span unrelated sections.
  • Testing firewall behavior by disabling ACLs instead of reading counters/logs.

See Also

  • Agent: network-config-reviewer
  • Agent: network-troubleshooter
  • Skill: network-interface-health
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card