Secure Software Engineering and DevSecOpsIntroductionSoftware is a primary source of organizational value and an equally important source of cyber risk. A defect in authentication, authorization, input validation, dependency management, or deployment configuration can expose personal data, interrupt services, or enable financial fraud. Secure software engineering treats security as a property that must be designed, implemented, verified, deployed, and maintained—not as a final inspection activity. DevSecOps extends this idea across development and operations. It integrates security responsibilities, evidence, and automated controls into the software delivery pipeline while preserving the rapid feedback associated with DevOps. The goal is not to make every developer a security specialist, but to make secure decisions a normal and measurable part of engineering work. This chapter focuses on web applications and APIs, because they are common interfaces between users, organizations, and distributed services. Learning ObjectivesBy the end of this chapter, students should be able to: - Explain the secure software development lifecycle and security requirements engineering.
- Construct a basic threat model using assets, actors, trust boundaries, threats, and mitigations.
- Apply secure coding principles to web applications and APIs.
- Distinguish code review, software composition analysis, dynamic testing, and penetration testing.
- Design practical secrets-management and CI/CD controls.
- Analyze security trade-offs using a realistic software-delivery scenario.
- Explain governance, ethical, privacy, and supply-chain responsibilities in secure software engineering.
1. Security Across the Software Development LifecycleA conventional software lifecycle includes requirements, design, implementation, testing, deployment, and maintenance. Security activities should occur in each phase: | Lifecycle activity | Representative security work | Typical evidence |
|---|
| Requirements | Abuse cases, privacy requirements, regulatory constraints | Security requirements and acceptance criteria | | Architecture and design | Threat modeling, trust-boundary analysis, secure architecture | Threat model and design decisions | | Implementation | Secure coding, dependency control, peer review | Reviewed commits and scan results | | Verification | Security tests, fuzzing, static and dynamic analysis | Test reports and defect records | | Release | Artifact signing, configuration checks, approvals | Build provenance and release record | | Operations | Monitoring, patching, incident response, recovery testing | Logs, alerts, exercises, post-incident reviews |
This approach is often called a shift left because certain security decisions move earlier in development. However, security cannot shift entirely left: vulnerabilities may arise from production configuration, newly disclosed dependencies, changing threats, or operational misuse. A mature program therefore combines early prevention with continuous detection and response. Security requirements should be testable. “The system must be secure” is not testable; “After five failed login attempts within 10 minutes, the account is temporarily locked or subjected to an approved step-up control” is substantially more precise. Requirements should also avoid prescribing an implementation unnecessarily. A requirement may specify that passwords must be protected using an approved adaptive password-hashing algorithm, while allowing the engineering team to select a supported implementation. Useful security requirement categories include confidentiality, integrity, availability, authentication, authorization, accountability, privacy, resilience, and maintainability. For each requirement, define its owner, priority, acceptance test, and exception process. 2. Threat ModelingThreat modeling is a structured method for anticipating how a system could be attacked or misused. It is most effective during design, when architectural changes are less expensive, but it should be revisited when interfaces, data flows, dependencies, or deployment environments change. A basic threat model identifies: - Assets: data, credentials, services, intellectual property, and safety-critical functions.
- Actors: ordinary users, administrators, insiders, external attackers, compromised services, and automated agents.
- Entry points: web pages, APIs, mobile clients, message queues, administration interfaces, and CI/CD systems.
- Trust boundaries: transitions between privilege, identity, network, tenant, or data-classification domains.
- Data flows: what crosses each boundary, in what format, and under whose authority.
- Security objectives: confidentiality, integrity, availability, authenticity, accountability, and privacy.
One useful classification is STRIDE: spoofing, tampering, repudiation, information disclosure, denial of service, and elevation of privilege. STRIDE is a brainstorming framework, not a complete risk calculation. It should be supplemented by business impact, privacy analysis, abuse cases, and domain expertise. A practical threat-modeling sequence is: - Draw the system context and data-flow diagram.
- Identify assets and their required protections.
- Mark trust boundaries and privileged operations.
- Enumerate threats using STRIDE or a comparable method.
- Record existing controls and residual risks.
- Assign owners, priorities, and verification methods.
- Revisit the model after significant change.
Risk is commonly discussed as a combination of likelihood and impact. A simple qualitative model is: Risk priority = Likelihood × Impact Here, likelihood and impact are ordinal ratings such as 1 through 5. This multiplication is a prioritization aid, not a physical law or a precise probability. It assumes that the organization has defined consistent scales and that the ratings are comparable. A high-impact, low-likelihood threat may deserve more attention than a moderate-impact, high-likelihood issue when safety, law, or mission continuity is involved. Threat models should lead to design decisions. For example, if an API permits a user to retrieve an invoice by supplying an identifier, the model should ask whether the server verifies that the authenticated user is authorized for that invoice. This directly exposes the risk of broken object-level authorization, rather than merely labeling the endpoint “authenticated.” 3. Secure Architecture and Design PrinciplesSeveral principles provide durable guidance: - Least privilege: grant only the permissions required for a task and duration.
- Defense in depth: use independent layers so that one failure does not expose the whole system.
- Fail securely: errors should deny unsafe actions, avoid sensitive disclosure, and leave systems in a controlled state.
- Secure defaults: new deployments should begin with protective settings.
- Complete mediation: check authorization at every relevant access, not only at the user interface.
- Separation of duties: divide sensitive actions among people, services, or credentials where practical.
- Minimize attack surface: remove unused endpoints, libraries, ports, privileges, and administrative functions.
- Keep security decisions centralized: shared authentication, authorization, logging, and policy components reduce inconsistent implementations, although they must themselves be highly reliable.
Security architecture also requires explicit trust-boundary decisions. A browser is not a trusted enforcement point; hidden fields, client-side validation, and interface restrictions can be modified by an attacker. The server must validate requests and enforce authorization. Similarly, an internal network is not automatically trustworthy. Service-to-service authentication, authorization, encryption, and monitoring remain necessary in distributed systems. 4. Secure Coding for Web Applications and APIsInput handling and output encodingInput validation should be performed on the server and should be based on an allow-list where feasible. Validation should consider type, length, range, structure, and business meaning. Validation alone does not prevent every injection problem; output must also be encoded for its context, such as HTML, JavaScript, URL, SQL, or a shell command. Parameterized queries separate data from SQL instructions and are preferred to string concatenation. The same principle applies to command execution, template rendering, and directory paths. If an operation requires a system command, an API that accepts structured arguments is generally safer than constructing a shell string. Authentication and session managementAuthentication establishes identity; authorization determines what that identity may do. Passwords should not be encrypted for later recovery. They should be processed using a current, adaptive password-hashing function with a unique salt and a work factor selected through performance testing. Password-reset tokens should be random, short-lived, single-use, and stored or compared safely. Sessions require secure random identifiers, expiration, rotation after authentication or privilege changes, and cookie protections such as Secure, HttpOnly, and an appropriate SameSite policy. Logout should invalidate the session server-side when the architecture uses server-managed sessions. Multi-factor authentication is particularly valuable for administrators and high-impact operations. AuthorizationAuthorization should be explicit and deny by default. Role-based access control assigns permissions through roles; attribute-based access control evaluates attributes such as user, resource owner, tenant, location, or transaction state. Whichever model is used, authorization must be enforced on the server for every protected object and operation. A common API error is checking that a user is logged in but not checking whether the requested object belongs to that user. Another is trusting a role or tenant identifier supplied by the client. The server should derive or verify security-relevant attributes from trusted identity and authoritative data. API securityAPIs should define authentication, authorization, input schemas, error behavior, rate limits, pagination, and versioning. Important practices include: - validate content type and schema;
- reject unexpected fields where appropriate;
- limit request size, execution time, and result volume;
- avoid returning unnecessary fields;
- use TLS for data in transit;
- apply rate limits according to identity, resource, and operation;
- prevent replay of sensitive operations using idempotency controls or transaction identifiers;
- protect administrative and internal endpoints separately;
- log security-relevant events without recording secrets or excessive personal data.
CORS is a browser access-control mechanism, not an authentication mechanism. An origin should not be allowed merely because it appears in a request parameter. CSRF defenses are important for browser-based cookie authentication; bearer-token APIs have different exposure patterns and still require careful token storage and authorization. Error handling and loggingErrors should help legitimate operators diagnose failures without revealing stack traces, credentials, database details, or internal topology to untrusted users. Logs should record event type, time, relevant identity, resource, outcome, and correlation identifier, subject to privacy and retention rules. Log integrity and access control matter because attackers may attempt to erase or manipulate evidence. 5. Review and Automated AnalysisNo single tool detects all vulnerabilities. Secure engineering uses complementary techniques. | Technique | Main strength | Important limitation |
|---|
| Peer code review | Context, design reasoning, business authorization logic | Human inconsistency and limited scale | | Static application security testing | Finds patterns without executing the application | False positives; limited runtime context | | Software composition analysis | Identifies known issues and license concerns in dependencies | A clean database result does not prove safety | | Dynamic application testing | Observes behavior of a running system | Test coverage and environment limitations | | Interactive testing | Relates runtime behavior to code paths | Operational complexity | | Fuzz testing | Finds unexpected input and robustness failures | Requires suitable harnesses and oracles | | Penetration testing | Adversarial validation of realistic attack paths | Periodic, scope-dependent, and not exhaustive |
Code review should begin with security-sensitive changes: authentication, authorization, cryptography, deserialization, file handling, payments, tenant boundaries, and infrastructure configuration. Reviewers should ask what an attacker controls, what assumptions are trusted, whether authorization occurs at the object and operation level, and whether failures are safe. Software composition analysis must cover direct and transitive dependencies, container images, operating-system packages, and build tools. Organizations need an inventory or software bill of materials, a process for triaging vulnerabilities, and a way to identify affected products. Version upgrades should be tested; blindly upgrading can introduce incompatibility or a malicious package. 6. Security Testing and Defect ManagementSecurity tests should be derived from threats and requirements. Examples include: - unauthenticated requests to protected endpoints are rejected;
- users cannot read or modify another tenant’s records;
- malformed input produces controlled errors;
- rate limits resist excessive requests without blocking legitimate use unfairly;
- secrets do not appear in responses, logs, artifacts, or source control;
- expired tokens and revoked sessions cannot perform protected actions;
- dependency and container policies behave as intended.
A vulnerability should be triaged by exploitability, impact, exposure, affected assets, compensating controls, and remediation cost. Severity labels help organize work but should not replace engineering judgment. Exceptions require an owner, rationale, expiry or review date, compensating controls, and acceptance by an authorized risk owner. Security testing environments must be representative enough to reveal real problems while protecting real data. Production-like credentials should not be copied into test systems. Test data should be synthetic or appropriately de-identified. 7. Secrets ManagementSecrets include passwords, API keys, private keys, signing keys, tokens, and database credentials. They should never be committed to source repositories, embedded in client applications, printed in logs, or passed broadly through command-line arguments. A secrets-management design should provide: - centralized storage with encryption at rest;
- access controlled by workload identity and least privilege;
- audit logs for retrieval and administrative actions;
- rotation and revocation procedures;
- short-lived credentials where feasible;
- separation between development, test, and production secrets;
- backup and recovery procedures that do not create uncontrolled copies.
Secret scanning is useful but not sufficient. Once a secret has entered source control or a log, assume it may be compromised: revoke or rotate it, investigate access, remove exposure from future history where appropriate, and preserve evidence according to policy. Encryption keys require especially careful lifecycle management because losing a key may make protected data unrecoverable, while exposing one may compromise large data sets. 8. CI/CD and DevSecOps ControlsA secure pipeline treats source code, build definitions, dependencies, runners, artifacts, and deployment credentials as an interconnected supply chain. Typical stages are: - Pre-commit and pull request: secret detection, formatting, unit tests, and security-focused review.
- Build: dependency resolution from approved sources, static analysis, tests, and reproducible build practices.
- Package: artifact creation, metadata generation, vulnerability checks, and signing.
- Pre-production: deployment to an isolated environment, dynamic tests, configuration validation, and approval rules.
- Production: controlled deployment, monitoring, rollback, and post-deployment verification.
Pipeline permissions should be minimal. Build jobs should not receive unrestricted production credentials, and pull requests from untrusted sources must not be able to exfiltrate protected secrets. Branch protection, mandatory reviews, isolated runners, pinned or verified actions, protected environments, and immutable artifacts reduce supply-chain risk. A security gate should be actionable. Blocking every low-confidence warning produces alert fatigue and encourages bypasses. Policies should define which findings block a release, how exceptions are approved, and how rapidly critical issues must be addressed. Security metrics should measure meaningful outcomes, such as time to remediate exploitable vulnerabilities, percentage of critical services with current threat models, dependency inventory coverage, and recurrence of defect classes. Counting scans alone measures activity, not security. 9. Case Study: Illustrative Online Learning APIBackgroundConsider an illustrative university platform with a web interface and REST API. Students view courses and submit assignments; instructors grade work; administrators manage enrollment. The platform uses multiple services and a CI/CD pipeline. ProblemA review discovers that a student can request another student’s submission by changing an identifier in the URL. A third-party library has a known vulnerability, and a database password appears in a build log. The team proposes simply adding a web-application firewall rule. AnalysisThe identifier issue is broken object-level authorization. The browser is supplying a resource identifier, but the API is failing to verify ownership or instructor authority. The problem is therefore an application authorization defect, not merely malicious traffic. A firewall may detect some patterns but cannot reliably understand enrollment and grading relationships. The dependency issue requires inventory, affected-version analysis, upgrade or mitigation, and testing. The exposed database password must be revoked and replaced; deleting the log line does not make the credential safe. The threat model identifies student submissions and grades as confidential assets, the API as an entry point, and the student/instructor boundary as a critical authorization boundary. Approach and solutionThe team implements server-side authorization that checks the authenticated subject, course membership, submission ownership, and instructor privileges. It adds tests for cross-student and cross-course access, including negative cases. The dependency is upgraded after compatibility testing, and the build produces a software bill of materials. Database access moves to a secrets manager using a short-lived workload identity. Logs are reviewed for additional exposure. The pipeline adds secret scanning, dependency checks, protected deployment environments, and a rule preventing unreviewed changes to authorization modules. Threat-model updates become part of the definition of done for new data flows. OutcomeThe direct vulnerability is removed, regression tests make recurrence less likely, and credential rotation limits the impact of the previous exposure. The organization also recognizes that security is a system property: application controls, identity, pipeline governance, dependency management, and monitoring must operate together. Learning points- Authentication does not imply authorization.
- Client-controlled identifiers require server-side object checks.
- A vulnerability scanner cannot replace architectural reasoning.
- Exposed secrets require rotation and investigation, not only deletion.
- Security controls should be integrated into normal delivery workflows.
10. Governance, Ethics, and Contemporary PracticeSecure software engineering involves legal and ethical duties. Teams should minimize collected personal data, define retention periods, restrict access, and communicate material incidents through appropriate channels. Security testing must be authorized, scoped, and conducted without unnecessary disruption. Researchers and students should not test systems without permission, even when the intent is educational. Organizations increasingly use artificial intelligence to assist code generation, review, test creation, and vulnerability triage. AI-generated code must be treated as untrusted draft material: it may contain insecure defaults, licensing problems, fabricated APIs, data leakage, or subtle authorization errors. Sensitive source code and credentials should not be submitted to an AI service unless organizational policy and contractual protections permit it. Human review, automated testing, provenance, and accountability remain necessary. Contemporary practice emphasizes software supply-chain security, provenance, signed artifacts, memory-safe languages where suitable, infrastructure-as-code scanning, zero-trust service identity, and continuous exposure management. None is a universal solution. Controls must be selected according to system risk, operational capacity, user impact, and evidence of effectiveness. Challenges and LimitationsSecurity work faces recurring constraints. Threat models can become stale; scanners generate false positives and false negatives; dependency data can be incomplete; security gates can slow delivery if poorly designed; and legacy systems may not support modern identity or testing. Excessive controls can cause workarounds, while insufficient controls leave risks invisible. Security also competes with usability, availability, cost, accessibility, and time-to-market. The appropriate response is risk-informed engineering: prioritize high-consequence assets, automate repeatable checks, provide developers with secure libraries and clear feedback, measure remediation, and periodically test whether controls actually reduce risk. Security is not achieved by compliance evidence alone. Chapter SummarySecure software engineering integrates security requirements, threat modeling, secure architecture, coding, review, testing, dependency governance, secrets management, deployment controls, and operations. Threat modeling makes assets, actors, trust boundaries, and abuse paths visible. Secure web and API development requires server-side validation, contextual output encoding, strong authentication, explicit authorization, protected sessions, controlled errors, and appropriate rate limits. Code review, static and dynamic analysis, composition analysis, fuzzing, and penetration testing provide complementary evidence rather than interchangeable guarantees. DevSecOps embeds these activities in CI/CD through least-privilege pipelines, protected environments, artifact integrity, secret scanning, dependency controls, and measurable remediation. Effective practice also respects privacy, ethics, regulation, and human accountability. Key TermsThreat model: A structured representation of assets, actors, threats, trust boundaries, and mitigations. Trust boundary: A point where data, identity, privilege, or assumptions change. Security requirement: A testable statement of a system’s required security behavior. Least privilege: Granting only the access necessary for an authorized task. Defense in depth: Using multiple independent protective layers. Authentication: Establishing or verifying an identity. Authorization: Determining whether an identity may perform an action. Object-level authorization: Checking permission for a specific resource or record. Input validation: Checking whether input satisfies permitted type, structure, range, and meaning. Output encoding: Transforming data safely for its destination context. Static application security testing: Analysis of code or artifacts without executing the application. Dynamic application security testing: Security testing of a running application. Software composition analysis: Examination of dependencies for vulnerabilities, licenses, and provenance. Software bill of materials: An inventory of software components in a product or artifact. Secret: Sensitive authentication or cryptographic material such as a key, token, or password. CI/CD: Continuous integration and continuous delivery or deployment practices. Artifact: A build output such as a package, container image, or binary. Threat model residual risk: Risk remaining after existing controls are considered. Secure default: A starting configuration that favors protection without requiring special action. Review QuestionsShort Answer Questions- Why should security requirements be testable?
- What is the difference between authentication and authorization?
- Name four elements normally included in a threat model.
- Why is software composition analysis necessary when an organization writes its own application code?
- What should happen when a credential is discovered in a public repository?
Long Answer Questions- Explain how security activities can be integrated across the software development lifecycle.
- Compare static analysis, dynamic testing, code review, and penetration testing, including one limitation of each.
- Describe a secure design for a multi-tenant API that prevents users from accessing another tenant’s records.
- Explain how least privilege, protected environments, artifact signing, and isolated runners contribute to CI/CD security.
- Discuss the ethical and privacy responsibilities involved in security testing and logging.
Analytical / Application Questions- An API verifies that a requester is logged in but accepts a document identifier supplied by the client without checking ownership. Identify the threat, explain the trust-boundary failure, and propose tests and a mitigation.
- A critical dependency vulnerability is discovered one day before release. Analyze the technical, operational, and governance factors that should determine whether to patch, mitigate, delay, or proceed under an exception.
- Design a threat-model summary for an online payment endpoint. Identify at least three assets, two trust boundaries, four threats, and corresponding controls.
Multiple Choice Questions with AnswersQuestion 1Which statement best distinguishes authentication from authorization? A. Authentication determines what a user may do; authorization verifies identity. B. Authentication verifies identity; authorization determines permitted actions. C. Authentication encrypts data; authorization compresses data. D. Authentication applies only to administrators; authorization applies only to students. Correct Answer: B. Authentication verifies identity; authorization determines permitted actions. Question 2Which control most directly prevents a student from retrieving another student’s submission by changing an identifier? A. A longer URL B. Client-side input validation only C. Server-side object-level authorization D. A larger database index Correct Answer: C. Server-side object-level authorization Question 3What is the principal purpose of software composition analysis? A. To replace all human code review B. To identify risks in direct and transitive dependencies C. To encrypt application logs D. To measure network bandwidth Correct Answer: B. To identify risks in direct and transitive dependencies Question 4Which practice is safest when a database password is found in a build log? A. Delete only the visible line from the log B. Rename the database C. Rotate or revoke the credential and investigate exposure D. Hide the password with a longer variable name Correct Answer: C. Rotate or revoke the credential and investigate exposure Question 5Which statement about a web application firewall is most accurate? A. It replaces server-side authorization logic. B. It guarantees that all application vulnerabilities are removed. C. It can provide an additional layer but cannot replace application controls. D. It makes authentication unnecessary. Correct Answer: C. It can provide an additional layer but cannot replace application controls. Question 6Which CI/CD practice most directly limits the damage caused by a compromised build job? A. Giving every job permanent production administrator credentials B. Using least-privilege permissions and isolated runners C. Disabling audit logs D. Allowing unsigned artifacts into production Correct Answer: B. Using least-privilege permissions and isolated runners Question 7Which activity is an example of dynamic application security testing? A. Inspecting source code without running it B. Testing a deployed application with crafted requests C. Listing dependency licenses only D. Reviewing a requirements document Correct Answer: B. Testing a deployed application with crafted requests Question 8In threat modeling, a trust boundary is best described as: A. A point where privilege, identity, or assumptions change B. A duplicate backup of source code C. A physical wall around a server room only D. A list of approved programming languages Correct Answer: A. A point where privilege, identity, or assumptions change Question 9Why should client-side validation not be the only input-validation control? A. Clients cannot display error messages. B. Client behavior can be modified or bypassed by an attacker. C. Servers cannot process structured data. D. Validation always reduces availability. Correct Answer: B. Client behavior can be modified or bypassed by an attacker. Question 10Which item is an appropriate security metric? A. Number of decorative dashboard colors B. Number of meetings held regardless of outcome C. Time to remediate exploitable vulnerabilities D. Number of source-code lines written Correct Answer: C. Time to remediate exploitable vulnerabilities
|