Defense in Depth describes an approach to security in which a series of defensive mechanisms are layered to protect valuable data and information, such that if one mechanism fails, another can be relied upon to thwart an attack.
To understand how secure software development relates to a defense in depth strategy, it is useful to borrow an analogy that explains how system accidents occur in medical environments. Many aspects of medical endeavour require human input, and the inevitable human error that goes with it. But generally, there are so many levels of defense that for a catastrophe to happen, an entire sequence of failures is required such than none of the defenses prevent it.
Professor Reason likened this principle to a sequence of slices of “Swiss Cheese”, except that in his model the holes in the “slices” are forever moving, closing, widening and shrinking.

The Swiss cheese model, applied to cybersecurity
Just like the checks and controls applicable to medical systems, a multiple level approach to cybersecurity makes a great deal of sense, such that if aggressors get past the first line of defense, then there are others in waiting.
No connected system is ever going to be both useful and absolutely impenetrable, and no single defense of that system aside can guarantee impenetrability. It therefore makes sense to protect it proportionately to the level of risk involved if it were to be compromised, and that means applying multiple levels of security – or “slices” of Swiss Cheese – so that if one level fails, others are standing guard.
Examples of such “slices” might include:
But should every one of these precautions be implemented on every occasion? And if not, how should the decisions be made as to what applies, and when? To address that question, it is useful to focus on the relationship between two key “slices of Swiss Cheese” – Domain Separation, and Secure Coding.
It is easy to suggest the application of every possible security precaution to every possible software architecture and application, but clearly that makes little commercial sense. Consider, for example, an automotive head unit deploying a Linux-based OS, complete with massive footprint and unknown software provenance. Where should attention be focused?
According to Peterson, Hope and Lavenhar [1], “Architectural risk assessment is a risk management process that identifies flaws in a software architecture and determines risks to business information assets that result from those flaws. Through the process of architectural risk assessment, flaws are found that expose information assets to risk, risks are prioritized based on their impact to the business, mitigations for those risks are developed and implemented, and the software is reassessed to determine the efficacy of the mitigations.”
Although this and similar studies are generally focused on enterprise computing, the basic premise of identifying and focusing attention on the components of the system at most risk makes a great deal of sense. Examples of high risk areas are likely to include:
Consider that principle in relation to a system deploying domain separation technology – in this case, a separation kernel hypervisor in an automotive application.

Leveraging a separation kernel hypervisor in an automotive application
It is easy to find examples of high risk areas specific to this scenario. For instance, consider the gateway virtual machine. How secure are its encryption algorithms? How well does it validate incoming data from the cloud? How well does it validate outgoing data to the different domains?
Then there are data endpoints – only those shown in the cloud in the diagram, but many more in reality. Is it feasible to inject rogue data? How is the application code configured to ensure that doesn’t happen?
Another potential vulnerability arises because many systems need to communicate across domains. For example, central locking generally belongs to a benign domain, but in an emergency after an accident it becomes imperative that doors are unlocked, implying communication with a more critical domain. However such communications between virtual machines are implemented, their very nature demands that their implementation should be secure.
Taint analysis plays a crucial role in the contribution of secure software coding to defense-in-depth by helping to identify and prevent vulnerabilities related to untrusted or user-supplied input. It works by tracking the flow of potentially dangerous data—known as “tainted” data—through a program, from its entry point (such as user input fields or external sources) to points where it could cause harm, like database queries, file operations, or system commands.
It is easy to see how taint analysis is potentially helpful in our separation kernel hypervisor with respect to the tracking of incoming data from the cloud, outgoing data to the different domains, data input from endpoints, and so on.
By highlighting these paths, taint analysis enables developers to detect and address security flaws such as injection attacks or buffer overflows before they can be exploited. This proactive approach is essential for building robust, secure applications that can safely handle untrusted input.
It would be easy to suggest that all code should be developed to the highest possible standards if security is a concern, but such an approach is not always commercially justifiable. By identifying high-risk software components, attention can be focused on the code associated with them. Applying a proactive software development approach to those high-risk components, complete with best-practice static and dynamic analysis techniques (particularly taint analysis) can help to ensure that secure code does not just provide an additional line of defense, but that it actively contributes to the effectiveness of the underlying architecture by underpinning its weak points.
Webinar on demand: Taint Analysis, Functional Safety, Cybersecurity, and you
Technical white paper: Secure code properly
Email: info@ldra.com
EMEA: +44 (0)151 649 9300
USA: +1 (855) 855 5372
INDIA: +91 80 4080 8707