Secure Software Development

Building security into every SDLC phase, with secure coding principles, testing methods, software supply chain controls, CI/CD security gates and vulnerability disclosure.

Most application vulnerabilities are design or coding mistakes, and fixing them late is expensive. Secure software development means making security a normal part of how software is specified, written, tested, shipped and maintained, rather than a penetration test bolted on at the end. This page is the defender's view; the attacker's view is in OWASP Top 10 and Application Attacks.

The short DevSecOps note in Security Controls introduces the idea of "shift left"; this page expands it.


Security in Each SDLC Phase

text
Requirements -> Design -> Implementation -> Testing -> Deployment -> Maintenance
     |            |            |              |           |             |
 security     threat       secure coding   SAST/DAST   hardened     patching,
 & privacy    modelling    code review     SCA, fuzz   config,      monitoring,
 reqs         arch review  secrets scan    pen test    signed       disclosure,
                                                       artifacts    retirement

PhaseSecurity activities
RequirementsIdentify data sensitivity, regulatory needs, abuse cases ("how would someone misuse this?"), authentication/authorisation needs. See Security Requirements.
DesignThreat modelling (STRIDE etc.), secure architecture patterns, trust boundaries, data flow review, choose vetted libraries and frameworks. See Security Architecture Principles.
ImplementationSecure coding standards, peer code review, IDE linters, pre-commit secret scanning.
TestingSAST, DAST, IAST, SCA, fuzzing, security unit tests, pen test before major releases.
DeploymentHardened images and configuration, secrets injected at runtime, signed artifacts, least-privilege deploy identities. See System Hardening.
MaintenanceDependency updates, patching, monitoring, incident handling, vulnerability disclosure, secure decommissioning. See Vulnerability and Patch Management.

Treat changes through the process described in Change Management: reviewed, tested, reversible.


Secure Coding Principles

PrincipleWhat it meansDefends against
Validate inputTreat all input (forms, headers, files, APIs, other services) as untrusted; validate type, length, range and format with an allow-listInjection, path traversal, file upload abuse
Encode outputEncode for the context it lands in (HTML, attribute, JS, URL, SQL)Cross-site scripting
Parameterised queriesKeep data separate from commands; never build SQL or shell strings by concatenationSQL injection, command injection
Least privilegeApp accounts, database users and service tokens get only what they needLimits blast radius of any bug
Fail securely, handle errorsDeny on error; show generic messages to users, log detail server-side; never leak stack traces or secretsInformation disclosure
Strong authn/authzUse proven libraries; check authorisation on every request on the server sideBroken access control, IDOR
Secrets managementNo credentials in source, images or logs; use a secrets manager and rotateCredential leaks
Use vetted cryptoStandard libraries and algorithms, never home-made; see Cryptographic SolutionsWeak or broken cryptography
Defence in depthSeveral independent controls, not one filterSingle control failure
Minimise attack surfaceRemove unused features, endpoints, dependencies and debug modesReduces exposure

Example of the most important fix:

python
# Vulnerable: attacker input becomes part of the SQL command
cur.execute("SELECT * FROM users WHERE name = '" + name + "'")

# Safe: parameterised, data can never change the query structure
cur.execute("SELECT * FROM users WHERE name = %s", (name,))


Security Testing Methods

MethodHow it worksStrengthLimitation
Code reviewHumans read changes, ideally with a security checklistFinds logic and design flawsDepends on reviewer skill
SAST (static)Analyses source or bytecode without running itEarly, in the IDE/CI, pinpoints the lineFalse positives, misses runtime/config issues
DAST (dynamic)Probes the running app from outside like an attackerFinds real exploitable issues, language-agnosticLate, limited code coverage
IAST (interactive)Agent inside the running app observes testsAccurate, shows code pathNeeds instrumentation and good test traffic
SCA (composition analysis)Matches dependencies against known vulnerabilities and licencesCatches vulnerable librariesOnly known issues
FuzzingSends malformed or random input to find crashesFinds parser and memory bugsNeeds harness and time
Penetration testAuthorised manual attack, see Penetration Testing MethodologyChains issues like a real attackerPoint-in-time, costly

No single method is enough; combine them. Findings feed vulnerability management and are prioritised by exploitability and impact, not scanner severity alone. See Vulnerability Scanning for scanner concepts.


Software Supply Chain Security

Modern applications are mostly third-party code. An attacker who compromises a dependency, build system or update channel reaches every consumer.

ThreatControl
Vulnerable dependencySCA scanning, timely updates
Typosquatting / dependency confusion (malicious package with a similar or internal-looking name)Verify package names, use private registry with scoped namespaces, allow-list sources
Malicious or hijacked maintainer releasePin versions and use lock files with hashes; review upgrade diffs; delay adoption of brand-new releases
Compromised build systemIsolated, ephemeral build runners; protect pipeline credentials; two-person review on pipeline changes
Tampered artifactSigned builds and provenance attestations; verify signatures at deploy
Unknown contentsGenerate an SBOM (software bill of materials: machine-readable list of components and versions, e.g. SPDX or CycloneDX) for every release, so you can answer "are we affected?" within minutes when a new vulnerability is announced

Regulation increasingly expects this; see Cyber Resilience Act.


CI/CD Pipeline Security and DevSecOps

DevSecOps automates security checks as gates in the pipeline so feedback arrives while the developer still has context (shift left).

text
commit -> pre-commit hooks -> build -> test -> package -> deploy -> run
            secret scan       SAST     DAST    sign      policy    monitor
            lint              SCA      unit    SBOM      checks    runtime
                              IaC scan         image     approval  protection
                                               scan

Typical gates:

  • Block merge on secrets found, critical SAST findings or known-exploited dependency vulnerabilities (with a documented exception process).
  • Scan infrastructure-as-code and container images before deploy.
  • Require reviewed pull requests, protected branches and signed commits.
  • Deploy with short-lived credentials (federated identity), not static keys stored in CI variables.
  • Separate duties: the person who writes code cannot alone push it to production.

Tune gates to keep false positives low; a noisy gate gets bypassed. The pipeline itself is a high-value target and needs the same hardening as production (see Cloud Security).


Vulnerability Disclosure and Bug Bounty

  • Security.txt / VDP: publish a security contact (/.well-known/security.txt) and a vulnerability disclosure policy stating how to report, scope, safe-harbour for good-faith research and expected response times.
  • Coordinated disclosure: reporter and vendor agree a fix window (commonly 90 days) before public details.
  • Bug bounty: a paid programme (often via a platform) rewarding valid reports within a defined scope and rules. Needs triage capacity; run a VDP first.
  • Track reports like any vulnerability: acknowledge, reproduce, fix, release advisory, credit the reporter. Use CVE IDs where applicable.

Maturity Frameworks (named only)

  • NIST SSDF (Secure Software Development Framework)
  • OWASP SAMM (Software Assurance Maturity Model)
  • BSIMM (Building Security In Maturity Model)

See Security Frameworks for how frameworks fit together.


Key Points

  • Fix problems early: requirements and design flaws cost most when found in production.
  • Core coding defences: validate input, encode output, parameterise queries, least privilege, safe error handling, no hard-coded secrets.
  • Combine SAST, DAST, IAST, SCA, fuzzing, code review and periodic pen tests.
  • Know what you ship: SBOM, pinned dependencies, signed builds.
  • Automate security gates in CI/CD, and secure the pipeline itself.
  • Give outsiders a clear way to report vulnerabilities.