CISSP-115 · Lesson 8 of 12 · 31 min
Security testing in the software life cycle
Most organizations now build or customize software, whether that means a public website, an internal workflow tool or the scripts that configure cloud infrastructure. Every one of those artefacts can contain security defects, and defects found late cost far more to fix than defects found early. Security testing in the software life cycle is the set of assessment activities that find those defects while code is being designed, written, built and deployed. Sub-domain 6.2 of the outline lists code review and testing, misuse case testing, test coverage analysis and interface testing among the activities a security professional must be able to plan and evaluate.
This lesson takes the manager's view. It explains what each kind of security testing does, where it fits in the pipeline, what its results mean and how to judge whether a development team's testing gives adequate assurance. For the engineering detail of testing in general, see CMPUT-301 Software Engineering; for the mechanisms behind common software flaws and their fixes, see CMPUT-331 Computer Security.
Why test early
The cost of fixing a defect rises as it moves through the life cycle. A design flaw found in a threat modelling session costs a conversation; the same flaw found in production may require an emergency patch, customer notification and a redesign. Estimates of the multiplier vary widely and many published figures are poorly sourced, but the direction is not in dispute. The practice of moving testing earlier is often called shifting left. It does not remove the need for testing in production; it adds checks at each stage so that fewer defects survive to the end.
Code review
Code review is the examination of source code by someone other than its author. In a security context, reviewers look for flaws such as missing input validation, unsafe handling of queries, weak use of cryptography, hard-coded secrets, missing authorization checks and poor error handling. Formal inspections, such as the Fagan inspection method, follow defined roles and stages and are used for high-assurance software. Most teams use lighter peer review in which every change is approved by another developer before it is merged, with security-focused review for sensitive components.
For managers, the questions are about coverage and competence. Are all changes reviewed, including urgent fixes? Are reviewers trained to recognize security issues? Do sensitive components, such as authentication and payment handling, get a review by someone with security expertise? Is there a checklist so that reviews are consistent? The evidence is the review record in the source control platform, linked to the change.
| Checklist area | What the reviewer looks for |
|---|---|
| Input handling | All external input validated against an allow-list of expected forms; queries use parameters |
| Authentication and sessions | Uses the approved framework; no custom password handling or token formats |
| Authorization | Every operation checks that the user is allowed to act on that specific object |
| Cryptography | Approved libraries and algorithms; no home-made schemes; keys not in code |
| Secrets | No passwords, keys or tokens in source or configuration files committed to the repository |
| Error handling and logging | Errors do not reveal internals to users; security events are logged without sensitive data |
| Dependencies | New libraries approved, pinned to versions and free of known critical vulnerabilities |
The example below shows the kind of change a reviewer should insist on. The first function builds a database query by joining strings, so user input becomes part of the query text. The second passes the input as a parameter, so the database treats it strictly as data. The point for a manager is not the syntax but the review rule: queries must be parameterized, and a reviewer who sees string-built queries should reject the change.
import sqlite3
db = sqlite3.connect(':memory:')
db.execute('CREATE TABLE customers (id INTEGER, name TEXT, region TEXT)')
db.executemany('INSERT INTO customers VALUES (?, ?, ?)',
[(1, 'Aster Ltd', 'west'), (2, 'Birch Co', 'east'), (3, 'Cedar Inc', 'west')])
# Rejected in review: query text built by joining strings with user input
def find_by_region_unsafe(region):
return 'SELECT name FROM customers WHERE region = \'' + region + '\''
# Approved: the input is passed as a parameter, never as query text
def find_by_region(region):
return db.execute('SELECT name FROM customers WHERE region = ?', (region,)).fetchall()
print('Unsafe version builds this query text:')
print(' ', find_by_region_unsafe('west'))
print('Safe version returns:', find_by_region('west'))
# Unexpected input is simply treated as a value that matches nothing
print('Safe version with odd input:', find_by_region("west' OR '1'='1"))Unsafe version builds this query text:
SELECT name FROM customers WHERE region = 'west'
Safe version returns: [('Aster Ltd',), ('Cedar Inc',)]
Safe version with odd input: []Automated security testing tools
Automated tools scale testing beyond what people can review. Each type sees the application from a different angle, and a mature program combines them.
| Type | What it examines | When it runs | Strengths | Limits |
|---|---|---|---|---|
| Static application security testing (SAST) | Source code or binaries without running them | On commit or in the build | Early, points to exact lines, covers code paths not easily reached | False positives; misses runtime and configuration issues |
| Dynamic application security testing (DAST) | The running application from the outside | In a test environment | Finds runtime and configuration issues, language-independent | Needs a running app; limited insight into code; may miss unreached paths |
| Interactive application security testing (IAST) | The running app from inside, through instrumentation | During functional testing | Combines code and runtime context, fewer false positives | Language and framework support varies; needs good test coverage |
| Software composition analysis (SCA) | Third-party libraries and their known vulnerabilities and licences | In the build and continuously | Covers the large share of code that is not written in-house | Depends on vulnerability databases; reachability often unclear |
| Secrets scanning | Repositories and builds for credentials and keys | On commit and in history | Catches a common, high-impact mistake early | Only finds recognizable patterns |
| Infrastructure as code scanning | Templates that define cloud resources | Before deployment | Prevents misconfigured resources from being created | Only covers resources defined as code |
Fuzz testing deserves a separate mention. Fuzzing supplies large volumes of unexpected, malformed or random input to a program to find crashes, hangs and unhandled errors, which often indicate robustness or security defects. Mutation fuzzers alter valid samples; generation fuzzers build inputs from a model of the expected format. Coverage-guided fuzzers measure which code each input reaches and favour inputs that explore new paths. For a manager, fuzzing is evidence of robustness for components that parse untrusted data, such as file uploads and network protocols, and it is increasingly built into continuous integration.
Software bills of materials and the supply chain
Modern applications are assembled more than written: open-source and commercial components often make up most of the code. A software bill of materials (SBOM) is a formal, machine-readable inventory of the components in a piece of software, their versions and their relationships. Common formats are SPDX (an ISO standard, ISO/IEC 5962:2021) and CycloneDX (standardized by Ecma International as ECMA-424 in 2024). An SBOM lets an organization answer quickly whether it uses a component when a new vulnerability is announced, and lets customers evaluate what they are buying.
In Canada, the Canadian Centre for Cyber Security has published guidance on software supply chain security and joint guidance with allied agencies on SBOMs and secure-by-design principles. Federal departments reference these in procurement, and the Critical Cyber Systems Protection Act, enacted through Bill C-8 in June 2026, is expected to require designated operators in federally regulated sectors to manage third-party and supply chain risks as regulations are made (check current status). Private organizations increasingly ask vendors for SBOMs and secure development attestations in contracts.
# A tiny SBOM extract checked against an advisory list (illustrative data)
sbom = [
{'name': 'log-utils', 'version': '2.14.0', 'terms': 'Apache-2.0'},
{'name': 'json-fast', 'version': '1.9.3', 'terms': 'MIT'},
{'name': 'imgparse', 'version': '0.8.1', 'terms': 'BSD-3-Clause'},
{'name': 'netclient', 'version': '5.2.0', 'terms': 'GPL-3.0'},
]
advisories = {('log-utils', '2.14.0'): 'critical', ('imgparse', '0.8.1'): 'high'}
approved_terms = {'Apache-2.0', 'MIT', 'BSD-3-Clause'}
for c in sbom:
issues = []
sev = advisories.get((c['name'], c['version']))
if sev:
issues.append(f'known vulnerability ({sev})')
if c['terms'] not in approved_terms:
issues.append(f"terms {c['terms']} need legal review")
status = '; '.join(issues) if issues else 'ok'
print(f"{c['name']:10s} {c['version']:7s} {status}")log-utils 2.14.0 known vulnerability (critical) json-fast 1.9.3 ok imgparse 0.8.1 known vulnerability (high) netclient 5.2.0 terms GPL-3.0 need legal review
The same inventory supports two kinds of decisions. Security decides how quickly vulnerable components must be upgraded, using the prioritization approach from lesson 4. Legal and procurement decide whether licence obligations, such as copyleft terms, fit how the software will be distributed. A component with an unknown licence or no maintainer is also a risk in its own right.
Misuse cases, interface testing and coverage
Functional tests check that software does what it should. Misuse case testing checks that it does not do what it should not. A misuse case describes how a feature could be abused, from the point of view of someone with harmful intent, and leads to a test of the control that should stop it: a user trying to view another customer's invoice by changing an identifier, a buyer submitting a negative quantity, a form submitted thousands of times a minute. Misuse cases come from threat modelling and from past incidents, and they are written alongside ordinary use cases so that requirements include the controls.
Interface testing examines the points where components meet: application programming interfaces, user interfaces, network interfaces and physical interfaces. Security defects cluster at interfaces because each side may assume the other validates input or checks authorization. API testing confirms authentication, authorization on every endpoint, input validation, rate limiting and error handling. Test coverage analysis measures how much of the code or requirements the tests exercise; for security, coverage of authorization checks and input handling matters more than a single overall percentage.
Worked problem
Writing a misuse case
A new feature lets customers download their past statements from a URL containing the statement number. Write a misuse case and the test that follows from it.
Show solution
- Use case: a signed-in customer downloads one of their own statements.
- Misuse case: a signed-in customer changes the statement number in the URL to retrieve another customer's statement.
- Control: the server checks that the requested statement belongs to the signed-in customer before returning it.
- Test: sign in as test customer A and request a statement belonging to test customer B; the expected result is a refusal and a logged authorization failure.
- Add the test to the automated suite so it runs on every release.
Answer: The misuse case of changing the statement number leads to an object-level authorization test that runs on every release.
Release gates and assurance evidence
A release gate is a checkpoint in the pipeline where results must meet criteria before software moves on: no unresolved critical findings from static analysis, no components with critical known vulnerabilities, all misuse case tests passing, and secrets scanning clean. Gates should be automatic where possible, with a documented exception process for cases where the business accepts a risk temporarily. Exceptions need an owner, a reason, compensating controls and an expiry date.
Assurance evidence for software includes the pipeline configuration showing which tests run, the results for each release, the exceptions granted, code review records and the SBOM. Auditors and customers ask for this evidence, and frameworks such as NIST SP 800-218, OWASP SAMM (Software Assurance Maturity Model) and BSIMM (Building Security In Maturity Model) help organizations measure and improve their secure development practices.
Worked problem
Interpreting tool results
A static analysis tool reports 1,240 findings on a legacy application. The team says it cannot fix them all and wants to switch the tool off. What should the security manager propose?
Show solution
- Triage by severity and confidence, starting with high-severity findings in internet-facing and sensitive code.
- Tune rules that produce known false positives, and record the tuning decisions.
- Set a baseline: existing findings are tracked as technical debt with a reduction plan, while new code must not add new high-severity findings.
- Measure progress quarterly and report the trend.
Answer: Keep the tool, triage and tune, baseline legacy findings with a reduction plan, and gate new code against new high-severity findings.
Worked problem
Evaluating a vendor's secure development claims
A SaaS vendor says its software is secure because it passes an annual penetration test. What further evidence should the buyer request?
Show solution
- Ask how security testing is built into development: code review, SAST, SCA, DAST and secrets scanning.
- Request an SBOM or at least the vendor's process for tracking component vulnerabilities.
- Ask for a secure development attestation or alignment with a framework such as NIST SP 800-218.
- Ask for the most recent penetration test attestation letter and evidence that findings were fixed.
- Include obligations to notify of vulnerabilities and to patch within defined times in the contract.
Answer: An annual test is one data point; request evidence of continuous testing in development, an SBOM, a secure development attestation and contractual obligations.
Common mistakes
MistakeRelying on a single annual penetration test for application security.
InsteadCombine code review, SAST, SCA, DAST or IAST, and periodic penetration tests.
MistakeTurning off a noisy static analysis tool.
InsteadTriage, tune and baseline findings, and gate new code.
MistakeIgnoring third-party components because the team did not write them.
InsteadMaintain an SBOM and track component vulnerabilities and licences.
MistakeWriting only functional tests.
InsteadAdd misuse case tests that check controls stop abuse.
MistakeGranting release exceptions with no expiry.
InsteadGive exceptions an owner, compensating controls and an expiry date.
MistakeTreating overall code coverage as proof of security.
InsteadCheck coverage of security-relevant code such as authorization and input handling.
Summary and key terms
- Security testing belongs at every stage of the life cycle; defects found early cost less to fix.
- Code review checks changes for security flaws using trained reviewers and a consistent checklist.
- SAST, DAST, IAST, SCA, secrets scanning and infrastructure-as-code scanning each cover different risks.
- Fuzzing tests robustness against malformed input, especially in parsers.
- SBOMs inventory components so vulnerabilities and licences can be managed; SPDX and CycloneDX are the main formats.
- Misuse cases, interface tests and coverage analysis check that controls stop unwanted behaviour.
- Release gates enforce criteria, with time-limited, owned exceptions and recorded evidence.
- Shift left
- Moving testing earlier in the life cycle so defects are found sooner.
- Code review
- Examination of source code by someone other than its author.
- SAST
- Static application security testing of code without running it.
- DAST
- Dynamic application security testing of a running application from outside.
- IAST
- Interactive testing through instrumentation inside a running application.
- Software composition analysis
- Identification of third-party components and their vulnerabilities and licences.
- Fuzzing
- Supplying large volumes of unexpected input to find crashes and errors.
- SBOM
- A software bill of materials listing components, versions and relationships.
- Misuse case
- A description of how a feature could be abused, used to design tests of controls.
- Release gate
- A pipeline checkpoint where results must meet criteria before release.
Practice problems
Work each problem on paper first, then reveal the answer to check.
What does shifting left mean?
Show answer
Moving security testing earlier in the life cycle.
What evidence shows that code review took place?
Show answer
Review records in the source control platform linked to each change.
How does SAST differ from DAST?
Show answer
SAST examines code without running it; DAST tests the running application from outside.
What does IAST add?
Show answer
Runtime context from instrumentation inside the application, reducing false positives.
Why is software composition analysis important?
Show answer
Most code in modern applications comes from third-party components.
Name two SBOM formats.
Show answer
SPDX and CycloneDX.
What is a misuse case?
Show answer
A description of how a feature could be abused, leading to a test of the control that should stop it.
Why do defects cluster at interfaces?
Show answer
Each side may assume the other validates input or checks authorization.
What should every release gate exception include?
Show answer
An owner, a reason, compensating controls and an expiry date.
Name a framework for measuring secure development maturity.
Show answer
OWASP SAMM or BSIMM, or NIST SP 800-218 for practices.
Lesson quiz · 5 questions
Score 60% or more to complete this lesson.
Create a free account to save your progress, take quizzes and earn a certificate.