Skip to main content

Good Practices for Writing Secure Code

💡 Practical note:
Many modern static analysis tools and linters - such as ESLint, Pylint, SonarQube, Checkmarx, Semgrep, among others - already include essential security rules by default that cover several of the practices described here.
These rules can (and should) be customised, audited and aligned with the organisation's technical context.
Adopting these tools does not remove the need to define these good practices, but it significantly facilitates their verification and operationalisation.


This document establishes the minimum set of good practices for writing secure code, which must be followed by all development teams and validated during the development, review and release process.

These practices must be integrated into the organisation's technical guidelines and code review routines.


📌 Objectives​

  • Reduce the introduction of common vulnerabilities (e.g. CWE Top 25)
  • Increase the readability, maintainability and security of code
  • Standardise behaviour across teams
  • Integrate security from the very first commit

👥 Who should apply it​

  • Developers: while writing and refactoring code.
  • Technical reviewers (peer reviewers, tech leads): while analysing PRs.
  • Security / AppSec teams: as a cross-cutting validation criterion.

⏱️ When to apply it​

  • Whenever production source code is started or changed.
  • During technical reviews of PRs.
  • In internal audits or security reviews.
  • During the technical onboarding of new developers.

🧱 Essential practices​

  1. Avoid copying code from the internet without validation

    • Justify and review copied snippets (StackOverflow, GitHub, etc.)
    • Validate security and licensing
  2. Separate business logic from presentation logic

    • Minimises the risk of injection (e.g. XSS)
    • Improves testability and security per layer
  3. Avoid code duplication (DRY)

    • Increases traceability
    • Reduces security inconsistencies
  4. Avoid using dangerous or deprecated functions

    • E.g. eval, exec, system, strcpy, innerHTML without sanitisation
    • Replace them with secure alternatives
  5. Use meaningful and expressive names

    • Increases comprehensibility and reduces logic errors
  6. Keep comments useful and up to date

    • Outdated comments lead to critical errors
  7. Remove dead or commented-out code before final commits

    • Obsolete code is a frequent source of security flaws

🚨 Prohibited practices​

  • Use of hardcoded secrets (e.g. tokens, passwords)
  • Inclusion of debug code or console logging in production
  • Direct access to request without validation/sanitisation
  • Query strings built by concatenation
  • Commit of altered dependencies without formal review

✅ How to validate​

These practices must be validated through:

  • Code review checklists (see addon/08-validacoes-codigo.md)
  • Automated linters with mandatory minimum rules (see addon/02-linters-validacoes.md)
  • PRs with mandatory reviewers and semantic annotation (see addon/09-anotacoes-evidencia.md)

🧾 How to evidence it​

Evidence of the application of these practices may be:

  • Presence of an annotation in the code (@sec:checked, @sec:input-validated)
  • Explicit validation in the PR template
  • Linter execution logs in the CI/CD
  • Inclusion in the technical review report

🔄 Link to other practices​

ThemeAssociated file
Linters and automated validationsaddon/02-linters-validacoes.md
Secure dependency managementaddon/03-seguranca-dependencias.md
Code reviews with a checklistaddon/08-validacoes-codigo.md
Traceability in codeaddon/09-anotacoes-evidencia.md
Justification of exceptionsaddon/05-excecoes-e-justificacoes.md

📌 This practice is cross-cutting and must be applied across all of the organisation's technical stacks and languages. Its absence undermines the effectiveness of automated validations and leaves the codebase vulnerable to trivial flaws.