automotive-cybersecurity

automotive-cybersecurity is a skill for Claude Code, Codex from pangzhenying2025/hermes-automotive-skills. It costs 43 tokens per session (37,629 once invoked), scanned A, original, MIT.

A collection of automotive cybersecurity guidance covering vehicle-network intrusion detection, ISO 21434 compliance, penetration testing, secure boot, and secure software development. Automotive cybersecurity protects vehicle computers, networks, and software from attacks.

In plain words
What is it for?
It is for tasks such as monitoring CAN-bus traffic, detecting anomalies, analyzing network behavior, testing vehicle security, and building secure ECU software.
Why use it?
It provides focused knowledge for recognizing attacks and designing security controls in vehicle systems.

Skill for Claude CodeCodex

Written for no agent in particular: nothing here depends on one. Also seen: positional $N argument.

Not installable: its command points at a path on the author’s own machine, so it runs nowhere else. The line is /home/user/ecu-firmware.

Good fit It is for tasks such as monitoring CAN-bus traffic, detecting anomalies, analyzing network behavior, testing vehicle security, and building secure ECU software.

Compare 6 skills from other repositories ↓
Install

Getting it into your agent

There is no command for this one: it runs only inside a plugin, and the catalogue could not identify which plugin ships it. The source is linked below.

Made for: Claude Code, Codex.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for automotive-cybersecurity

README.md
[![agentmods](https://agentmods.dev/badge/skills/pangzhenying2025/hermes-automotive-skills/automotive-cybersecurity/github.svg)](https://agentmods.dev/skills/pangzhenying2025/hermes-automotive-skills/automotive-cybersecurity)
Your own site
<a href="https://agentmods.dev/skills/pangzhenying2025/hermes-automotive-skills/automotive-cybersecurity"><img src="https://agentmods.dev/badge/skills/pangzhenying2025/hermes-automotive-skills/automotive-cybersecurity/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for automotive-cybersecurity

Your own site · 80×15
<a href="https://agentmods.dev/skills/pangzhenying2025/hermes-automotive-skills/automotive-cybersecurity"><img src="https://agentmods.dev/badge/skills/pangzhenying2025/hermes-automotive-skills/automotive-cybersecurity.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 43 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 37,629 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 2 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00043 $0.37629
Opus 5 $0.00022 $0.18815
Sonnet 5 $0.00009 $0.07526
Haiku 4.5 $0.00004 $0.03763

Measured 12d ago against content hash 4016704b160a, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-12, from the pricing page.

Security

Grade A, and why

automotive-cybersecurity scanned grade A with 2 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 12d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Asks for rootlowPrivilege escalation

A mod that escalates privileges can change anything on the machine, not only the project.

os.system('sudo modprobe vcan')

Downgraded: this mod is about security review, or the phrase is quoted, so it is likely naming the pattern rather than instructing it.

Runs shell commandslowCapability

Expected in a hook, worth knowing in a rule or an instructions file.

os.system('sudo modprobe vcan')
skills/automotive-cybersecurity/SKILL.md · 4,658 lines

How it starts

The opening of the file, as written. The whole thing — 4,658 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Automotive Cybersecurity

Intrusion Detection Prevention

Intrusion Detection & Prevention Skill

Overview

Expert skill for implementing IDS/IPS (Intrusion Detection/Prevention Systems) in automotive networks. Covers CAN bus anomaly detection, network traffic analysis, SIEM integration, honeypot deployment, and incident response playbooks.

Core Competencies

IDS/IPS Architecture

  • Network-based IDS (NIDS): Monitor CAN, FlexRay, Ethernet traffic
  • Host-based IDS (HIDS): Monitor ECU system calls, file integrity
  • Anomaly Detection: Machine learning for baseline behavior
  • Signature-based Detection: Known attack patterns
  • Prevention Mechanisms: Frame filtering, rate limiting, isolation

Detection Techniques

  • Statistical Analysis: Abnormal message rates, timing violations
  • Protocol Validation: Malformed frames, invalid DLC
  • Behavioral Analysis: Unexpected ECU communication patterns
  • Entropy Analysis: Randomness in payload data

CAN Bus Intrusion Detection System

CAN IDS Implementation

#!/usr/bin/env python3
"""
CAN Bus Intrusion Detection System
Real-time anomaly detection for automotive CAN networks
"""

import can
import time
import statistics
from collections import defaultdict, deque
from datetime import datetime, timedelta
import json

class CANIDSEngine:
    """Core CAN IDS detection engine"""

    def __init__(self, can_interface: str = 'can0', window_size: int = 100):
        self.interface = can_interface
        self.bus = can.interface.Bus(channel=can_interface, bustype='socketcan')

        # Message statistics per CAN ID
        self.msg_stats = defaultdict(lambda: {
            'count': 0,
            'last_timestamp': None,
            'intervals': deque(maxlen=window_size),
            'dlc_values': deque(maxlen=window_size),
            'payloads': deque(maxlen=window_size)
        })

        # Learned baseline (normal behavior)
        self.baseline = {}
        self.alerts = []

        print(f"=== CAN IDS Engine Initialized ===")
        print(f"[INFO] Interface: {can_interface}")
        print(f"[INFO] Window size: {window_size}")

    def learn_baseline(self, duration_seconds: int = 300):
        """Learn normal CAN traffic baseline (5 minutes)"""
        print(f"\n=== Learning Baseline (mode) ===")
        print(f"[INFO] Duration: {duration_seconds} seconds")
        print(f"[INFO] Capturing normal traffic...")

        start_time = time.time()
        message_count = 0

        while (time.time() - start_time) < duration_seconds:
            msg = self.bus.recv(timeout=1.0)
            if msg is None:
                continue

            self._update_statistics(msg)
            message_count += 1

            if message_count % 1000 == 0:
                elapsed = int(time.time() - start_time)
                print(f"[INFO] {message_count} messages captured ({elapsed}s)")

        # Compute baseline statistics
        self._compute_baseline()

        print(f"\n[PASS] Baseline learning complete")
        print(f"[INFO] Total messages: {message_count}")
        print(f"[INFO] Unique CAN IDs: {len(self.baseline)}")

    def _update_statistics(self, msg: can.Message):
        """Update statistics for received message"""
        stats = self.msg_stats[msg.arbitration_id]
        stats['count'] += 1

        # Calculate inter-arrival time
        if stats['last_timestamp'] is not None:
            interval = msg.timestamp - stats['last_timestamp']
            stats['intervals'].append(interval)

        stats['last_timestamp'] = msg.timestamp
        stats['dlc_values'].append(msg.dlc)
        stats['payloads'].append(bytes(msg.data))

    def _compute_baseline(self):
        """Compute baseline statistics from learned data"""
        print(f"\n[INFO] Computing baseline statistics...")

        for can_id, stats in self.msg_stats.items():
            if stats['count'] < 10:
                continue  # Insufficient data

            # Interval statistics
            intervals = list(stats['intervals'])
            interval_mean = statistics.mean(intervals) if intervals else 0
            interval_std = statistics.stdev(intervals) if len(intervals) > 1 else 0

            # Expected DLC
            dlc_mode = max(set(stats['dlc_values']), key=list(stats['dlc_values']).count)

            # Payload entropy (randomness)
            payloads = list(stats['payloads'])
            entropy_mean = statistics.mean([self._calculate_entropy(p) for p in payloads])

            self.baseline[can_id] = {
                'message_count': stats['count'],
                'interval_mean': interval_mean,
                'interval_std': interval_std,
                'interval_min': interval_mean - (3 * interval_std),  # 3-sigma
                'interval_max': interval_mean + (3 * interval_std),
                'expected_dlc': dlc_mode,
                'entropy_mean': entropy_mean,
                'payloads_sample': payloads[:10]  # Store samples for comparison
            }

            print(f"  CAN ID 0x{can_id:03X}: "
                  f"interval={interval_mean*1000:.2f}ms±{interval_std*1000:.2f}ms, "
                  f"DLC={dlc_mode}, "
                  f"entropy={entropy_mean:.2f}")

    def _calculate_entropy(self, data: bytes) -> float:
        """Calculate Shannon entropy of payload"""
        if len(data) == 0:
            return 0.0

        from collections import Counter
        import math

        counter = Counter(data)
        length = len(data)

        entropy = 0.0
        for count in counter.values():
            p = count / length
            entropy -= p * math.log2(p)

        return entropy

    def detect_anomalies(self, msg: can.Message) -> list:
        """Detect anomalies in received message"""
        anomalies = []
        can_id = msg.arbitration_id

        if can_id not in self.baseline:
            anomalies.append({
                'type': 'UNKNOWN_CAN_ID',
                'severity': 'HIGH',
                'description': f'New CAN ID 0x{can_id:03X} not seen during baseline',
                'timestamp': msg.timestamp
            })
            return anomalies

        baseline = self.baseline[can_id]
        stats = self.msg_stats[can_id]

        # Check 1: Inter-arrival time anomaly
        if stats['last_timestamp'] is not None:
            interval = msg.timestamp - stats['last_timestamp']

            if interval < baseline['interval_min']:
                anomalies.append({
                    'type': 'MESSAGE_FLOODING',
                    'severity': 'HIGH',
                    'description': f'CAN ID 0x{can_id:03X} flooding: '
                                 f'interval {interval*1000:.2f}ms < expected {baseline["interval_min"]*1000:.2f}ms',
                    'timestamp': msg.timestamp,
                    'can_id': can_id
                })

            elif interval > baseline['interval_max']:
                anomalies.append({
                    'type': 'MESSAGE_SUPPRESSION',
                    'severity': 'MEDIUM',
                    'description': f'CAN ID 0x{can_id:03X} delayed: '
                                 f'interval {interval*1000:.2f}ms > expected {baseline["interval_max"]*1000:.2f}ms',
                    'timestamp': msg.timestamp,
                    'can_id': can_id
                })

        # Check 2: DLC anomaly
        if msg.dlc != baseline['expected_dlc']:
            anomalies.append({
                'type': 'DLC_ANOMALY',
                'severity': 'MEDIUM',
                'description': f'CAN ID 0x{can_id:03X} unexpected DLC: '
                             f'{msg.dlc} != expected {baseline["expected_dlc"]}',
                'timestamp': msg.timestamp,
                'can_id': can_id
            })

        # Check 3: Payload entropy anomaly (possible injection/fuzzing)
        payload_entropy = self._calculate_entropy(bytes(msg.data))
        entropy_diff = abs(payload_entropy - baseline['entropy_mean'])

        if entropy_diff > 2.0:  # Significant entropy change
            anomalies.append({
                'type': 'PAYLOAD_ANOMALY',
                'severity': 'HIGH',
                'description': f'CAN ID 0x{can_id:03X} unusual payload entropy: '
                             f'{payload_entropy:.2f} (expected {baseline["entropy_mean"]:.2f})',
                'timestamp': msg.timestamp,
                'can_id': can_id,
                'payload': msg.data.hex()
            })

        # Update statistics
        self._update_statistics(msg)

        return anomalies

    def monitor(self, duration_seconds: int = None, prevention_mode: bool = False):
        """Monitor CAN bus for intrusions"""
        print(f"\n=== CAN IDS Monitoring ===")
        print(f"[INFO] Prevention mode: {prevention_mode}")

        start_time = time.time()
        message_count = 0
        anomaly_count = 0

        try:
            while True:
                if duration_seconds and (time.time() - start_time) > duration_seconds:
                    break

                msg = self.bus.recv(timeout=1.0)
                if msg is None:
                    continue

                message_count += 1

                # Detect anomalies
                anomalies = self.detect_anomalies(msg)

                if anomalies:
                    anomaly_count += len(anomalies)

                    for anomaly in anomalies:
                        self._handle_alert(anomaly, msg, prevention_mode)

                # Status update every 5000 messages
                if message_count % 5000 == 0:
                    elapsed = int(time.time() - start_time)
                    print(f"[INFO] {message_count} messages, {anomaly_count} anomalies ({elapsed}s)")

        except KeyboardInterrupt:
            print(f"\n[INFO] Monitoring stopped by user")

        print(f"\n=== Monitoring Summary ===")
        print(f"[INFO] Total messages: {message_count}")
        print(f"[INFO] Anomalies detected: {anomaly_count}")
        print(f"[INFO] Detection rate: {anomaly_count/message_count*100:.2f}%")

    def _handle_alert(self, anomaly: dict, msg: can.Message, prevention_mode: bool):
        """Handle detected anomaly"""
        timestamp = datetime.fromtimestamp(anomaly['timestamp']).strftime('%H:%M:%S.%f')[:-3]

        print(f"\n[ALERT] {anomaly['severity']} - {anomaly['type']} @ {timestamp}")
        print(f"  Description: {anomaly['description']}")
        print(f"  CAN ID: 0x{msg.arbitration_id:03X}, DLC: {msg.dlc}, Data: {msg.data.hex()}")

        # Log alert
        self.alerts.append(anomaly)

        # Prevention actions
        if prevention_mode:
            if anomaly['type'] == 'MESSAGE_FLOODING':
                print(f"  [BLOCK] Rate limiting CAN ID 0x{msg.arbitration_id:03X}")
                # In real system: configure CAN controller filters

            elif anomaly['type'] == 'UNKNOWN_CAN_ID':
                print(f"  [BLOCK] Dropping frames from unknown CAN ID 0x{msg.arbitration_id:03X}")

            elif anomaly['type'] == 'PAYLOAD_ANOMALY':
                print(f"  [ISOLATE] Potential fuzzing/injection detected - isolating ECU")

    def export_alerts(self, output_file: str):
        """Export alerts to JSON"""
        with open(output_file, 'w') as f:
            json.dump(self.alerts, f, indent=2)

        print(f"[INFO] Alerts exported: {output_file}")


# Example: Simulate CAN attacks and detect them
def demo_can_ids():
    import os

    # Setup virtual CAN interface
    os.system('sudo modprobe vcan')
    os.system('sudo ip link add dev vcan0 type vcan')
    os.system('sudo ip link set up vcan0')

    print("=== CAN IDS Demo ===")
    print("[INFO] Using virtual CAN interface vcan0")

    # Create IDS
    ids = CANIDSEngine(can_interface='vcan0', window_size=50)

    # Simulate normal traffic generator (in separate process)
    print("\n[INFO] Start normal CAN traffic generator in another terminal:")
    print("  python3 can_traffic_generator.py --interface vcan0 --scenario normal")

    input("\nPress Enter when normal traffic is running...")

    # Learn baseline
    ids.learn_baseline(duration_seconds=60)

    # Monitor for attacks
    print("\n[INFO] Now inject attacks using:")
    print("  python3 can_attack_simulator.py --interface vcan0 --attack flooding")

    input("\nPress Enter to start monitoring...")

    ids.monitor(duration_seconds=120, prevention_mode=True)

    # Export results
    ids.export_alerts('/tmp/can_ids_alerts.json')

if __name__ == "__main__":
    demo_can_ids()

Read the full file on GitHub · 4,658 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 12d ago First seen · 4,658 lines · 43 tokens per session scan A 4016704b160a

Subscribe to this mod's changes

automotive-cybersecurity is a skill published in the GitHub repository pangzhenying2025/hermes-automotive-skills (5 stars, last pushed 3mo ago), licensed MIT. It adds 43 tokens to every session and 37,629 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 2 findings (asks for root, runs shell commands). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.

Related

Other skills, from other repositories

iso26262

ISO 26262 functional-safety expert that operates in two modes: (1) HARA / ASIL determination — enumerate hazardous events from item malfunctions × driving situations, rate Severity (S0–S3), Exposure (E0–E4), Controllability (C0–C3), look up ASIL from ISO 26262-3:2018 Table 4, and produce a HARA report with Safety…

ptsilivis/autonomousguy · 197 tokens

automotive-syseng

When the user wants to analyze automotive requirements, check INCOSE/EARS compliance, review MISRA-C code, assess ADAS levels, or verify ISO 26262/AUTOSAR/SOTIF conformance. Also use when the user says 'check requirements', 'EARS check', 'INCOSE analysis', 'MISRA check', 'ASIL assessment', 'V-model check'…

duonghvu/automotive-syseng · 122 tokens

automotive-expert

Expert-level automotive systems, connected vehicles, fleet management, telematics, ADAS, and automotive software. Use when the user mentions connected car, fleet, telematics, ADAS, or vehicle, or when the task involves Automotive Systems, Technologies, Standards and Protocols, or Fleet Management.

personamanagmentlayer/pcl · 64 tokens

misra

MISRA C:2025 expert that operates in two modes: (1) Review — scan existing C code for violations across all 223 guidelines (22 directives + 201 rules), report findings with rule IDs, corrected code, and deviation justification templates; (2) Develop — generate new C functions, modules, or data structures that are…

ptsilivis/autonomousguy · 221 tokens

requirements

Requirements-engineering expert that operates in three modes: (1) Elicitation — extract atomic, testable requirements from briefs, meeting notes, or system specs using EARS notation, with full attribute set (ID, type, priority, ASIL, verification method, source), flagging ambiguities as open questions; (2) Refinement…

ptsilivis/autonomousguy · 221 tokens

auto-dev

Use when working with Auto.dev APIs, vehicle data, VIN decoding, car listings, vehicle photos, specs, recalls, payments, interest rates, taxes, OEM build data, plate-to-VIN, CLI commands, MCP tools, or SDK methods for any automotive data task.

drivly/auto-dev-skill · 57 tokens