Overview
To reduce security vulnerabilities and improve software quality, secure coding principles must be consistently applied throughout development. These principles ensure that code is not only functional and maintainable but also resilient to misuse, malicious input, and unintended behaviour.
Secure code is the foundation of trustworthy systems. It enables long-term sustainability, rapid feature delivery, and reduced incident response burden.
Key secure coding principles
Principle | Best practice controls |
---|---|
Input validation & output encoding | All user input must be treated as untrusted. Validate early, encode outputs, and avoid dynamic code execution. Apply allow-lists where possible. |
Fail securely | Code should fail gracefully without leaking sensitive information. Error messages must be generic to users and detailed only in logs. |
Authentication & authorisation checks | Ensure all critical functions enforce both identity and permissions. Never assume context or rely solely on front-end checks. |
Secure dependency management | Limit third-party dependencies. Use trusted sources, specify versions explicitly, and automate vulnerability checks (e.g., with Dependabot, Snyk). |
Secrets & configuration management | Never hardcode secrets or credentials. Use environment-specific secrets vaults (e.g., Azure Key Vault, GitHub Secrets). Ensure config files are not stored in public or shared repos. |
Defensive coding & code hygiene | Assume your code will be attacked. Use safe defaults, initialise variables, avoid unsafe functions (e.g., eval , raw SQL). Write clean, modular, well-documented code. |
Logging & monitoring hooks | Include meaningful logs for key events such as authentication attempts, permission errors, and data mutations. Never log passwords or sensitive tokens. |
Memory & resource management | Avoid memory leaks, uncontrolled recursion, or unbounded data processing. Be aware of DoS and resource exhaustion risks. |
Immutable infrastructure & infrastructure as code | Ensure infrastructure changes are applied via code rather than manual edits to enforce consistency and traceability. |
Code review & pairing | Regular peer reviews and optional pairing promote early identification of potential security risks and encourage team-wide knowledge sharing. |
Tools and controls for secure coding
Tool / practice | Purpose |
---|---|
ESLint / Prettier | Linting and formatting for consistent, safe JS/TS code |
SonarQube | Detects code smells, vulnerabilities, and insecure patterns |
GitHub Advanced Security / CodeQL | Automated code scanning and security alerts |
Dependabot / Snyk | Alerts on vulnerable dependencies and suggests patches |
OWASP Secure coding guidelines | Language-specific cheat sheets (e.g., for JavaScript, C#, Python) |
Code review checklists | Include secure coding prompts: input validation, secrets, logging, etc. |
Automated test coverage reports | Ensure high coverage of logic and edge cases |
Secrets detection | Git hooks or scanners to prevent committing sensitive data |
CI/CD quality gates | Prevent merging code that fails security, style, or test checks |
A continuous culture
Secure coding is not a one-off activity—it must be a habitual, team-wide practice. To support this:
- developers should have access to secure coding checklists and OWASP resources
- security champions can guide teams and help interpret threats or trade-offs
- code reviews should be fast but purposeful, supporting mentoring and critical feedback
- teams should be encouraged to refactor and address tech debt, on a continual right-size/right-time basis
- digital applications should be treated as living products - product managers should ensure that operating systems, frameworks, and dependencies remain up to date. Running on outdated software introduces unnecessary and often critical risk to service integrity and security.