Chapter 1: Introduction
Software has become part of the infrastructure of everyday life. It moves money, stores health records, controls vehicles, coordinates supply chains, and connects people across the world. This reach makes software enormously useful, but it also creates opportunities for harm. A defect in a small application may inconvenience a few users; a defect in a widely deployed or safety-critical system may expose millions of records, interrupt essential services, or put lives at risk.
Software security asks a deceptively simple question: How can we engineer software that continues to function correctly when someone is deliberately trying to make it fail? Answering that question requires more than adding a security tool near the end of development. It requires us to examine the decisions made throughout the software lifecycle: what the system should do, how it is structured, how it is implemented, how it is tested, and how it changes after deployment.
This chapter introduces the vocabulary and ideas that the rest of this book builds upon.
1.1 Learning Objectives
After completing this chapter, you should be able to:
- explain why software engineering is a lifecycle activity rather than merely programming;
- define software security and describe what it means to build security in;
- contrast proactive and reactive approaches to security;
- distinguish a vulnerability, bug, design flaw, exploit, and threat;
- explain how different defenses address different security problems; and
- apply confidentiality, integrity, availability, and other security goals to a software system.
1.2 From Programming to Software Engineering
Programming is the act of expressing a solution in code. Software engineering is broader: it is a systematic approach to developing, operating, maintaining, and evolving software. Code is an essential product of this process, but it is not the entire product. Real software also includes requirements, architecture, configuration, data, dependencies, tests, documentation, deployment infrastructure, and the practices used to keep the system working over time.
A typical software development lifecycle includes:
- Requirements: Determine what the system must do and what constraints it must satisfy.
- Design: Decide how responsibilities, data, components, and interfaces will be organized.
- Implementation: Translate the design into code and configuration.
- Verification and testing: Evaluate whether the system behaves as intended and identify defects.
- Deployment and operation: Release the system, monitor it, and respond to operational events.
- Maintenance and evolution: Correct defects, adapt to new environments, and revise capabilities.
Although this list appears sequential, development is usually iterative. A test result may reveal a misunderstood requirement. Operational data may motivate a redesign. A new dependency may change the system’s attack surface. The lifecycle is better understood as a set of connected, recurring activities than as a one-way assembly line.
Software does not wear out—but it does age
Software does not wear out through friction or material fatigue. Nevertheless, deployed software often appears to deteriorate. Its environment changes: dependencies are updated, attackers discover new techniques, assumptions become invalid, and repeated modifications make the system harder to understand. The software has not physically aged, but the relationship between the software and its environment has changed.
This distinction has an important security consequence. A system that was considered secure when released is not guaranteed to remain secure. New vulnerabilities may be discovered in its code or dependencies, features may introduce unsafe interactions, and attackers may find ways to violate assumptions that once seemed reasonable. Secure software must be maintained as deliberately as it is created.
Complexity is the central challenge
Software systems are extremely complex. Even a modest application can contain many components, third-party libraries, services, identities, permissions, data flows, and configuration options. Security failures often occur at boundaries:
- between components that make different assumptions;
- between trusted and untrusted data;
- between the permissions a user needs and the permissions the user receives;
- between an application and a third-party dependency; or
- between the system the designers imagined and the system that was deployed.
Software engineering gives us methods for managing complexity. Software security extends those methods to situations in which mistakes are not merely encountered by accident but actively searched for and exploited.
1.3 What Is Software Security?
Gary McGraw defines software security as engineering software so that it continues to function correctly under malicious attack {cite}mcgraw_software_security_2004. This definition emphasizes three ideas.
First, security is a property of the software system, not only of the network or machine on which it runs. Firewalls, antivirus software, and intrusion-detection systems provide valuable layers of defense, but they cannot compensate for every insecure design or implementation decision.
Second, security is an engineering concern. It must be considered in requirements, design, implementation, testing, deployment, and maintenance. A review immediately before release may find some defects, but fundamental design decisions can be expensive to change by then.
Third, the system operates in an adversarial environment. Reliability asks whether the system behaves correctly when components fail or users make mistakes. Security also asks what happens when an intelligent opponent intentionally searches for inputs, actions, or states that developers did not anticipate.
**Security and reliability overlap, but they are not identical.** A reliable system handles expected faults and accidental failures. A secure system must also withstand purposeful attempts to violate its goals.
Defense in depth
No single control can address every failure mode. Defense in depth uses multiple, mutually reinforcing layers so that the failure of one control does not immediately compromise the system. A web application might combine input validation, parameterized database queries, least-privilege credentials, network segmentation, monitoring, and reliable backups.
Some controls reduce the chance that a vulnerability is introduced. Some make exploitation harder. Some limit damage after compromise. Others help detect an attack or restore service. Their value comes from both their individual functions and their independence: several copies of the same flawed control do not create meaningful depth.
1.4 Building Security In
Software security aims to bring security into engineering from the beginning. This approach is often called building security in or shifting security left. The word left refers to diagrams that place early lifecycle activities, such as requirements and design, on the left and deployment on the right.
A proactive approach addresses security before a vulnerability reaches production. Examples include identifying security requirements, modeling threats, choosing architectures that isolate sensitive assets, adopting secure implementation patterns, reviewing code and dependencies, testing misuse cases, and planning for recovery.
A reactive approach addresses a vulnerability after it is discovered in a deployed system. Reactive work remains essential: no process eliminates every defect, and organizations must be able to detect, patch, contain, and learn from incidents. The mistake is to rely on reaction as the primary strategy.
| Proactive security | Reactive security |
|---|---|
| Begins during requirements and design | Begins after a weakness or attack is discovered |
| Seeks to prevent or mitigate vulnerabilities | Seeks to contain damage and restore safe operation |
| Makes fundamental changes while they are feasible | May require costly changes to deployed systems |
| Reduces exposure before release | Limits the consequences of residual risk |
The strongest programs do both. They prevent what they can, detect what remains, respond effectively, and feed lessons from incidents back into future engineering decisions.
Why timing matters
A missing authorization requirement found during design may be corrected by revising a model and a few interfaces. The same omission discovered after deployment may require changes to APIs, databases, clients, tests, documentation, and operational procedures—all while users remain exposed. Security incidents can also interrupt operations, trigger legal obligations, harm customers, and damage trust. Early work cannot guarantee a defect-free system, but it creates more opportunities to find consequential problems before attackers do.
1.5 Vulnerabilities, Bugs, and Design Flaws
A software vulnerability is a weakness that can lead to a security consequence. It exists when a defect or unsafe condition makes it possible to violate a security goal. The underlying defect may be in implementation or design.
Bugs
A bug is an implementation error. The intended design may be sound, but the code does not correctly realize it. Examples include an incorrect type conversion, an out-of-bounds memory access, an omitted authorization check, or improper handling of untrusted input.
Consider a service whose design requires it to verify a user’s permission before returning a record. If one endpoint accidentally omits the check, the implementation violates the design. Correcting the code brings the implementation back into alignment with the intended policy.
Design flaws
A design flaw is a fundamental problem in the system’s architecture, security mechanisms, or assumptions. The implementation may perfectly match the design, yet the system remains insecure.
Suppose an application performs authentication entirely on a client device and tells the server that authentication succeeded. Even flawless client code cannot make this design secure because an attacker controls messages sent to the server. The server must independently verify the identity or trustworthy proof of authentication. The allocation of trust and responsibility—not merely one line of code—must change.
| Bug | Design flaw | |
|---|---|---|
| Location | Implementation | Architecture, mechanism, or assumption |
| Symptom | Code departs from the intended design | The intended design permits a security failure |
| Remedy | Correct or replace faulty code | Reconsider trust, responsibilities, interfaces, or policy |
| Example | A missing bounds check | Client-side authentication trusted by the server |
The distinction matters because different techniques find different defects. Code review and static analysis may reveal implementation mistakes, while architecture analysis and threat modeling are better suited to flawed trust assumptions and missing security mechanisms. Secure development must address both.
1.6 Threats and Exploits
The terms vulnerability, exploit, and threat are related but not interchangeable.
- A vulnerability is a weakness that can lead to a security consequence.
- An exploit is software, data, or a sequence of actions that takes advantage of a vulnerability to cause unintended behavior.
- A threat actor is a person, group, organization, or automated agent capable of causing harm.
- A threat may refer to a potential cause of harm or, in some contexts, a class of harmful actions such as spoofing.
One vulnerability may have multiple exploits. An exploit may be performed manually or automated at scale. The relationship can be summarized as follows:
A threat actor uses an exploit to take advantage of a vulnerability and violate a security goal.
Imagine a file-processing service with a memory-safety vulnerability. A malicious file crafted to trigger the defect is an exploit input. The person sending it is the threat actor. If exploitation alters records, it violates integrity; if the service crashes, it violates availability; if memory is exposed, it may violate confidentiality.
Match the protection to the problem
- Protections against exploits block, detect, or contain attack techniques. Examples include endpoint protection, intrusion detection, application firewalls, exploit mitigations, and sandboxing.
- Protections against threat actors deter, identify, constrain, or respond to adversaries. Examples include authentication, monitoring, forensics, legal deterrence, and incident response.
- Protections against vulnerabilities prevent or remove weaknesses in the software. Examples include secure design, defensive programming, code review, security testing, and remediation.
Blocking a known exploit does not remove the vulnerability; correcting one vulnerability does not eliminate the threat actor; and identifying an attacker does not automatically restore a compromised system. Defense in depth depends on understanding which problem each control solves.
1.7 Security Goals
We cannot decide whether a system is secure without stating what must be protected. Security goals turn “make it secure” into properties that guide requirements, design, and tests.
The CIA triad
The three classic goals are confidentiality, integrity, and availability—the CIA triad.
Confidentiality means that information is disclosed only as intended. Encryption can support confidentiality, but so can access control, data minimization, and preventing secrets from appearing in logs or errors. A payroll system violates confidentiality if one employee can read another’s salary without authorization.
Integrity means that programs and data are protected against improper modification or destruction. A system may also need to identify who made an authorized change and preserve the order of transactions. A banking system violates integrity if an attacker can alter a balance or replay a transfer.
Availability means that the system and its information are accessible and operational when required. Redundancy, capacity planning, graceful degradation, rate limiting, backups, and disaster recovery can support availability. A hospital system that protects every record from disclosure but cannot retrieve one during an emergency is not secure in the way its users need.
These goals can create tradeoffs. Extensive verification may reduce performance and affect availability. Replication may improve availability while increasing the places where confidentiality must be protected. Good engineering makes these tensions explicit.
Additional goals
Identification and authentication establish and verify a claimed identity for a user, process, or device. Identification asks, “Who are you claiming to be?” Authentication asks, “What evidence supports that claim?”
Authorization determines what an authenticated entity may do. Proving that a user is Alice does not establish that Alice may approve a payment, read a medical record, or administer the system.
Accountability means that security-relevant actions can be traced to the responsible actor. Logs, audit trails, trustworthy timestamps, and protected identities can support it. Non-repudiation is a related but stronger property: it provides evidence that makes it difficult for an actor to credibly deny an action.
Privacy concerns a person’s ability to understand and control how information about them is collected, used, shared, retained, and deleted. Privacy and confidentiality overlap but are not synonymous. An organization may keep personal data confidential while collecting it without a valid purpose or using it in unexpected ways.
Security goals are contextual
The importance of each goal depends on the system. Availability may dominate for emergency communications, while confidentiality may dominate for a password manager. Security requirements should therefore name the asset, desired property, relevant conditions, and—where possible—a measurable criterion. “The system must be secure” is not testable. “Only clinicians assigned to a patient’s care may view the active treatment record, and every access must be recorded in a tamper-evident log” provides engineering guidance.
1.8 Putting the Concepts Together
Consider a web application that lets university students view grades.
- Asset: grade records and the service that provides them.
- Security goals: students may view only their own grades (confidentiality); unauthorized users may not alter grades (integrity); records must be available during defined hours (availability); and accesses and changes must be attributable to an account (accountability).
- Threat actor: a student attempting to view another student’s record.
- Vulnerability: the server accepts a student identifier from the browser but does not verify that it belongs to the authenticated account.
- Exploit: the student changes the identifier and retrieves another student’s record.
- Root cause: if the design assigns authorization to browser code, it contains a design flaw; if the server-side design requires authorization but one handler omits it, the defect is a bug.
- Proactive controls: define authorization requirements, centralize server-side access control, analyze trust boundaries, review the design, and test cross-account requests.
- Reactive controls: detect unusual access, investigate audit records, disable compromised accounts, correct the vulnerability, notify affected people when required, and learn from the incident.
Precise language matters because each term identifies a different part of the problem and suggests a different engineering response.
1.9 Chapter Summary
Software engineering manages the complexity of creating and evolving software systems. Software security applies that discipline in an adversarial setting, aiming to ensure that systems continue to satisfy their goals under attack.
Security must be built into the lifecycle and supported by multiple layers of defense. Proactive practices reduce the vulnerabilities that reach production; reactive capabilities detect, contain, and correct the failures that remain.
A vulnerability is a weakness with security consequences. It may arise from an implementation bug or a design flaw. An exploit takes advantage of a vulnerability, while a threat actor is a potential source of harm. Effective defenses address these distinct parts of the problem.
Security is meaningful only in relation to explicit goals. Confidentiality, integrity, and availability form a foundation, supplemented by identification, authentication, authorization, accountability, non-repudiation, and privacy.
1.10 Review Questions
- Why is software engineering broader than programming?
- Why can an unchanged program become less secure over time?
- What does it mean to shift security left? Why does it not eliminate the need for incident response?
- Explain the difference between a bug and a design flaw. Give one example of each.
- Distinguish a vulnerability, an exploit, and a threat actor.
- Why might blocking a particular exploit leave a system vulnerable?
- Describe confidentiality, integrity, and availability requirements for an online voting system.
- How do authentication and authorization differ?
- Give an example of a system that preserves confidentiality but violates privacy.
- Choose a system you use regularly. Identify one asset, one threat actor, one plausible vulnerability, and two layers of defense.
:filter: docname in docnames