Every ECU in a modern vehicle accepts input from external interfaces — CAN messages, UDS diagnostic requests, DoIP packets, SOME/IP service calls, Ethernet frames. Each of these inputs is parsed by firmware code that was written under schedule pressure, compiled with assumptions about message structure, and tested primarily against valid, expected data. Fuzz testing exists to challenge those assumptions systematically. By feeding malformed, unexpected, and boundary-violating inputs to automotive interfaces, fuzzing discovers vulnerabilities that structured test cases and code reviews routinely miss.

The stakes in automotive are uniquely high. A buffer overflow in a web application might leak user data. A buffer overflow in a brake ECU firmware parser could cause unintended vehicle behavior at highway speed. This guide provides a comprehensive technical treatment of fuzz testing applied to automotive systems: the fundamentals of fuzzing methodology, protocol-specific techniques for every major automotive interface, lab setup and infrastructure considerations, crash triage and root cause analysis, CI/CD integration for continuous fuzzing, and alignment with ISO/SAE 21434 verification and validation requirements.

Fuzz testing workflow pipeline with feedback loop Fuzz Testing Workflow Test Inputs Random / mutated data Fuzzer Engine Generation / mutation Target ECU CAN / UDS / Ethernet Monitor Crash / hang detection ! Crash Report Vulnerability found Coverage feedback: new paths guide next inputs
Fuzz testing pipeline: random or mutated inputs are fed through the fuzzer engine into the target ECU, monitored for crashes, with coverage feedback guiding the next generation of test inputs.

Why Fuzzing Is Critical for Automotive Security

Traditional automotive software testing focuses on validating that systems behave correctly when given correct inputs. Test engineers write structured test cases based on requirements: send a valid UDS diagnostic request, verify the ECU responds with the expected positive response. Send a valid CAN message with a known arbitration ID, verify the receiving ECU processes the payload correctly. This approach validates functional correctness but entirely ignores the question: what happens when the input is wrong?

Attackers do not send valid inputs. They send deliberately malformed messages designed to trigger parsing errors, memory corruption, state machine violations, and resource exhaustion. The gap between what testers validate and what attackers exploit is precisely where fuzzing operates. Fuzzing is the automated generation and injection of invalid, unexpected, or random data into program inputs, with the goal of triggering observable failures — crashes, hangs, memory violations, assertion failures, or unexpected state transitions.

The automotive industry has several characteristics that make fuzzing especially important:

  • Long product lifecycles: Vehicles remain on the road for 15–20 years. Vulnerabilities discovered after production require expensive OTA updates or recalls. Finding them before production through fuzzing is orders of magnitude cheaper.
  • Safety-critical systems: Unlike IT systems where the worst case is data loss, automotive vulnerabilities can have physical safety consequences. Fuzzing helps ensure that malformed inputs cause graceful failure modes rather than undefined behavior.
  • Supply chain complexity: OEMs integrate ECU software from dozens of Tier-1 and Tier-2 suppliers. Each supplier’s code has its own parsing assumptions and edge cases. Fuzzing at integration boundaries catches incompatibilities that component-level testing misses.
  • Regulatory requirements: ISO/SAE 21434 explicitly requires security verification and validation activities. UNECE R155 mandates that vehicle manufacturers demonstrate they have addressed known attack techniques. Fuzzing is a recognized verification method that satisfies both requirements.
  • Expanding attack surface: Modern vehicles expose more external interfaces than ever: Bluetooth, Wi-Fi, cellular, V2X, USB, OBD-II, Ethernet. Each interface multiplies the volume of input parsing code that must be validated against adversarial inputs.

Types of Fuzzing

Not all fuzzing is the same. The three major approaches differ in how they generate test inputs, what knowledge they require about the target, and the types of vulnerabilities they are best suited to find:

Generation-Based Fuzzing (Smart Fuzzing)

Generation-based fuzzing uses a formal specification or grammar of the target protocol to generate inputs that are structurally aware but contain deliberate violations. For example, a UDS generation-based fuzzer understands the structure of a UDS request — service ID, sub-function, data length, payload — and generates test cases that violate specific fields while keeping others valid. It might send a DiagnosticSessionControl request with a valid service ID (0x10) but an invalid sub-function value (0xFF), or a ReadDataByIdentifier request with a data length field that claims 4096 bytes but only includes 2 bytes of actual data.

The advantage of generation-based fuzzing is protocol awareness. Because the fuzzer understands message structure, it can systematically exercise every field, every boundary condition, and every state transition in the protocol. It can generate inputs that pass initial parsing stages and reach deeper code paths that random data would never trigger. The disadvantage is that building a generator requires detailed knowledge of the protocol specification, which is time-intensive and must be updated as protocols evolve.

Mutation-Based Fuzzing (Dumb Fuzzing)

Mutation-based fuzzing starts with a corpus of valid inputs — captured CAN traffic, recorded UDS sessions, legitimate SOME/IP method calls — and applies random mutations: bit flips, byte insertions, byte deletions, integer boundary substitutions, and block shuffling. The fuzzer does not need to understand the protocol structure; it simply perturbs known-good inputs and observes what happens.

Mutation-based fuzzing is fast to set up because it requires no protocol grammar, only a seed corpus of valid traffic. It excels at finding shallow parsing bugs — vulnerabilities in the first few bytes of input processing where even random perturbations can trigger failures. Its weakness is that random mutations rarely produce inputs that pass structural validation checks, so deeper code paths remain unexplored. A CAN message with a randomly corrupted arbitration ID will likely be dropped by the hardware filter before it ever reaches the application layer.

Coverage-Guided Fuzzing

Coverage-guided fuzzing is the modern synthesis of generation and mutation approaches. Pioneered by tools like AFL (American Fuzzy Lop) and now widely implemented in libFuzzer, Honggfuzz, and automotive-specific tools, coverage-guided fuzzers instrument the target binary to collect code coverage feedback. When a mutated input triggers a new code path — a branch not previously taken, a function not previously called — that input is saved to the corpus and used as a seed for further mutations. Over time, the corpus evolves to maximize code coverage, systematically exploring deeper and deeper into the target’s logic.

Coverage-guided fuzzing is particularly powerful for automotive ECU firmware because it can discover complex, multi-step vulnerabilities that require specific sequences of field values to trigger. For example, it might discover that a particular combination of UDS service ID, sub-function, and data length triggers a buffer overflow in a handler that is only reached when all three fields satisfy specific constraints. Neither pure generation nor pure mutation would find this efficiently, but coverage feedback guides the fuzzer toward it incrementally.

In practice, the most effective automotive fuzzing campaigns combine all three approaches: generation-based fuzzing for protocol-aware systematic exploration, mutation-based fuzzing for rapid surface-level coverage, and coverage-guided fuzzing for deep exploration of binary code paths. The choice depends on the target interface, the availability of protocol specifications, and whether source code or instrumentation access is available.

Fuzzing Approach Comparison

Aspect Generation-Based Mutation-Based Coverage-Guided
Setup & Requirements
Protocol knowledge required Full specification needed None (seed corpus only) Minimal (seed corpus + instrumentation)
Setup time High (grammar development) Low (capture traffic, start) Medium (instrumentation setup)
Source code access Not required Not required Preferred (for instrumentation)
Effectiveness
Shallow bug detection Good Excellent Excellent
Deep bug detection Good (protocol-aware paths) Poor (random exploration) Excellent (feedback-driven)
State machine coverage Excellent (sequence-aware) Poor (no state awareness) Good (emergent via coverage)
Code coverage potential Medium (specification-bounded) Low (random walk) High (coverage-maximizing)
Practical Considerations
Throughput (tests/sec) Medium (generation overhead) High (simple mutations) Medium (instrumentation overhead)
False positive rate Low (structured inputs) Higher (noise from invalid format) Low (confirmed new coverage)
Best suited for Protocol conformance, state machines Quick surface scan, unknown protocols Deep firmware analysis, binary targets
Automotive example tools Peach, Defensics, custom grammars Radamsa, zzuf, custom mutators AFL, libFuzzer, Honggfuzz, CANalyze

Protocol-Specific Fuzzing Techniques

Each automotive communication protocol has unique characteristics that demand tailored fuzzing strategies. A CAN bus fuzzer operates at a fundamentally different level than an Ethernet SOME/IP fuzzer, and the vulnerabilities they find are correspondingly different.

CAN / CAN FD Fuzzing

CAN bus fuzzing targets the most ubiquitous in-vehicle network. CAN frames are small (8 bytes for Classic CAN, up to 64 bytes for CAN FD), and the protocol has no built-in authentication or encryption. Every ECU on a CAN segment receives every message, and acceptance is determined solely by the arbitration ID filter configured in the receiving controller.

Effective CAN fuzzing involves several dimensions. Arbitration ID fuzzing iterates through the 11-bit (standard) or 29-bit (extended) ID space to discover which IDs each ECU accepts and processes. Many ECUs respond to undocumented arbitration IDs that were used during development or diagnostics and were never disabled in production firmware. Payload fuzzing for known arbitration IDs systematically varies each byte of the 8-byte (or 64-byte CAN FD) data field, testing boundary values (0x00, 0x7F, 0x80, 0xFF), bit patterns, and length variations. Timing fuzzing varies message frequency — sending messages at 10x the expected rate to test buffer overflow conditions, or sending messages with irregular inter-frame gaps to test timing assumption violations. DLC fuzzing sends frames with mismatched Data Length Code values, claiming a length that differs from the actual payload size, which can trigger memory read overflows in ECUs that trust the DLC field without bounds checking.

CAN fuzzing requires hardware: a CAN interface adapter (such as a PEAK PCAN-USB, Kvaser Leaf, or Vector CANcase) connected to the target bus segment. For safety, CAN fuzzing should never be performed on a complete vehicle with active actuators. Instead, the target ECU should be isolated on a bench with only the specific CAN segment under test connected.

UDS (Unified Diagnostic Services) Fuzzing

UDS (ISO 14229) is the standard diagnostic protocol used by virtually every modern vehicle. UDS runs over CAN (ISO 15765-2 transport layer), DoIP (ISO 13400), or other transports. Because UDS provides powerful capabilities — reading and writing memory, flashing firmware, unlocking security access, resetting ECUs — it is a high-value target for attackers and a critical focus for fuzzing.

UDS fuzzing should cover several layers. Service ID fuzzing sends requests with every possible service ID (0x00–0xFF), including undefined and manufacturer-specific ranges (0x80–0xFE), to discover hidden or debug services that should have been disabled. Sub-function fuzzing for each discovered service iterates through all 128 sub-function values with both suppressPositiveResponse bit states. Security access fuzzing targets the SecurityAccess service (0x27) with brute-force seed-key attempts, timing attacks, and session manipulation to bypass authentication. Data parameter fuzzing for services like WriteDataByIdentifier (0x2E) and RoutineControl (0x31) sends oversized payloads, truncated payloads, and boundary-value parameters. Session and sequence fuzzing tests state machine violations: attempting privileged operations from the default session, sending sequences out of order, and interleaving requests from multiple concurrent sessions.

A sophisticated UDS fuzzer maintains a state model of the diagnostic session and explores transitions systematically, rather than sending random individual requests. This is essential because many UDS vulnerabilities are only reachable in specific session states — for example, a buffer overflow in a RoutineControl handler that is only accessible after a successful SecurityAccess unlock in the extended diagnostic session.

DoIP (Diagnostics over IP) Fuzzing

DoIP (ISO 13400) tunnels UDS diagnostic communication over TCP/IP, typically via the vehicle’s Ethernet backbone. DoIP introduces network-layer attack surface that does not exist in CAN-based diagnostics: TCP connection management, DoIP header parsing, vehicle identification and routing, and TLS configuration when encryption is used.

DoIP fuzzing targets the DoIP header fields independently from the wrapped UDS payload. The DoIP header contains a protocol version, inverse protocol version, payload type, and payload length. Fuzzing should test mismatched version and inverse version fields, invalid payload type codes, length fields that exceed the TCP segment or that claim zero length for payload types that require data, and fragmented TCP delivery of single DoIP messages. Additionally, the vehicle identification request/response exchange that occurs before diagnostic communication is established should be fuzzed, as vulnerabilities in the identification parser can be exploited before any authentication occurs.

SOME/IP Fuzzing

SOME/IP (Scalable service-Oriented MiddlewarE over IP) is the service-oriented communication middleware for automotive Ethernet, defined by AUTOSAR. SOME/IP carries method calls, event notifications, and field accessors between ECUs over UDP or TCP. The protocol has a rich message structure including message ID, length, request ID, protocol version, interface version, message type, and return code, followed by serialized payload data.

SOME/IP fuzzing must account for the service discovery layer (SOME/IP-SD) and the service communication layer separately. SOME/IP-SD fuzzing targets the service discovery mechanism: sending malformed OfferService, FindService, and SubscribeEventgroup entries with invalid TTL values, corrupted endpoint options, and conflicting service instance IDs. A vulnerable SD implementation might crash when parsing a malformed option or allocate excessive memory when processing a subscription with an enormous TTL. SOME/IP method fuzzing targets specific service methods with malformed serialized payloads. Because SOME/IP serialization follows the AUTOSAR SOME/IP Transformer specification, a generation-based fuzzer can produce payloads with incorrect field lengths, type mismatches, nested structure depth violations, and string encoding errors. SOME/IP-TP (Transport Protocol) fuzzing targets the segmentation and reassembly of large SOME/IP messages, testing out-of-order segments, overlapping offsets, and excessive segment counts.

Automotive Ethernet Fuzzing

Beyond SOME/IP, automotive Ethernet carries multiple protocol stacks that each require fuzzing: AVB/TSN (time-sensitive networking) for audio/video streaming and control data, TCP/IP for general communication, TLS for encrypted channels, HTTP/REST for API endpoints on infotainment systems, and custom protocols specific to individual OEMs.

Automotive Ethernet fuzzing at the network layer should test VLAN tagging manipulation (IEEE 802.1Q), ARP spoofing and cache poisoning on in-vehicle Ethernet segments, DHCP server fuzzing for ECUs that dynamically acquire addresses, and IPv6 neighbor discovery fuzzing for IPv6-enabled architectures. At the transport layer, TCP state machine fuzzing (SYN floods, RST injection, window size manipulation) and UDP amplification testing are relevant. At the application layer, any ECU exposing an HTTP API, REST endpoint, or WebSocket interface should be fuzzed with standard web application fuzzing techniques adapted for the embedded context.

Fuzzing ECU Firmware

Protocol fuzzing tests the external interfaces of an ECU. Firmware fuzzing goes deeper, testing internal code paths by instrumenting the firmware binary itself. This is particularly valuable for finding vulnerabilities in message parsing routines, cryptographic implementations, and state management logic that are not directly reachable through protocol-level fuzzing alone.

Source-Level Fuzzing

When source code is available (either because the ECU software is developed in-house or because the supplier provides source access), coverage-guided fuzzing can be applied directly. The approach is to extract individual parsing functions from the firmware codebase, compile them into standalone harness binaries instrumented with AFL or libFuzzer, and fuzz them on a standard Linux workstation at millions of executions per second. This approach, sometimes called harness-based fuzzing, is dramatically faster than fuzzing through the physical interface because it eliminates hardware communication latency and ECU reset times.

Building effective fuzzing harnesses requires identifying the right targets: functions that accept external input, perform parsing or deserialization, handle memory allocation based on input-controlled sizes, or implement cryptographic operations. Each harness should set up the minimum required state (global variables, configuration structures) for the target function and call it with fuzzer-generated input. The harness must also include appropriate sanitizers — AddressSanitizer (ASan) for memory errors, UndefinedBehaviorSanitizer (UBSan) for language-level undefined behavior, and MemorySanitizer (MSan) for use of uninitialized memory.

Binary-Level Fuzzing

When source code is not available — a common situation with third-party supplier ECUs — binary-level fuzzing techniques apply. Tools like AFL in QEMU mode can instrument ARM and other embedded architecture binaries without source code, providing coverage-guided fuzzing at the binary level. Unicorn Engine allows extracting individual firmware functions and fuzzing them in an emulated context. For more complete emulation, frameworks like QEMU full-system emulation or Renode can boot entire firmware images and fuzz them through emulated peripheral interfaces.

Binary-level fuzzing is slower than source-level fuzzing due to emulation overhead, and crash triage is more difficult without debug symbols. However, it is often the only option for validating third-party ECU firmware, and it is essential for OEMs who must verify the security of supplier-provided components as part of their ISO/SAE 21434 cybersecurity assurance obligations.

Setting Up a Fuzz Testing Lab

Effective automotive fuzzing requires a purpose-built test environment. The lab setup must balance realism (testing against real hardware with real firmware) against scalability (running enough parallel fuzzing sessions to achieve meaningful coverage).

Hardware-in-the-Loop (HIL) Fuzzing

HIL fuzzing connects real ECU hardware to a fuzzing host via physical communication interfaces. The ECU runs production firmware on production hardware, and the fuzzer sends malformed inputs through real CAN transceivers, Ethernet PHYs, or diagnostic connectors. This provides the highest-fidelity results because every hardware-specific behavior — interrupt timing, DMA behavior, peripheral register interactions, watchdog behavior — is captured exactly as it occurs in the vehicle.

A HIL fuzzing bench typically includes the target ECU with its wiring harness and power supply, communication interface adapters connected to a Linux fuzzing host, power cycling equipment (relay boards or programmable power supplies) for automated ECU reset after crashes, and serial or JTAG debug connections for monitoring ECU state and capturing crash dumps. The primary limitation of HIL fuzzing is throughput: physical ECU communication is bounded by bus speeds (500 kbps for CAN, 100 Mbps for Ethernet) and ECU processing latency, yielding hundreds to low thousands of test cases per second rather than the millions achievable in software emulation.

Simulation-Based Fuzzing

Simulation-based fuzzing replaces physical ECU hardware with software emulation, enabling massive parallelism. The target firmware is executed in an emulator (QEMU, Renode, or a vendor-specific simulation environment), and fuzzing inputs are injected through emulated peripheral interfaces. A single server can run dozens of parallel fuzzing instances, each with its own emulated ECU, achieving aggregate throughput orders of magnitude higher than HIL fuzzing.

The tradeoff is fidelity. Emulators may not perfectly reproduce hardware-specific behavior, particularly around peripheral timing, interrupt priority, and DMA interactions. Vulnerabilities that depend on exact hardware timing may not manifest in emulation. The recommended approach is to use simulation-based fuzzing for broad coverage exploration (finding the majority of bugs quickly and cheaply) and then validate findings against real hardware in a HIL setup. Bugs found in simulation should always be confirmed on physical hardware before being reported as verified vulnerabilities.

Hybrid Approach

The most effective labs combine both approaches. Coverage-guided fuzzing runs continuously in simulation against instrumented firmware images, achieving high code coverage over days and weeks of execution. In parallel, generation-based protocol fuzzers run against physical ECU hardware in HIL benches, testing hardware-specific behavior and timing-dependent code paths. Findings from both pipelines feed into a shared triage database where they are deduplicated, severity-rated, and assigned for root cause analysis.

Measuring Coverage and Effectiveness

Fuzzing without coverage measurement is shooting in the dark. Code coverage metrics tell you what percentage of the target code has been exercised by fuzzing inputs, guiding decisions about when to stop, where to add new seed inputs, and which code regions need alternative testing approaches.

The primary coverage metrics for automotive fuzzing are:

  • Line coverage: The percentage of source code lines executed during fuzzing. A useful starting metric but can be misleading because a single execution through a function counts as coverage even if only one of many possible paths was taken.
  • Branch coverage: The percentage of conditional branches (if/else, switch cases, loop conditions) taken in both directions. More meaningful than line coverage because it captures decision logic exploration. A fuzzing campaign should target at least 80% branch coverage of input-handling code.
  • Function coverage: The percentage of functions called during fuzzing. Low function coverage often indicates that the fuzzer cannot reach certain code regions due to state requirements, authentication gates, or environmental dependencies that need to be mocked in the harness.
  • Edge coverage: The number of unique control-flow edges (transitions between basic blocks) discovered. This is the metric that coverage-guided fuzzers like AFL optimize for, and it provides the finest-grained view of exploration progress.

Beyond code coverage, track unique crashes (deduplicated by crash signature), unique hangs (inputs that cause the target to exceed a timeout threshold), corpus size growth rate (new coverage discoveries per unit time — a flattening curve indicates diminishing returns), and execution speed (test cases per second, which affects how quickly coverage can be achieved).

Triaging Crashes

A fuzzing campaign against an automotive ECU can produce hundreds or thousands of crash-inducing inputs. Triaging these crashes — determining which represent unique vulnerabilities, assessing their severity, and identifying root causes — is where fuzzing translates from automated exploration into actionable security findings.

Crash Deduplication

The first step is deduplication: grouping crashes that trigger the same underlying bug. Crashes are typically deduplicated by their stack trace hash — a hash of the function call chain at the point of failure. Two inputs that crash with the same stack trace almost certainly trigger the same bug. More sophisticated deduplication uses coverage-based clustering, grouping crashes that exercise the same set of code edges even if their stack traces differ slightly due to memory layout variations.

Severity Assessment

Each unique crash must be assessed for security impact. The key questions are: Is this a memory safety violation (buffer overflow, use-after-free, null dereference)? Is it exploitable for code execution or information disclosure? Is the affected interface externally accessible (can an attacker reach this code path)? What is the safety impact if this vulnerability is exploited in a production vehicle? Memory corruption vulnerabilities in network-facing parsers (DoIP, SOME/IP, Bluetooth) are typically rated critical because they combine remote reachability with potential for arbitrary code execution. Null pointer dereferences in CAN message handlers may cause ECU resets but are typically not exploitable for code execution.

Root Cause Analysis

For each unique vulnerability, root cause analysis determines the exact code defect: an unchecked array index, a missing length validation, an integer overflow in a size calculation, a type confusion in a union, or a race condition in interrupt handling. Root cause analysis requires reproducing the crash with debug instrumentation (ASan, valgrind, or JTAG debugging) to obtain precise information about the corrupted memory region, the original allocation, and the sequence of operations that led to the violation. The root cause informs not only the immediate fix but also a broader code audit for similar patterns elsewhere in the codebase.

Integrating Fuzzing into CI/CD

Fuzzing is most valuable when it runs continuously and is integrated into the development workflow, not when it is performed as a one-time activity before release. Continuous fuzzing catches regressions immediately when new code is committed, before they propagate to release candidates.

Continuous Fuzzing Pipeline

A mature continuous fuzzing pipeline operates as follows. Every commit to the firmware repository triggers a build that produces instrumented binaries (compiled with coverage instrumentation and sanitizers). These binaries are deployed to a fuzzing cluster — either physical HIL benches for hardware-in-the-loop targets or virtual machines for simulation-based targets. The fuzzing cluster runs multiple parallel fuzzing instances against the new build, seeded with the corpus from the previous build. Any new crashes are automatically triaged, deduplicated against the known bug database, and reported as build-breaking issues with the specific commit that introduced the regression identified through git bisection.

Corpus Management

The fuzzing corpus — the set of inputs that collectively achieve the current maximum code coverage — is a valuable artifact that must be managed across builds. When the firmware is updated, the existing corpus is replayed against the new build to verify that coverage is maintained and to identify any inputs that now trigger new crashes (indicating a regression). The corpus is minimized periodically using tools like afl-cmin to remove redundant inputs, keeping only the minimum set that achieves maximum coverage. Corpus files should be stored in version control alongside the firmware source, enabling reproducibility and historical analysis.

Integration with Test Suites

Crash-inducing inputs discovered by fuzzing should be converted into regression test cases and added to the standard test suite. Each regression test reproduces the exact input that triggered the crash, verifies that the fix resolves the issue, and prevents future regressions. Over time, the regression test suite becomes a valuable catalog of real-world edge cases that supplements the requirements-based test cases written by test engineers.

Alignment with ISO/SAE 21434 Verification Requirements

ISO/SAE 21434 (Road vehicles — Cybersecurity engineering) requires cybersecurity verification and validation as part of the product development process. Clause 10 specifies that verification methods shall demonstrate that cybersecurity requirements are implemented correctly and that the work product is free from vulnerabilities. Fuzzing directly addresses several ISO/SAE 21434 verification objectives:

  • Verification of cybersecurity specifications (Clause 10.4.1): Fuzzing verifies that input parsing implementations correctly enforce the constraints specified in interface definitions. When fuzzing discovers that an out-of-range value crashes an ECU, it demonstrates a failure to implement the cybersecurity specification that should have required input validation.
  • Vulnerability analysis (Clause 8.5): Fuzzing is a systematic technique for discovering unknown vulnerabilities, complementing static analysis and manual code review. ISO/SAE 21434 requires that vulnerability analysis be performed, and fuzzing results provide concrete evidence that automated vulnerability discovery has been conducted.
  • Security testing (Clause 10.4.2): ISO/SAE 21434 recognizes fuzz testing as a valid security testing technique. Fuzzing results — including code coverage achieved, number of test cases executed, unique crashes found, and crash resolution status — constitute verification evidence artifacts that support the cybersecurity case.
  • Cybersecurity validation (Clause 10.5): Validation confirms that the cybersecurity goals are achieved at the vehicle level. Fuzzing at integration boundaries (between ECUs, between vehicle and external interfaces) validates that the assembled system resists malformed inputs, not just individual components.

For UNECE R155 type approval, demonstration that systematic fuzz testing has been performed across all external vehicle interfaces strengthens the case that the vehicle manufacturer has addressed known attack techniques, which is an explicit requirement of the regulation. Type approval authorities increasingly expect to see fuzzing results as part of the technical evidence package submitted with the cybersecurity management system (CSMS) documentation.

Common Pitfalls and How to Avoid Them

Automotive fuzzing programs frequently encounter the same set of challenges. Awareness of these pitfalls can save months of wasted effort:

  1. Fuzzing only at the protocol level without firmware instrumentation. Protocol-level fuzzing through physical interfaces is limited by communication speed and provides no code coverage feedback. Always supplement with instrumented firmware harnesses for coverage-guided deep exploration.
  2. Ignoring state machines. Many automotive protocols are stateful — UDS requires session transitions, SOME/IP requires service registration, DoIP requires vehicle identification. Fuzzing only single-message inputs without traversing state transitions misses the majority of the attack surface. Use stateful fuzzers or build harnesses that set up the required state before exercising target functions.
  3. No automated crash triage. A fuzzing campaign that produces 10,000 crash files is useless if no one reviews them. Build automated deduplication and severity classification into the fuzzing pipeline from day one. Integrate with issue tracking so that unique crashes are automatically filed as bugs.
  4. Stopping too early. Fuzzing coverage grows logarithmically: the first hour finds the easy bugs, but the deep vulnerabilities require days or weeks of continuous execution. Monitor coverage curves and continue fuzzing until the rate of new coverage discoveries drops below a meaningful threshold.
  5. Not fuzzing across supplier boundaries. OEMs often rely on suppliers to fuzz their own ECU firmware, but integration-level fuzzing at the boundary between supplier components is nobody’s responsibility unless explicitly assigned. Include integration fuzzing in the cybersecurity interface agreement (CIA) between OEM and supplier.
  6. Fuzzing production builds without sanitizers. A buffer overflow in a production binary might silently corrupt memory without causing a visible crash. Always fuzz with AddressSanitizer and UndefinedBehaviorSanitizer enabled so that memory safety violations are detected immediately, even if they do not cause a crash in the uninstrumented binary.

How ThreatZ Supports Fuzz Testing Programs

ThreatZ integrates fuzz testing into the broader cybersecurity engineering workflow rather than treating it as an isolated verification activity.

During TARA, ThreatZ identifies which components and interfaces have the highest risk exposure from malformed input attacks. These risk ratings directly inform fuzzing prioritization: high-risk interfaces receive more fuzzing effort and stricter coverage requirements. The threat scenarios identified in TARA — such as “attacker sends malformed UDS request to unlock security access” — become the basis for targeted fuzz testing campaigns with specific goals beyond random exploration.

ThreatZ tracks cybersecurity verification status across all work products, including fuzzing. Fuzzing campaigns are linked to the specific cybersecurity requirements they verify, creating traceability from risk assessment through verification results to the cybersecurity case. When a fuzzing campaign discovers a vulnerability, ThreatZ captures the finding, links it to the affected component and threat scenario, tracks the remediation through the development process, and verifies the fix through re-fuzzing — all within a single auditable workflow that directly supports ISO/SAE 21434 and UNECE R155 evidence requirements.

Key Takeaways

  • Fuzzing is the most effective technique for discovering unknown vulnerabilities in automotive input parsing code, complementing structured test cases and static analysis.
  • Three fuzzing approaches — generation-based, mutation-based, and coverage-guided — serve different purposes, and the most effective campaigns combine all three.
  • Each automotive protocol (CAN, UDS, DoIP, SOME/IP, Ethernet) requires tailored fuzzing strategies that account for its unique message structure, state model, and hardware interface.
  • Firmware-level fuzzing with coverage instrumentation finds deeper bugs faster than protocol-level fuzzing alone, but both are necessary for comprehensive coverage.
  • Lab setup should combine HIL benches for hardware-fidelity testing with simulation-based fuzzing for throughput and parallelism.
  • Automated crash triage, deduplication, and severity assessment are essential for translating raw fuzzing output into actionable security findings.
  • Continuous fuzzing integrated into CI/CD catches regressions immediately and builds a growing corpus and regression test suite over time.
  • Fuzzing directly satisfies ISO/SAE 21434 verification requirements and strengthens UNECE R155 type approval evidence.

Integrate Fuzz Testing into Your Cybersecurity Workflow

ThreatZ links TARA-driven risk analysis to fuzz testing campaigns, tracking coverage, findings, and remediation in a single auditable platform.

Explore ThreatZ