From bb8ac0b5af4604148840dc4d5a3b9246fa38cb51 Mon Sep 17 00:00:00 2001 From: Ali-Yazdani Date: Sun, 28 Jun 2026 00:07:38 +0200 Subject: [PATCH] docs: restructure guideline and expand content for 2025/2026 --- .claude/settings.local.json | 12 + README.md | 26 +- current-version/0-Intro/0-1-Intro.md | 97 +++++-- current-version/0-Intro/0-2-Overview.md | 144 +++++----- .../0-Intro/0-3-Frameworks-and-Standards.md | 102 +++++++ .../1-1-1-Security-champions.md | 124 +++++++++ .../1-1-2-Roles-and-Responsibilities.md | 137 +++++++++ .../1-2-Training/1-2-1-Secure-coding.md | 159 ++++++++++- .../1-2-Training/1-2-2-Security-CICD.md | 130 ++++++++- .../1-2-3-Security-culture-and-awareness.md | 108 ++++++++ .../2-1-Design/2-1-1-Threat-modeling.md | 207 ++++++-------- .../2-1-2-Secure-design-and-requirements.md | 117 ++++++++ .../2-2-1-Pre-commit/2-2-1-1-Pre-commit.md | 157 +++++++++-- .../2-2-1-2-Secrets-Management.md | 206 +++++++++++--- .../2-2-1-Pre-commit/2-2-1-3-Linting-code.md | 150 +++++++--- .../2-2-1-4-Repository-Hardening.md | 262 +++++++++++++++--- .../2-2-2-IDE-and-AI-assisted-development.md | 146 ++++++++++ ...1-1-Static-Application-Security-Testing.md | 174 ++++++++++-- .../2-3-2-1-Software-Composition-Analysis.md | 194 +++++++++++++ .../2-3-3-1-Container-Scanning.md | 205 ++++++++++++-- .../2-3-3-2-Container-Hardening.md | 138 +++++++-- ...2-3-4-1-Infrastructure-as-Code-Scanning.md | 228 +++++++++++++++ .../2-3-Build/2-3-5-Security-Gates.md | 103 ++++++- .../2-3-6-1-SBOM.md | 117 ++++++++ ...2-3-6-2-Artifact-Signing-and-Provenance.md | 131 +++++++++ .../2-3-6-3-CICD-Pipeline-Security.md | 150 ++++++++++ ...nteractive-Application-Security-Testing.md | 170 +++++++++--- ...-2-Dynamic-Application-Security-Testing.md | 231 +++++++++++++-- .../2-4-3-Mobile-Application-Security-Test.md | 203 +++++++++++++- .../2-Process/2-4-Test/2-4-4-API-Security.md | 131 ++++++++- .../2-4-Test/2-4-5-Misconfiguration-Check.md | 116 +++++++- .../2-Process/2-5-Release/2-5-1-Release.md | 123 +++++++- .../2-Process/2-6-Deploy/2-6-1-Deploy.md | 135 ++++++++- .../2-7-1-Cloud-Native-Security.md | 132 ++++++++- .../2-7-2-Logging-and-Monitoring.md | 141 +++++++++- .../2-Process/2-7-Operate/2-7-3-Pentest.md | 164 ++++++----- .../2-7-4-Vulnerability-Management.md | 112 +++++++- .../2-7-Operate/2-7-5-VDP-and-Bug-bounty.md | 131 +++++++++ .../2-7-6-Breach-and-attack-simulation.md | 109 +++++++- .../3-1-1-Compliance-Auditing.md | 128 +++++++++ .../3-1-2-Policy-as-code.md | 208 ++++++++++++-- .../3-1-3-Security-benchmarking.md | 137 ++++++++- .../3-Governance/3-2-Data-protection.md | 127 +++++++-- .../3-3-1-Tracking-maturities.md | 116 ++++++++ ...tral-vulnerability-management-dashboard.md | 117 ++++++-- .../3-Governance/3-3-Reporting/3-3-3-ASPM.md | 193 +++++++++++++ .../3-4-AI-Governance-and-Risk.md | 131 +++++++++ current-version/README.md | 95 ++++--- doc-utilities/scripts/toc.md | 20 +- old-versions/V0.3/0-Intro/0-1-Intro.md | 25 ++ old-versions/V0.3/0-Intro/0-2-Overview.md | 106 +++++++ .../1-1-1-Security-champions.md | 1 + .../1-2-Training/1-2-1-Secure-coding.md | 1 + .../1-2-Training/1-2-2-Security-CICD.md | 1 + .../2-1-Design/2-1-1-Threat-modeling.md | 168 +++++++++++ .../2-2-1-Pre-commit/2-2-1-1-Pre-commit.md | 34 +++ .../2-2-1-2-Secrets-Management.md | 66 +++++ .../2-2-1-Pre-commit/2-2-1-3-Linting-code.md | 60 ++++ .../2-2-1-4-Repository-Hardening.md | 51 ++++ ...1-1-Static-Application-Security-Testing.md | 52 ++++ .../2-3-2-1-Software-Composition-Analysis.md | 0 .../2-3-3-1-Container-Scanning.md | 52 ++++ .../2-3-3-2-Container-Hardening.md | 45 +++ .../2-3-1-3-Infastructure-as-Code-Scanning.md | 0 .../2-3-Build/2-3-5-Security-Gates.md | 3 + ...nteractive-Application-Security-Testing.md | 67 +++++ ...-2-Dynamic-Application-Security-Testing.md | 43 +++ .../2-4-3-Mobile-Application-Security-Test.md | 3 + .../2-Process/2-4-Test/2-4-4-API-Security.md | 3 + .../2-4-Test/2-4-5-Misconfiguration-Check.md | 3 + .../2-Process/2-5-Release/2-5-1-Release.md | 3 + .../V0.3/2-Process/2-6-Deploy/2-6-1-Deploy.md | 3 + .../2-7-1-Cloud-Native-Security.md | 3 + .../2-7-2-Logging-and-Monitoring.md | 3 + .../2-Process/2-7-Operate/2-7-3-Pentest.md | 98 +++++++ .../2-7-4-Vulnerability-Management.md | 3 + .../2-7-6-Breach-and-attack-simulation.md | 3 + .../3-1-1-Compliance-Auditing.md | 1 + .../3-1-2-Policy-as-code.md | 39 +++ .../3-1-3-Security-benchmarking.md | 1 + .../V0.3/3-Governance/3-2-Data-protection.md | 37 +++ .../3-3-1-Tracking-maturities.md | 1 + ...tral-vulnerability-management-dashboard.md | 55 ++++ old-versions/V0.3/README.md | 73 +++++ .../V0.3/assets/images/Cred scanning.png | Bin 0 -> 117131 bytes .../V0.3/assets/images/Dev-process.png | Bin 0 -> 23251 bytes .../assets/images/DevOps-vs-DevSecOps.png | Bin 0 -> 110261 bytes old-versions/V0.3/assets/images/DevSecOps.png | Bin 0 -> 30721 bytes .../V0.3/assets/images/Pipeline-view.png | Bin 0 -> 8017024 bytes .../V0.3/assets/images/Static scanning.png | Bin 0 -> 102017 bytes .../images/container-security-pipeline.png | Bin 0 -> 84845 bytes .../V0.3/assets/images/dast_scanning.png | Bin 0 -> 17602 bytes .../V0.3/assets/images/devsecops-pillars.png | Bin 0 -> 100476 bytes .../V0.3/assets/images/iast_analysis.png | Bin 0 -> 17538 bytes .../V0.3/assets/images/pre-commit.png | Bin 0 -> 525710 bytes .../V0.3/assets/images/sast_scanning.png | Bin 0 -> 16654 bytes 96 files changed, 7301 insertions(+), 700 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 current-version/0-Intro/0-3-Frameworks-and-Standards.md create mode 100644 current-version/1-People/1-1-Shape-the-team/1-1-2-Roles-and-Responsibilities.md create mode 100644 current-version/1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md create mode 100644 current-version/2-Process/2-1-Design/2-1-2-Secure-design-and-requirements.md create mode 100644 current-version/2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md create mode 100644 current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md create mode 100644 current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md create mode 100644 current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md create mode 100644 current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md create mode 100644 current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md create mode 100644 current-version/2-Process/2-7-Operate/2-7-5-VDP-and-Bug-bounty.md create mode 100644 current-version/3-Governance/3-3-Reporting/3-3-3-ASPM.md create mode 100644 current-version/3-Governance/3-4-AI-Governance-and-Risk.md create mode 100644 old-versions/V0.3/0-Intro/0-1-Intro.md create mode 100644 old-versions/V0.3/0-Intro/0-2-Overview.md create mode 100644 old-versions/V0.3/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md create mode 100644 old-versions/V0.3/1-People/1-2-Training/1-2-1-Secure-coding.md create mode 100644 old-versions/V0.3/1-People/1-2-Training/1-2-2-Security-CICD.md create mode 100644 old-versions/V0.3/2-Process/2-1-Design/2-1-1-Threat-modeling.md create mode 100644 old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md create mode 100644 old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md create mode 100644 old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md create mode 100644 old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md create mode 100644 old-versions/V0.3/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md rename {current-version => old-versions/V0.3}/2-Process/2-3-Build/2-3-2-Software Composition Analysis/2-3-2-1-Software-Composition-Analysis.md (100%) create mode 100644 old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md create mode 100644 old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md rename {current-version => old-versions/V0.3}/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security/2-3-1-3-Infastructure-as-Code-Scanning.md (100%) create mode 100644 old-versions/V0.3/2-Process/2-3-Build/2-3-5-Security-Gates.md create mode 100644 old-versions/V0.3/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md create mode 100644 old-versions/V0.3/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md create mode 100644 old-versions/V0.3/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md create mode 100644 old-versions/V0.3/2-Process/2-4-Test/2-4-4-API-Security.md create mode 100644 old-versions/V0.3/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md create mode 100644 old-versions/V0.3/2-Process/2-5-Release/2-5-1-Release.md create mode 100644 old-versions/V0.3/2-Process/2-6-Deploy/2-6-1-Deploy.md create mode 100644 old-versions/V0.3/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md create mode 100644 old-versions/V0.3/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md create mode 100644 old-versions/V0.3/2-Process/2-7-Operate/2-7-3-Pentest.md create mode 100644 old-versions/V0.3/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md create mode 100644 old-versions/V0.3/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md create mode 100644 old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md create mode 100644 old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md create mode 100644 old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md create mode 100644 old-versions/V0.3/3-Governance/3-2-Data-protection.md create mode 100644 old-versions/V0.3/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md create mode 100644 old-versions/V0.3/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md create mode 100644 old-versions/V0.3/README.md create mode 100644 old-versions/V0.3/assets/images/Cred scanning.png create mode 100644 old-versions/V0.3/assets/images/Dev-process.png create mode 100644 old-versions/V0.3/assets/images/DevOps-vs-DevSecOps.png create mode 100644 old-versions/V0.3/assets/images/DevSecOps.png create mode 100644 old-versions/V0.3/assets/images/Pipeline-view.png create mode 100644 old-versions/V0.3/assets/images/Static scanning.png create mode 100644 old-versions/V0.3/assets/images/container-security-pipeline.png create mode 100644 old-versions/V0.3/assets/images/dast_scanning.png create mode 100644 old-versions/V0.3/assets/images/devsecops-pillars.png create mode 100644 old-versions/V0.3/assets/images/iast_analysis.png create mode 100644 old-versions/V0.3/assets/images/pre-commit.png create mode 100644 old-versions/V0.3/assets/images/sast_scanning.png diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..04eda61 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,12 @@ +{ + "permissions": { + "allow": [ + "WebSearch", + "Bash(set -e)", + "Bash(git mv *)", + "Bash(mkdir -p current-version/0-Intro current-version/1-People/1-1-Shape-the-team current-version/1-People/1-2-Training current-version/2-Process/2-1-Design current-version/2-Process/2-2-Develop/2-2-1-Pre-commit current-version/2-Process/2-3-Build/2-3-1-Static-Analysis current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis current-version/2-Process/2-3-Build/2-3-3-Container-Security current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security current-version/2-Process/2-4-Test current-version/2-Process/2-5-Release current-version/2-Process/2-6-Deploy current-version/2-Process/2-7-Operate current-version/3-Governance/3-1-Compliance-Auditing current-version/3-Governance/3-3-Reporting)", + "Bash(cp -R \"old-versions/V0.3/assets\" \"current-version/assets\")", + "Bash(python3 doc-utilities/scripts/toc-generator.py)" + ] + } +} diff --git a/README.md b/README.md index eb91fc6..156a495 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ At first, we consider implementing the following steps in a basic pipeline: - SCA (Software Composition Analysis) - SAST (Static Application Security Test) - IaC Scanning (Scanning Terraform, HelmChart code to find misconfiguration) +- Software supply-chain security (SBOM, artifact signing and provenance, CI/CD pipeline security) - IAST (Interactive Application Security Testing) - API Security - DAST (Dynamic Application Security Test) @@ -32,6 +33,7 @@ At first, we consider implementing the following steps in a basic pipeline: - Infrastructure scanning - Continuous Scanning from other tools - Compliance check +- AI/LLM security and AI governance (securing AI-assisted development and AI-powered features) We can customize the steps of our pipeline according to our Software Development Life Cycle (SDLC) or software architecture and add automation progressively if we are starting. For instance, we can switch from SAST/DAST to a regular test suite with built-in security controls or add an audit script checking for known vulnerable dependencies. @@ -46,32 +48,41 @@ However, when using CI/CD tools to provide automation, keep in mind that the too - [0-Intro](current-version/0-Intro) - [0-1-Intro](current-version/0-Intro/0-1-Intro.md) - [0-2-Overview](current-version/0-Intro/0-2-Overview.md) + - [0-3-Frameworks-and-Standards](current-version/0-Intro/0-3-Frameworks-and-Standards.md) - [1-People](current-version/1-People) - [1-1-Shape-the-team](current-version/1-People/1-1-Shape-the-team) - [1-1-1-Security-champions](current-version/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md) + - [1-1-2-Roles-and-Responsibilities](current-version/1-People/1-1-Shape-the-team/1-1-2-Roles-and-Responsibilities.md) - [1-2-Training](current-version/1-People/1-2-Training) - [1-2-1-Secure-coding](current-version/1-People/1-2-Training/1-2-1-Secure-coding.md) - [1-2-2-Security-CICD](current-version/1-People/1-2-Training/1-2-2-Security-CICD.md) + - [1-2-3-Security-culture-and-awareness](current-version/1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md) - [2-Process](current-version/2-Process) - [2-1-Design](current-version/2-Process/2-1-Design) - [2-1-1-Threat-modeling](current-version/2-Process/2-1-Design/2-1-1-Threat-modeling.md) + - [2-1-2-Secure-design-and-requirements](current-version/2-Process/2-1-Design/2-1-2-Secure-design-and-requirements.md) - [2-2-Develop](current-version/2-Process/2-2-Develop) - [2-2-1-Pre-commit](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit) - [2-2-1-1-Pre-commit](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md) - [2-2-1-2-Secrets-Management](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md) - [2-2-1-3-Linting-code](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md) - [2-2-1-4-Repository-Hardening](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md) + - [2-2-2-IDE-and-AI-assisted-development](current-version/2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md) - [2-3-Build](current-version/2-Process/2-3-Build) - - [2-3-5-Security-Gates](current-version/2-Process/2-3-Build/2-3-5-Security-Gates.md) - [2-3-1-Static-Analysis](current-version/2-Process/2-3-Build/2-3-1-Static-Analysis) - [2-3-1-1-Static-Application-Security-Testing](current-version/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md) - - [2-3-2-Software Composition Analysis](current-version/2-Process/2-3-Build/2-3-2-Software Composition Analysis) - - [2-3-2-1-Software-Composition-Analysis](current-version/2-Process/2-3-Build/2-3-2-Software Composition Analysis/2-3-2-1-Software-Composition-Analysis.md) + - [2-3-2-Software-Composition-Analysis](current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis) + - [2-3-2-1-Software-Composition-Analysis](current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md) - [2-3-3-Container-Security](current-version/2-Process/2-3-Build/2-3-3-Container-Security) - [2-3-3-1-Container-Scanning](current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md) - [2-3-3-2-Container-Hardening](current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md) - - [2-3-4-Infrastructure as Code Security](current-version/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security) - - [2-3-1-3-Infastructure-as-Code-Scanning](current-version/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security/2-3-1-3-Infastructure-as-Code-Scanning.md) + - [2-3-4-Infrastructure-as-Code-Security](current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security) + - [2-3-4-1-Infrastructure-as-Code-Scanning](current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md) + - [2-3-5-Security-Gates](current-version/2-Process/2-3-Build/2-3-5-Security-Gates.md) + - [2-3-6-Supply-Chain-Security](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security) + - [2-3-6-1-SBOM](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md) + - [2-3-6-2-Artifact-Signing-and-Provenance](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md) + - [2-3-6-3-CICD-Pipeline-Security](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md) - [2-4-Test](current-version/2-Process/2-4-Test) - [2-4-1-Interactive-Application-Security-Testing](current-version/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md) - [2-4-2-Dynamic-Application-Security-Testing](current-version/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md) @@ -87,16 +98,19 @@ However, when using CI/CD tools to provide automation, keep in mind that the too - [2-7-2-Logging-and-Monitoring](current-version/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md) - [2-7-3-Pentest](current-version/2-Process/2-7-Operate/2-7-3-Pentest.md) - [2-7-4-Vulnerability-Management](current-version/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md) + - [2-7-5-VDP-and-Bug-bounty](current-version/2-Process/2-7-Operate/2-7-5-VDP-and-Bug-bounty.md) - [2-7-6-Breach-and-attack-simulation](current-version/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md) - [3-Governance](current-version/3-Governance) - - [3-2-Data-protection](current-version/3-Governance/3-2-Data-protection.md) - [3-1-Compliance-Auditing](current-version/3-Governance/3-1-Compliance-Auditing) - [3-1-1-Compliance-Auditing](current-version/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md) - [3-1-2-Policy-as-code](current-version/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md) - [3-1-3-Security-benchmarking](current-version/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md) + - [3-2-Data-protection](current-version/3-Governance/3-2-Data-protection.md) - [3-3-Reporting](current-version/3-Governance/3-3-Reporting) - [3-3-1-Tracking-maturities](current-version/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md) - [3-3-2-Central-vulnerability-management-dashboard](current-version/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md) + - [3-3-3-ASPM](current-version/3-Governance/3-3-Reporting/3-3-3-ASPM.md) + - [3-4-AI-Governance-and-Risk](current-version/3-Governance/3-4-AI-Governance-and-Risk.md) --- diff --git a/current-version/0-Intro/0-1-Intro.md b/current-version/0-Intro/0-1-Intro.md index 376a71d..2066a98 100644 --- a/current-version/0-Intro/0-1-Intro.md +++ b/current-version/0-Intro/0-1-Intro.md @@ -1,25 +1,90 @@ -# Introduction to the OWASP DevSecOps Guideline +# Introduction -The OWASP DevSecOps Guideline explains how we can transition from a traditional approach to achieving security that starts with requirements and ends with security testing to an approach that brings together Development, Security, and Operations throughout the software lifecycle -- a "DevSecOps" approach. +The OWASP DevSecOps Guideline explains how to build and operate a secure software delivery pipeline using best practices and a curated, vendor-neutral set of tools. The aim is to help organizations of any size that run a DevOps pipeline introduce security controls without slowing delivery, and to promote a **shift-left** (and increasingly **shift-everywhere**) security culture across the whole development lifecycle. -This project's goal is to help companies of any size to add security to their DevOps pipeline and culture. There is no one **right** way to do DevSecOps, so it's important to stay focused. +The ideal goal of this guideline is simple: -DevSecOps strives to **"produce demonstrably secure code"** by: +> **Detect security issues — whether design flaws or application vulnerabilities — as early and as cheaply as possible, and keep detecting them continuously.** -- leveraging automation to create short feedback loops to developers -- breaking down the silos between development, security, and operations -- breaking down security work into small pieces to create flow -- making decisions based on threat intelligence from operations -- establishing a culture of security experimentation and learning +DevSecOps is about embedding security *into* DevOps. To keep up with the pace of CI/CD, security cannot be a gate at the end; it has to be injected early into how software is designed, written, built, tested, and operated, and then continuously validated in production. -There are tools to support security processes across the software development lifecycle. Every company should have processes in place to ensure: +## Why DevSecOps — the cost of waiting -- **Custom Code Security** - your custom code has the right defenses and is free from vulnerabilities, including applications, APIs, serverless, mobile, infrastructure as code, etc... -- **Supply Chain Security** - your platform, framework, libraries, containers, and other components -- **Runtime Protection** - you detect attacks on your software and prevent them from being exploited +The earlier a vulnerability is found, the cheaper it is to fix. IBM's Systems Science Institute research consistently shows that a defect found in the design phase costs roughly 6× less to fix than one found in implementation, and 100× less than one found in production. These ratios are not exact — they depend on the defect type and system — but the directional truth holds across the industry: late discovery is expensive. -If you do these three processes well, you will be in relatively good shape in terms of application security. In this document, we will explore a variety of automated solutions that can help you implement these three processes. +But there is a second, harder cost that the numbers do not fully capture: a vulnerability in production that is *exploited* does not just carry a remediation cost — it carries breach costs, regulatory penalties, reputational damage, customer harm, and executive accountability. The 2020 SolarWinds supply-chain attack, the 2021 Log4Shell disclosure affecting millions of systems, and the 2019 Capital One breach (via a misconfigured WAF/SSRF) all share a common thread: the exploit path existed because security was not a continuous concern throughout delivery. -The goal is not to use all of the tools in your pipeline. The goal is to ensure secure code emerges from your pipeline. You need to pick and choose the tools that are effective with your organization's people, process, technology, and culture. You will very likely want to use each tool for what it is best at, rather than repeating all tests with all tools. Of course, every software development organization is different and you are free to select tools and the exact location where you want to implement the tools. +Traditional security — a penetration test weeks before release, a security team that reviews code on request — cannot keep up with teams that ship multiple times a day. DevSecOps resolves this by automating what can be automated, making security feedback immediate, and building shared ownership so risk decisions happen at the right level. -![Secure Pipeline](/current-version/assets/images/Pipeline-view.png) +## How this guideline is organized + +This version is structured around the three core pillars of DevSecOps: + +- **People** — the teams, roles, culture, and training that make secure delivery possible. +- **Process** — the security activities woven into every stage of the software development lifecycle. +- **Governance** — the oversight, compliance, measurement, and reporting that keep the program accountable and improving. + +Under **Process**, the product development lifecycle is divided into seven stages, with security controls mapped to each: + +- **Design** — threat modeling, secure-by-design, security requirements. +- **Develop** — pre-commit hooks, secrets management, linting, repository hardening, securing the AI-assisted inner loop. +- **Build** — SAST, SCA, container security, IaC scanning, security gates, and software supply-chain security (SBOM, signing/provenance, pipeline security). +- **Test** — IAST, DAST, mobile app testing, API security, misconfiguration checks. +- **Release** — final sign-off, signed and attested artifacts. +- **Deploy** — admission control, GitOps, progressive delivery. +- **Operate** — cloud-native runtime security, logging and monitoring, pentesting, vulnerability management, disclosure programs, and breach-and-attack simulation. + +You can customize these stages to match your own SDLC and architecture, and add automation progressively as your maturity grows. + +## What DevSecOps is NOT + +Understanding the common misconceptions is as important as knowing the definition: + +- **DevSecOps is not "security team in the pipeline"** — adding security engineers to approve every PR does not scale. The goal is to give developers the tools, training, and context to make security decisions themselves, with the security team acting as an enabler and escalation path, not a gatekeeper. +- **DevSecOps is not tool procurement** — buying a SAST, SCA, and DAST tool without a triage process, clear ownership, and remediation SLAs creates alert fatigue and false confidence. Tools are enablers; process and culture are the program. +- **DevSecOps is not a one-time project** — there is no "done." The threat landscape, your architecture, your dependencies, and your regulatory obligations all change continuously. DevSecOps is a continuous practice, not a migration. +- **DevSecOps is not compliance** — passing an audit is a floor, not a ceiling. Compliance frameworks describe minimum bars against known risks; a real-world adversary does not follow the framework. Design for adversaries, not just auditors. +- **DevSecOps is not just CI/CD** — the pipeline is important, but threat modeling happens at design, culture happens in teams, runtime security happens in production, and vulnerability disclosure happens at the boundary with the outside world. The pipeline is one layer of a much broader system. + +## A note on the pipeline itself + +CI/CD is a powerful entry point for security automation, but the build and automation tooling is also part of your attack surface. Compromised pipelines, leaked tokens, and poisoned dependencies are now among the most damaging attack vectors — the SolarWinds, Codecov, and XZ Utils incidents all illustrate how the build and supply chain can be abused to reach production at scale. This guideline therefore treats **securing the pipeline** as a first-class concern alongside securing the application. + +## How to use this guideline + +Different audiences will find different entry points most useful: + +**If you are a developer or engineer:** +Start with the [Develop](../2-Process/2-2-Develop) stage, specifically pre-commit hooks and secrets management — the controls you can implement in your own workflow today. Then read the [Build](../2-Process/2-3-Build) stage for what your CI pipeline should enforce. Use the [Threat Modeling](../2-Process/2-1-Design/2-1-1-Threat-modeling.md) page when you are designing a new feature or service. + +**If you are a security engineer or AppSec lead:** +Start with the [Overview](0-2-Overview.md) for a full pipeline view, then use the [Frameworks and Standards](0-3-Frameworks-and-Standards.md) page to map this guideline to your regulatory or maturity framework requirements. Use the [Governance](../3-Governance) section to build a reporting and measurement program. + +**If you are an engineering manager or CISO:** +Start with the [Maturity levels](#maturity-levels--where-to-start) table below and the [Tracking Maturities](../3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md) page. The [People](../1-People) section covers the organizational structures (security champions, roles) that make the program sustainable. + +## Common anti-patterns to avoid + +- **Security as a gate at the end** — running a pentest or DAST scan as the sole security activity before release does not scale, finds issues too late, and creates a bottleneck. Gates are necessary but not sufficient. +- **Tool sprawl without process** — buying or deploying many scanners without a clear triage, ownership, and remediation process generates noise and alert fatigue that causes teams to ignore findings entirely. +- **Centralized security ownership** — a small security team that "owns" security and must review everything becomes a bottleneck and a single point of failure. Shared ownership, supported by tooling and champions, is the goal. +- **Treating compliance as security** — passing an audit is not the same as being secure. Compliance is a floor, not a ceiling; design for real-world adversaries, not just checkbox controls. +- **Ignoring developer experience** — security tooling that is slow, noisy, or hard to use gets disabled or routed around. Developer experience is a security concern. + +## Maturity levels — where to start + +| Stage | What to focus on | +|---|---| +| Starting out | Secrets scanning in CI, SCA for known CVEs, basic branch protection, OWASP Top 10 awareness training | +| Developing | SAST in pull requests, IaC scanning, security gates on high/critical findings, security champions program | +| Maturing | Container hardening, SBOM generation, threat modeling, DAST, vulnerability management SLAs | +| Advanced | Supply-chain signing and provenance (SLSA), ASPM, BAS, runtime detection-as-code, AI/ML security | + +## Where to start + +- [OWASP Proactive Controls](https://owasp.org/www-project-proactive-controls/) lists the top security controls every developer should implement while coding. +- [OWASP Software Assurance Maturity Model (SAMM)](https://owaspsamm.org/model/) helps you decide what to prioritize according to your maturity level. +- The [Frameworks and Standards](0-3-Frameworks-and-Standards.md) page maps how SSDF, SAMM, DSOMM, and SLSA fit together with this guideline. +- The [Overview](0-2-Overview.md) page lists a recommended progression of controls to introduce into a pipeline. + +If you need earlier editions, see the [old-versions](../../old-versions/) directory. diff --git a/current-version/0-Intro/0-2-Overview.md b/current-version/0-Intro/0-2-Overview.md index b3fc2e0..a5f37dc 100644 --- a/current-version/0-Intro/0-2-Overview.md +++ b/current-version/0-Intro/0-2-Overview.md @@ -1,106 +1,94 @@ -# DevSecOps Intro +# Overview -Today, DevOps is empowering any organizations to deploy changes to production environments at blazing rates. -Since time to deliver is so important feature during this process, the main question for a security person is -"How I can secure this process?" or "How much our deliverable products are secure?". -In this regard, we can embed some security-related steps entire our DevOps process to perform some automated tests. -So considering the DevSecOps or secure DevOps culture helps us to promote the shift-left security strategy in our company, -at least in the tech department. +## From DevOps to DevSecOps -## What's the Shift-left security strategy? +DevOps unified development and operations to deliver software faster and more reliably through automation, continuous integration, and continuous delivery. **DevSecOps** extends that model by making security a shared responsibility integrated into every phase, rather than a separate audit performed at the end. -As a simple definition, the shift-left security strategy is a way or solution to embedding security as a part of our development process -and consider security from the inception steps of application or system design. -In other words, security is responsible for everyone who works in the software development and operating process. -Of course, security is a profession and we need highly skilled people to play security-related roles; -but in this approach, any designer, software architecture, developer, DevOps engineer, and ... together with security guys have liability about security. +The driving idea is **shift-left**: move security feedback as close as possible to the moment code is written, when issues are cheapest to fix. In practice, mature programs now **shift everywhere** — running fast, low-friction checks early *and* deeper validation continuously through build, test, deploy, and runtime. -## Dev+Sec+Ops +The difference is not just where security happens, but *who owns it*: DevSecOps moves security ownership from a separate team to the whole engineering organization, supported by automation, tooling, and a champions network. -![DevSecOps Venn Diagram](/current-version/assets/images/DevSecOps.png) +## What to add to a pipeline -Suppose that these 3 different areas for covering each other is something like the image, -so in conclusion with the above words, we need to implement some tools and working on promoting a DevSecOps culture too. +A reasonable progression of controls to introduce: -As Shannon Lietz - founder at DevSecOps foundation - said: +- **Secrets scanning** — find credentials before they are committed or merged. Tools like TruffleHog and Gitleaks run in pre-commit hooks or CI with near-zero false-positive rates on high-entropy strings and known secret formats. A single leaked cloud credential can compromise an entire environment within minutes of appearing in a public repo. +- **SCA (Software Composition Analysis)** — detect vulnerable and malicious open-source dependencies. SCA tools map your dependency tree against CVE databases and increasingly flag malicious packages (typosquatting, dependency confusion) and license issues. Log4Shell (2021) demonstrated what a critical CVE in a transitive dependency can do at scale: hundreds of millions of systems affected by a library most of their developers had never heard of. +- **SAST (Static Application Security Testing)** — analyze first-party source code for flaws. Effective SAST runs in the pull request and reports only *new* findings against the base branch so developers see only what they introduced. +- **IaC scanning** — find misconfigurations in Terraform, Helm, Kubernetes manifests, Ansible, etc. These flaws — overly permissive IAM, unencrypted storage, open network rules — are frequently the easiest path into cloud environments. The Capital One breach (2019) exploited a misconfigured WAF combined with excessive IAM permissions to exfiltrate over 100 million records. +- **Container security** — scan and harden images and their base layers. Container scanning should run at build time and again continuously against the registry, since new CVEs emerge after an image is published. +- **Supply-chain security** — generate SBOMs, sign artifacts, and produce build provenance (SLSA). Signed provenance lets you verify that a release artifact was built from the expected source by the expected pipeline, catching tampering before production. The SolarWinds attack (2020) injected malicious code into the build process; signed provenance would have created a verifiable record of the anomaly. +- **IAST / DAST** — test running applications interactively and dynamically. IAST instruments the application at test time for deep, low-noise findings; DAST probes from the outside, as an attacker would. +- **API security** — discover, test, and protect APIs. REST and GraphQL surfaces are often undertested; dedicated API security tools enumerate endpoints from specs, traffic, or code and fuzz them for the OWASP API Top 10. +- **CNAPP / cloud-native security** — protect cloud and Kubernetes workloads at runtime. CNAPP platforms (CSPM + CWPP + CIEM + KSPM) give a unified view of misconfigurations, vulnerable workloads, excessive permissions, and runtime threats. +- **Continuous monitoring and vulnerability management** — aggregate, prioritize, and remediate findings over time. A vulnerability management process with defined SLAs (e.g., critical CVEs within 7 days, high within 30) closes the loop between detection and fix. +- **Compliance checks** — continuously verify controls against policy and regulation using policy-as-code tools so compliance state is always known, not discovered at audit time. -> The purpose and intent of DevSecOps is to build on the mindset that -> "everyone is responsible for security" with the goal of safely distributing -> security decisions at speed and scale to those who hold the highest level of -> context without sacrificing the safety required." +## A recommended introduction order -## The DevSecOps culture +| Priority | Control | Why first | +|---|---|---| +| 1 | Secrets scanning (pre-commit + CI) | Prevents the single most common and damaging class of pipeline leak; near-zero false positives | +| 2 | SCA in CI | Finds known CVEs in dependencies with very low false-positive rates; often the largest immediate risk surface | +| 3 | Branch protection + SAST in PR | Gates new code, surfaces findings where developers can act immediately at lowest cost | +| 4 | IaC scanning | Catches the misconfiguration class of cloud breach before infrastructure is provisioned | +| 5 | Container scanning | Stops vulnerable base images reaching production; runs automatically at build time | +| 6 | DAST / IAST | Tests the running application from inside and outside; requires a test environment | +| 7 | SBOM + signing | Establishes supply-chain trust and meets emerging regulatory requirements (EU CRA, NIST guidance) | -As you heard before we want to talk about the Shift-left security. -It means we should consider security from design (in a simple definition) which target is moving security earlier in the development process. +Start with controls 1–3. They provide the highest risk reduction per implementation effort and build the cultural habit of security-in-CI before adding more sophisticated controls. -Let's suppose that you are working in a DevOps team and you are traditionally doing security test -(yes, end of all QA tests and before going to production), what happens? -Well, all bugs should be fixed ASAP, Developer team is under pressure to fix issues, -QA tests should be performed again, and security test again. -This means that the costs, money and time, increase. -In the end, you sacrifice agility for security things do not like a business team. +## A finding's journey through the pipeline -The solution is introducing security earlier in the process instead of having it in the final steps. -Considering security in design by threat modeling and -break down huge security tests in smaller security testing and integrating them in the development pipeline. +To understand how the pieces connect, follow a typical SAST finding from discovery to closure: -The following picture shows the differences between DevOps and DevSecOps lifecycles. +1. **Developer writes code** with a SQL string built by concatenation (potential injection). The IDE plugin (e.g., Semgrep LSP, Snyk IDE) flags it inline — the developer sees it before a single commit. +2. **Pre-commit hook** runs a fast Semgrep scan on staged files. If the developer ignored the IDE warning, the hook catches it before the commit lands. +3. **Pull request CI** runs a full SAST scan against the base branch. A PR comment is posted automatically with the finding, the file, the line, the CWE reference, and a remediation suggestion. The PR is blocked from merge until the finding is addressed. +4. **Developer fixes** the injection by using a parameterized query. They push an updated commit; the SAST re-runs and the gate passes. +5. **The fix is merged.** The scan result (pass, with the finding resolved) is automatically ingested into the vulnerability management platform (e.g., DefectDojo) via webhook, closing the finding ticket. +6. **Governance dashboard** shows the MTTR for this finding (time from PR open to fix merged), contributing to the team's remediation SLA metric. -![DevOps vs DevSecOps](/current-version/assets/images/DevOps-vs-DevSecOps.png) +This flow is fully automated. No security team member touched it. The developer was informed, guided, and unblocked within their normal workflow. -## Privacy +## Integration architecture -Privacy has become a major topic for companies of all sizes, since GDPR (Europe’s General Data Protection Regulations), CCPA (California Consumer Privacy Act), LGPD – Brazil’s Lei Geral de Proteção de Dados, and other laws and regulations are being enforced around the world. +Tools in a DevSecOps pipeline connect through a few standard integration patterns: -Applications that will process a large volume of PII (personally identifiable information) should adapt the DevSecOps to follow the Privacy by Design approach, where the development process addresses privacy concerns thru the whole cycle. +- **CI hooks** — SAST, SCA, IaC, and secrets scanners run as pipeline steps. They emit exit codes (0 = pass, non-zero = fail) and produce structured output (SARIF, JSON, CycloneDX) consumed by downstream tooling. +- **SARIF ingestion** — GitHub Code Scanning, GitLab Security Dashboard, and DefectDojo all consume SARIF. A scanner that emits SARIF automatically integrates with any of these platforms without custom parsing. +- **Webhooks / APIs** — CI platforms push scan results to vulnerability management tools via webhook. Defect management tools (Jira, DefectDojo) create and close tickets via API. Dashboards pull from both. +- **OCI attestations** — SBOM and provenance attestations are stored as OCI artifacts alongside container images in the registry, discovered and verified by admission controllers at deploy time. +- **Policy engines** — OPA/Gatekeeper and Kyverno receive admission requests from Kubernetes and evaluate policies against them in real time. The decision (allow/deny) is logged for audit. -## Software testing strategies +## Security gates without breaking flow -When, we talk about testing we should have in mind -we have different definitions in testing which is can change our route to achieving -a secure DevSecOps cycle. -Let's take look into this definitions. +The goal is not to block every build on every finding — that destroys developer trust and creates alert fatigue. Instead: -### Different software testing strategies +- Gate on **risk** (severity, exploitability, reachability), not raw counts. +- Baseline existing issues so teams are accountable only for *new* risk they introduce. Many SAST tools support a `--baseline` flag or new-findings-only mode. +- Give developers actionable, in-context results in the tools they already use (IDE plugin, PR comment, Slack message) — not just a CI log they have to go digging for. +- Support a documented exception process for the rare cases where a finding cannot be remediated immediately, so teams do not disable gates as a workaround. -1. **Positive testing** +## Secure the pipeline, not just the app - Positive testing assumes that, under normal conditions and inputs, - everything will behave as expected. - It is performed with the assumption that only valid and relevant things will happen: - data set and all other functionalities will be as expected. +CI/CD tooling expands your attack surface. Build runners, package registries, third-party Actions/plugins, and long-lived tokens are all attractive targets. Concrete hardening steps include: -2. **Negative testing** +- Use **OIDC workload identity** (GitHub OIDC → AWS/GCP/Azure) instead of long-lived cloud credentials stored as secrets. +- **Pin** third-party Actions and container images to immutable SHA digests, not mutable tags. +- **Restrict `permissions:`** blocks in GitHub Actions to the minimum required per job. +- Run jobs in **ephemeral, isolated runners** and restrict network egress to only what the build needs. +- Audit third-party plugin and Action updates; treat them as supply-chain risk. - Negative testing checks the system behavior under unexpected conditions. - Negative testing plays a much important role in high-performance software development: - it checks the software behavior under unexpected conditions and inputs. +See the [CI/CD Pipeline Security](../2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md) page for a full hardening checklist. -#### Methods of testing +## Maturity and frameworks -1. **Static testing** +Use established frameworks to decide *what* to do and *how well*: - Static Testing checks software defects without executing the application code. - It is performed in the early stage of development to avoid errors, as it is easier to find sources of failures and it can be fixed easily. - Some issues that can’t be found using Dynamic Testing, can be easily found by Static Testing. Such issues consists of hard coded credentials, deprecated encryption algorithms, 2nd order injections, weak random, etc. - Most static analysis tools have the testing scope limited to one component and can not perform tests across different components. (EG. for a microservice architecture, static analysis tools will test each microservice independently) - ![Static testing](/current-version/assets/images/sast_scanning.png) +- [OWASP SAMM](https://owaspsamm.org/) — measure and improve security maturity across business functions. +- [OWASP DSOMM](https://dsomm.owasp.org/) — map concrete DevSecOps activities to maturity levels. +- [NIST SSDF (SP 800-218)](https://csrc.nist.gov/Projects/ssdf) — baseline secure-development practices for compliance. +- [SLSA](https://slsa.dev/) — supply-chain integrity levels. -2. **Dynamic testing** - - Dynamic Testing analyzes the behavior of the application code at runtime. Scanners send specially crafted requests to the target application. Request parameters are constantly modified during testing to try and expose a range of vulnerabilities. Based on the response of the application the tool can then identify potential vulnerabilities and report back. Some issues that can't be found by static analysis are easily detected by dynamic analysis. Such issues include client side vulnerabilities like authentication & session issues, sensitive data sent in plain text, etc. - Dynamic analysis tools have the possibility of testing the entire application flow(multiple components at once). (Eg. for a microservice architecture, dynamic analysis tools can point to one microservice, but as they interact with each other results will represent the behaviour of the entire application) - ![Dynamic testing](/current-version/assets/images/dast_scanning.png) - -3. **Interactive analysis** - - Also known as Interactive Application Security Testig (IAST) monitors the application while other systems interact with it and observe vulnerabilities. This is achieved via sensors or agents deploy with the application. The sensors can see the entire flow from HTTP request down to the executed code, tracing the data through the application. Similar to static analysis, it can test one component at a time, but not multiple components. However, if agents/sensors are deployed on all components, when they interact with eachother this could reveal vulnerabilities in each component used in the application. (Eg. for a microservice architecture, only the microservices that have agents/sensors attached will report vulnerabilities) - ![Interactive analysis](/current-version/assets/images/iast_analysis.png) - ---- - -#### References - -1. -2. +See [Frameworks and Standards](0-3-Frameworks-and-Standards.md) for how these relate. diff --git a/current-version/0-Intro/0-3-Frameworks-and-Standards.md b/current-version/0-Intro/0-3-Frameworks-and-Standards.md new file mode 100644 index 0000000..25f46fc --- /dev/null +++ b/current-version/0-Intro/0-3-Frameworks-and-Standards.md @@ -0,0 +1,102 @@ +# Frameworks and Standards + +No single framework covers all of DevSecOps. Strong programs combine several: one sets the **baseline** of required practices, another measures **maturity**, another drives **engineering adoption** inside the pipeline, and another secures the **supply chain**. This page maps the major frameworks and how they relate to this guideline. + +## The frameworks teams use together + +### NIST SSDF — Secure Software Development Framework ([SP 800-218](https://csrc.nist.gov/Projects/ssdf)) + +An outcome-focused baseline of secure-development practices, organized into four practice groups: + +- **PO — Prepare the Organization**: establish policies, roles, tools, and environments for secure development before writing a line of code. +- **PS — Protect the Software**: maintain the integrity of source code, third-party components, build processes, and release artifacts. This maps directly to supply-chain security and repository hardening. +- **PW — Produce Well-Secured Software**: apply secure design, coding, testing, and code review practices. The bulk of SAST, SCA, threat modeling, and testing activities live here. +- **RV — Respond to Vulnerabilities**: identify, assess, and remediate vulnerabilities discovered after release, including through external disclosure programs. + +SSDF says *what* outcomes to achieve, not *how* to build your pipeline — which makes it well suited to regulated environments and US federal procurement requirements (Executive Order 14028 references SSDF directly). Teams use it as a compliance mapping layer over their existing pipeline. + +### OWASP SAMM — Software Assurance Maturity Model ([owaspsamm.org](https://owaspsamm.org/)) + +Measures and improves security maturity across five business functions: **Governance, Design, Implementation, Verification, Operations**. Each function has practices that are scored at three maturity levels. + +SAMM's primary use is the **assessment**: run SAMM against your organization to produce a benchmark, identify gaps, and build a prioritized roadmap. Teams typically run a SAMM assessment annually and use results to set quarterly security program goals. The SAMM toolbox provides a spreadsheet-based assessment tool as well as an online version. + +### OWASP DSOMM — DevSecOps Maturity Model ([dsomm.owasp.org](https://dsomm.owasp.org/)) + +Zooms into concrete technical activities inside CI/CD and assigns them to maturity levels across dimensions like Build, Deploy, Test, and Culture. Where SAMM sets strategic direction, DSOMM drives day-to-day engineering adoption — it tells you *which specific pipeline activity* to implement next. + +For example, DSOMM distinguishes between "secrets are scanned in CI" (level 1) and "secrets are scanned pre-commit with automatic block" (level 2) and "secret rotation is automated and verified" (level 3). This specificity makes it a useful benchmark for platform and AppSec teams. + +### SLSA — Supply-chain Levels for Software Artifacts ([slsa.dev](https://slsa.dev/)) + +A graded framework (Levels 1–4) for build integrity and verifiable provenance. Each level adds stronger guarantees about where an artifact came from and how it was built: + +- **Level 1**: provenance exists (basic build metadata). +- **Level 2**: provenance is signed; build is hosted on a managed platform. +- **Level 3**: provenance is non-falsifiable; the build environment is hardened. +- **Level 4**: full two-party review; hermetic, reproducible builds. + +In practice, reaching SLSA Level 2 with GitHub Actions and Sigstore is achievable for most teams and satisfies most current regulatory and customer requirements. Level 3+ is the target for critical infrastructure software. + +### OWASP Top 10 CI/CD Security Risks ([owasp.org](https://owasp.org/www-project-top-10-ci-cd-security-risks/)) + +The canonical list of risks to the pipeline itself — an important complement to the application-focused OWASP Top 10. Key risks include: + +- **CICD-SEC-1**: Insufficient Flow Control Mechanisms (no approval gates, no separation of duties in the pipeline) +- **CICD-SEC-2**: Inadequate Identity and Access Management (overly permissive tokens, no OIDC) +- **CICD-SEC-3**: Dependency Chain Abuse (typosquatting, malicious packages) +- **CICD-SEC-4**: Poisoned Pipeline Execution (PPE) — untrusted code running in a trusted context +- **CICD-SEC-6**: Insufficient Credential Hygiene — long-lived tokens in environment variables or logs + +### OWASP Proactive Controls / ASVS / Top 10 + +Developer-facing security controls, verification requirements, and the best-known web risk list: + +- **OWASP Top 10** — the ten most critical web application risks. Use it to prioritize training and testing. +- **OWASP ASVS** — a 200+ item catalog of verifiable security requirements at three levels. Use it to define what "done" means for security in your backlog. +- **OWASP Proactive Controls** — ten defensive techniques every developer should apply. Use it as a quick-start guide for secure coding. + +## How they fit together + +| Concern | Framework | +| --- | --- | +| Baseline and compliance | NIST SSDF, ISO/IEC 27001, PCI DSS | +| Maturity measurement and roadmap | OWASP SAMM, BSIMM | +| Pipeline engineering adoption | OWASP DSOMM | +| Supply-chain integrity | SLSA, in-toto | +| Pipeline-specific risk | OWASP Top 10 CI/CD | +| Developer controls | OWASP ASVS, Proactive Controls, Top 10 | +| AI/ML risk | OWASP LLM Top 10, NIST AI RMF, ISO/IEC 42001 | + +In short: **SSDF = compliance baseline**, **SAMM = strategic maturity**, **DSOMM = engineering adoption**, **SLSA = supply-chain integrity**. This OWASP DevSecOps Guideline sits in the middle — translating these frameworks into concrete, stage-by-stage pipeline controls. + +## Regulatory drivers + +Several regulations have turned these practices from optional to expected: + +- **US Executive Order 14028 / OMB M-22-18** — requires federal software suppliers to attest SSDF compliance and provide SBOMs. Has driven rapid adoption of supply-chain security tooling in commercial software as well. +- **EU Cyber Resilience Act (CRA)** — security requirements, vulnerability handling obligations, and incident reporting for products with digital elements sold in the EU. Covers both software publishers and open-source stewards of "critical" components. +- **PCI DSS v4.0** — requires continuous vulnerability management, penetration testing, and secure development practices. New requirements in v4.0 increase emphasis on application security controls. +- **SOC 2 Type II** — audited against your SDLC for security, availability, and confidentiality. Reviewers examine change management, SAST/DAST evidence, access controls, and incident response. +- **ISO/IEC 27001:2022** — adds supply-chain security (A.5.19–5.22) and secure development lifecycle (A.8.25–8.31) as explicit control objectives. + +## Using frameworks without drowning in them + +A common failure mode is treating frameworks as compliance exercises to be completed rather than tools to improve outcomes. Practical advice: + +- **Pick one maturity model** (SAMM or DSOMM) and run a genuine assessment before shopping for tools. The assessment reveals real gaps; the tools address them. +- **Map your existing controls to SSDF** only if you have a regulatory reason. For most organizations, building a good program first and mapping it to SSDF afterward is more efficient. +- **Use SLSA as an engineering target**, not a compliance checkbox. Start at Level 1, move to Level 2, and measure the journey. +- **Do not maintain parallel compliance artifacts** if you can make your pipeline produce evidence natively (signed build logs, immutable artifact records, policy-as-code reports). + +--- + +## Further reading + +- [NIST SSDF (SP 800-218)](https://csrc.nist.gov/Projects/ssdf) +- [OWASP SAMM](https://owaspsamm.org/) +- [OWASP DSOMM](https://dsomm.owasp.org/) +- [SLSA](https://slsa.dev/) +- [OWASP Top 10 CI/CD Security Risks](https://owasp.org/www-project-top-10-ci-cd-security-risks/) +- [NIST AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework) +- [EU Cyber Resilience Act](https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act) diff --git a/current-version/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md b/current-version/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md index c6a9e7a..562d39d 100644 --- a/current-version/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md +++ b/current-version/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md @@ -1 +1,125 @@ # Security Champions + +Security teams are almost always outnumbered by developers — often by ratios of 1:100 or worse. A **Security Champions** program scales application security by embedding security-minded engineers *inside* development teams, rather than relying on a central team to review everything. + +A security champion is a developer (or QA, SRE, or product person) on a delivery team who takes on an additional interest in security: they act as the local point of contact, raise security concerns early, help triage findings, and connect their team to the central security function. + +## Why a champions program matters + +- **Scale** — security expertise reaches every team without hiring an army. At a 1:100 security-to-developer ratio, it is physically impossible for the security team to review every PR, threat model, or design doc. Champions create a distributed security presence. +- **Context** — champions understand their own codebase, deployment environment, and threat surface far better than an outside reviewer. They know which findings matter and which are false positives. +- **Shift-left culture** — security becomes a peer-to-peer norm rather than a top-down mandate from a team developers rarely interact with. Developers listen to each other. +- **Faster feedback** — questions get answered locally (in team standups, Slack channels, PR reviews) instead of queuing for the security team. Fast feedback loops reduce the cost of fixing issues. +- **Two-way information flow** — champions surface real-world friction (tool noise, process bottlenecks) back to the security team, which would otherwise never hear it. + +## Building the program + +### Recruitment and selection + +Recruit volunteers first; intrinsic motivation produces far better champions than nomination. Use this pitch in team channels or all-hands: + +> "We're looking for engineers curious about security who want to help their team ship more confidently. As a Security Champion you'll get advanced training, direct access to the security team, and recognition for the security outcomes you drive. Time commitment: roughly 10–15% of your week, protected in your sprint." + +When evaluating candidates, prioritize: +- **Curiosity and communication** over technical depth or seniority. A mid-level developer trusted by their peers is more effective than a senior engineer who works in isolation. +- **Peer influence** — a champion nobody talks to cannot shift team culture. +- Aim for at least one champion per product team or squad. Larger teams (10+) may need two. +- Reach across roles: developers, QA engineers, SREs, platform engineers, and technical product managers can all be effective champions with the right support. + +### Training and enablement + +- Give champions training that goes beyond the baseline all developers receive: threat modeling facilitation, deeper vulnerability classes, tool configuration, and triage methodology. +- Budget **dedicated, protected time** — typically 10–20% of their work week. Champions who are not given time will deprioritize champion work under delivery pressure. This must be agreed with team leads before the program launches. +- Provide direct access to the security team (a shared Slack channel, a weekly office hours slot) so champions can escalate quickly without filing tickets. +- Share internal threat intelligence, past incidents, and post-mortems so champions understand the real-world context behind policies. +- Certifications and external training (OWASP training, security conferences) should be available as a program benefit. + +### A champion's typical week + +| Time allocation | Activity | +|---|---| +| ~3 hours | Triage and comment on scanner findings in sprint planning or async | +| ~2 hours | Answer security questions from teammates (Slack, PR reviews) | +| ~1 hour | Attend security team office hours or sync | +| ~1 hour | Threat model review or secure design input for an upcoming feature | +| ~1 hour | Champion community of practice, knowledge base updates, or self-study | + +This 8–10 hour allocation (10–15% for a full-time engineer) should be reflected in sprint velocity planning. + +### Community of practice + +- Run a recurring champions community: a shared chat channel for day-to-day questions and a regular video sync (monthly or bi-weekly) for knowledge sharing, policy updates, and collaborative problem-solving. +- Rotate spotlight presentations where champions share what they found and fixed on their team — this spreads knowledge and builds recognition. +- Maintain a shared knowledge base (wiki, runbooks, FAQ) so institutional knowledge is not lost when a champion changes roles or leaves. +- Create a dedicated champions Slack channel where anyone can ask a question and get a real answer within hours — this is the program's most visible daily value. + +### Recognition and retention + +- Tie champion participation to career growth **explicitly** — performance reviews, promotion criteria, and public recognition at all-hands meetings. +- Create a tiered program (associate champion → champion → senior champion / lead) so there is a visible progression path and a reason to stay engaged. +- Celebrate catches: when a champion spots a critical issue in a design review or triage session, make sure it is acknowledged and credited publicly. +- Annual champion awards (most threats modeled, most findings closed, most knowledge shared) with leadership recognition. + +## Handling champion burnout + +Champions burn out when they take on too much without organizational backing. Warning signs: missed community calls, declining triage activity, requests to step down. + +Prevention: +- Enforce the time allocation — check in with team leads quarterly to ensure sprint planning protects champion hours. +- **Rotate coverage** for champions going on leave so their team is not left uncovered and they do not return to a backlog. +- Provide an escalation path: champions should never be expected to resolve a security problem that requires specialist expertise alone. A clear "call the security team" path removes the burden of being the final answer. +- Recognize and budget for burnout cycles — a champion who steps back after two years is still a net win; celebrate the contribution and recruit a successor. + +## Escalation paths + +A champion's authority is advisory, not absolute. Define clear escalation levels: + +| Situation | Who handles it | +|---|---| +| Team-level security question | Champion answers directly | +| Finding that needs prioritization guidance | Champion + security team sync | +| Critical / high finding that cannot be fixed in-sprint | Champion raises to security team for triage and risk acceptance | +| Suspected active breach or incident | Champion escalates immediately to security team and incident response | +| Disagreement on risk acceptance between team and security | Champion escalates to security engineering lead for arbitration | + +## Responsibilities of a champion + +| Responsibility | Frequency | +|---|---| +| First point of contact for team security questions | Ongoing | +| Help facilitate threat-modeling sessions and secure design reviews | Per new feature or quarter | +| Triage and prioritize scanner findings before central team escalation | Weekly / per sprint | +| Promote secure-coding standards; shepherd remediation of assigned findings | Ongoing | +| Attend the champions community of practice | Monthly / bi-weekly | +| Report tooling friction and false-positive patterns to the security team | Ongoing | +| Represent the team's security posture in security reviews | Per review cycle | + +## Common pitfalls + +- **Champions with no time allocated** — champion work competes with sprint commitments and always loses without protected time. +- **No path for escalation** — champions burn out if they are expected to solve security problems their team cannot fix alone with no route to specialist help. +- **Treating champions as a security review bottleneck** — champions should triage and advise, not be required to sign off on every PR. That recreates the bottleneck problem at the team level. +- **Starting too big** — a 50-person champions cohort with no structure, no training schedule, and no community quickly becomes a list of names. Start with 5–10 enthusiastic volunteers, prove the model, then scale. +- **No metrics** — without tracking engagement, defects caught, and threat models run, the program becomes invisible to leadership and risks being cut when budgets tighten. + +## Measuring the program + +Key metrics to track and report: + +| Metric | Why it matters | +|---|---| +| Active champions and team coverage | Shows program reach; flag teams with no champion | +| Threat models facilitated per quarter | Core security activity proxy | +| Findings triaged/closed by champions vs escalated | Champion effectiveness signal | +| MTTR on teams with vs without champions | Business case for the program | +| Training completion rates | Enablement health | +| Developer satisfaction scores (security tooling and support) | Friction and adoption indicator | +| Security issues raised by developers (not scanners) | Ultimate culture shift indicator | + +--- + +## References + +- [OWASP Security Champions Guide](https://owasp.org/www-project-security-champions-guidebook/) +- [OWASP Security Champions Playbook](https://github.com/c0rdis/security-champions-playbook) +- [OWASP SAMM — Education & Guidance](https://owaspsamm.org/model/governance/education-and-guidance/) diff --git a/current-version/1-People/1-1-Shape-the-team/1-1-2-Roles-and-Responsibilities.md b/current-version/1-People/1-1-Shape-the-team/1-1-2-Roles-and-Responsibilities.md new file mode 100644 index 0000000..b559259 --- /dev/null +++ b/current-version/1-People/1-1-Shape-the-team/1-1-2-Roles-and-Responsibilities.md @@ -0,0 +1,137 @@ +# Roles and Responsibilities + +DevSecOps works only when security is a **shared responsibility**. That does not mean everyone does everything — it means each role has clear, explicit security duties and the boundaries between them are understood. Ambiguity ("I thought security owned that") is where risk accumulates. + +## Core roles and their security duties + +### Developers + +Developers are the primary consumers of shift-left tooling and the first line of defense for application security: + +- Write secure code and apply the [OWASP Proactive Controls](https://owasp.org/www-project-proactive-controls/). +- Run pre-commit hooks and IDE security plugins; fix findings on their own code before opening a PR. +- Participate in threat modeling sessions and secure code review for their features. +- Write security acceptance criteria alongside functional acceptance criteria. +- Review AI-generated code with the same scrutiny as hand-written code. + +### Security Champions + +Embedded developers who act as the local security point of contact — see [Security Champions](1-1-1-Security-champions.md) for the full program description. Their unique value is combining the developer's context with security expertise: they can translate between the security team's concerns and the team's engineering realities. + +### AppSec / Security Engineers + +Own the application security function: + +- Define security requirements, policies, and gate thresholds. +- Own and tune the AppSec tooling (SAST, DAST, SCA, IAST, secrets scanning). +- Support triage — help developers distinguish real vulnerabilities from false positives. +- Run or support threat modeling for high-risk features and new architectures. +- Conduct security code reviews and provide consultation. +- Design and deliver security training (with the champions network as a force multiplier). +- Track and report on the security posture of the application portfolio. + +### DevSecOps / Platform Engineers + +Build and maintain the secure **paved road** — the infrastructure that makes security the default: + +- Harden CI/CD templates: enforce least-privilege tokens, pin dependencies, add security scanning as a standard step. +- Build and maintain approved, hardened golden base images for containers and VMs. +- Provide reusable, security-compliant IaC modules (Terraform modules, Helm charts) so product teams cannot easily misconfigure infrastructure. +- Maintain the self-service developer portal that surfaces security tooling as a first-class capability. +- Monitor the pipeline itself as an attack surface and apply the [OWASP Top 10 CI/CD](https://owasp.org/www-project-top-10-ci-cd-security-risks/) hardening checklist. + +### SRE / Operations + +Own runtime security posture and the reliability of security controls in production: + +- Monitor for security events and anomalies; operate the SIEM and alerting. +- Own incident response runbooks and lead security incident response for runtime events. +- Ensure backup, recovery, and availability controls function correctly. +- Feed production threat intelligence (active exploits, runtime anomalies) back to the engineering and AppSec teams. + +### Security Architects + +Define the security structure that product teams build on: + +- Design reusable secure design patterns (authentication, authorization, cryptography, API security). +- Threat-model high-risk systems and new architectural domains. +- Set technical security standards and ensure they are captured in the paved road. +- Review and sign off on major architectural decisions with significant security implications. + +### Product Owners / Managers + +Own the business risk decisions: + +- Prioritize security work in the backlog alongside feature work — security stories must be estimated, scheduled, and tracked like any other work. +- Accept or escalate residual risk with awareness of the business consequences. +- Ensure abuse cases and security acceptance criteria are part of story definition of done. + +### GRC / Compliance + +Bridge security and regulatory obligations: + +- Map pipeline controls to compliance frameworks (SSDF, PCI DSS, SOC 2, ISO 27001). +- Manage audit evidence collection and liaise with auditors. +- Track and review risk acceptance decisions; ensure exceptions have time-bound remediation plans. +- Monitor the regulatory landscape for changes that affect control requirements. + +### CISO / Security Leadership + +Accountable for the overall security posture: + +- Set security strategy, program goals, and risk appetite. +- Fund security work, including training, tooling, and champion program time allocations. +- Communicate security posture and risk to executive and board stakeholders. +- Hold engineering leadership accountable for remediation SLAs. + +## Platform engineering and the paved road + +Modern programs lean heavily on **platform engineering**: instead of asking every team to assemble security tooling themselves, a platform team provides golden paths — pre-hardened pipelines, templated IaC, vetted base images, and built-in scanning. Security becomes the default behavior of the platform rather than a checklist each team must remember. + +This approach scales security coverage dramatically without scaling the security team. A team of five platform engineers can raise the security baseline for hundreds of product developers by building and maintaining the right defaults. + +The paved road only works if it is kept current. Assign clear ownership for updating golden templates when new vulnerabilities, tooling updates, or policy changes require it. + +## The emerging AI/ML role + +As AI moves into the SDLC, a new specialization is appearing: **DevSecOps for AI/ML pipelines** (sometimes "MLSecOps"). These engineers secure the model lifecycle: + +- Training data integrity — provenance, poisoning detection, access controls. +- Model provenance and AI-BOMs — tracking what model, what weights, what training data. +- Securing the inference path — input validation, output filtering, prompt injection defenses. +- Scanning AI-generated code and the supply chain of models and datasets. + +See [AI Governance and Risk](../../3-Governance/3-4-AI-Governance-and-Risk.md) for the full treatment. + +## A simple RACI view + +A lightweight RACI matrix per activity prevents gaps and surfaces ownership disputes before they become incidents: + +| Activity | Responsible | Accountable | Consulted | Informed | +| --- | --- | --- | --- | --- | +| Fix SAST finding in app code | Developer | Eng. manager | AppSec, Champion | Security lead | +| Tune scanner / define gates | AppSec | AppSec lead | Dev teams, Platform | Leadership | +| Harden CI/CD pipeline | Platform eng. | Platform lead | AppSec | Dev teams | +| Runtime incident response | SRE | SRE lead | AppSec, Dev | Leadership | +| Risk acceptance / exception | Product owner | CISO | AppSec | Auditors, GRC | +| Threat model new feature | Champion + AppSec | Eng. manager | Security architect | Product owner | +| Security training delivery | AppSec | CISO | Champions | All developers | +| Compliance audit evidence | GRC | CISO | AppSec, Platform | Legal | + +Keep it lightweight and revisit it as the program matures or when ownership disputes arise. + +## Common pitfalls + +- **"Security's job"** — when developers believe security is someone else's responsibility, they defer findings, skip threat modeling, and route around controls. +- **AppSec as the only triage point** — every finding routed through the AppSec team creates a bottleneck that scales as O(number of findings). Champions and automated prioritization must handle the first tier. +- **Platform team isolated from security** — a platform team that builds without AppSec input produces paved roads with security gaps baked in and replicated across all consumers. +- **GRC and engineering in silos** — compliance requirements that are not translated into engineering controls get evidenced with screenshots rather than automated verification. + +--- + +## Further reading + +- [OWASP SAMM](https://owaspsamm.org/) +- [OWASP DevSecOps Maturity Model (DSOMM)](https://dsomm.owasp.org/) +- [Team Topologies — platform teams](https://teamtopologies.com/) +- [CISA Secure by Design — shifting responsibility](https://www.cisa.gov/securebydesign) diff --git a/current-version/1-People/1-2-Training/1-2-1-Secure-coding.md b/current-version/1-People/1-2-Training/1-2-1-Secure-coding.md index c1154a9..6cc75ae 100644 --- a/current-version/1-People/1-2-Training/1-2-1-Secure-coding.md +++ b/current-version/1-People/1-2-Training/1-2-1-Secure-coding.md @@ -1 +1,158 @@ -# Secure Coding +# Secure Coding Training + +Most vulnerabilities are introduced while code is being written. The cheapest place to prevent them is in the developer's head — which makes **secure coding training** one of the highest-leverage investments in a DevSecOps program. The goal is not to turn every developer into a security expert, but to give them the awareness, patterns, and reflexes to avoid the common, costly mistakes. + +## What to teach + +### Core web and application risk + +- **The OWASP Top 10** — [owasp.org/www-project-top-ten](https://owasp.org/www-project-top-ten/) — covers the ten most critical web application risks. Every developer writing server-side code should understand injection, broken access control, cryptographic failures, and insecure design. +- **The relevant variant for your stack** — [OWASP API Top 10](https://owasp.org/www-project-api-security/) for API developers, [OWASP Mobile Top 10](https://owasp.org/www-project-mobile-top-10/) for mobile engineers, [OWASP LLM Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/) for teams building AI-powered features. + +### Security requirements and verification + +- **OWASP ASVS** — [owasp.org/www-project-application-security-verification-standard](https://owasp.org/www-project-application-security-verification-standard/) — a concrete checklist of what "secure" means for authentication, session management, input validation, cryptography, API security, and more. Use it as a training curriculum and as the definition-of-done for security requirements. + +### Defensive techniques + +- **OWASP Proactive Controls** — [owasp.org/www-project-proactive-controls](https://owasp.org/www-project-proactive-controls/) — ten defensive techniques developers should apply in every application: define security requirements, leverage security frameworks, secure database access, encode and escape data, validate all inputs, implement digital identity correctly, enforce access controls, protect data everywhere, implement security logging and monitoring, handle all errors and exceptions. + +### Language- and framework-specific guidance + +Generic security training does not stick as well as guidance tied to the developer's actual stack. Use the [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/) as a reference by topic and language: + +| Language / Area | Key cheat sheets and pitfalls | +|---|---| +| Python | [SQL Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html), avoiding `pickle` deserialization, safe `subprocess` usage, SSRF prevention | +| Java / Spring | [Spring Security](https://cheatsheetseries.owasp.org/cheatsheets/Spring_Security_Cheat_Sheet.html), avoiding `ObjectInputStream`, XXE in XML parsers, expression language injection | +| JavaScript / Node.js | Prototype pollution, ReDoS, path traversal in file operations, [npm dependency confusion](https://cheatsheetseries.owasp.org/cheatsheets/npm_Security_Cheat_Sheet.html) | +| Go | SQL injection in raw queries, TLS configuration, goroutine leaks in error paths | +| Terraform / Helm | [Infrastructure as Code](https://cheatsheetseries.owasp.org/cheatsheets/Infrastructure_as_Code_Security_Cheat_Sheet.html), hardcoded secrets, overly permissive IAM, unsafe default values | +| Authentication | [Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html), [Session Management](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html) | +| Cryptography | [Cryptographic Storage](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html), [TLS](https://cheatsheetseries.owasp.org/cheatsheets/TLS_Cipher_String_Cheat_Sheet.html) | + +### Secure code review + +How to read code adversarially — spotting anti-patterns, data flow from untrusted input to dangerous sinks, missing authorization checks, and insecure defaults. Code review is where security knowledge directly translates into prevented vulnerabilities. + +A minimal secure code review checklist: +- [ ] All inputs validated server-side (type, length, allowlist where feasible) +- [ ] Parameterized queries used for all database access; no string concatenation +- [ ] Authorization checked on every state-changing operation, not just at login +- [ ] Secrets not hardcoded; no API keys in source files or logs +- [ ] Error responses sanitized; no stack traces, internal paths, or query text exposed +- [ ] Cryptographic functions use current algorithms and library defaults (not custom implementations) +- [ ] Dependencies match the expected version; no unexpected additions + +## Integrating training into the developer lifecycle + +Training is most effective when it meets developers where they already are, rather than pulling them out of their workflow. + +### Onboarding + +Every new developer should complete security onboarding before or alongside technical onboarding: + +- OWASP Top 10 awareness module (60–90 minutes, interactive) +- Language-specific cheat sheet review for their primary stack +- Introduction to internal tools (secrets scanner, SAST, pre-commit hooks) and how to interpret findings +- Introduction to the security champion for their team + +### Ongoing development + +| Touchpoint | Delivery | +|---|---| +| IDE security plugin | Real-time feedback (Snyk, SonarLint, Semgrep) as code is typed | +| PR review | Automated comments linking findings to cheat sheet remediation guidance | +| Sprint planning | Security champion reviews relevant findings before estimation | +| Quarterly learning sprints | 2–4 hour focused lab on a current threat (e.g., LLM prompt injection, supply-chain attacks) | +| Incident retrospectives | Post-mortems that include secure-coding lessons from real vulnerabilities | + +## Defining a secure coding standard + +Every organization should maintain a written secure coding standard — a living document that captures language-specific rules, approved libraries, and banned patterns. Minimum contents: + +1. **Approved dependency sources** — permitted registries, prohibited packages, lockfile requirements +2. **Authentication and session** — required auth library, forbidden patterns (rolling your own JWT validation, storing tokens in localStorage) +3. **Input and output handling** — validation libraries to use, encoding requirements per output context +4. **Database access** — ORM or query builder required, raw query rules +5. **Secrets management** — where secrets live (vault, environment variables), what is forbidden (committed plaintext, hardcoded strings) +6. **Cryptography** — approved algorithms and key sizes; forbidden (MD5, SHA1 for security purposes, DES, ECB mode) +7. **Error handling** — what to log, what to return in error responses +8. **Third-party code** — review requirements before adoption, license check, security advisory monitoring + +Link the standard from pull request templates so it is visible at review time. + +## What makes training stick + +- **Hands-on, not slideware** — interactive labs and deliberately vulnerable apps beat passive video lectures. A developer who exploits a SQL injection in a lab will remember it; one who watches a slide about it will not. +- **Just-in-time** — surface a short, relevant lesson at the moment a developer hits a related finding in their IDE or PR review. Context and motivation are both highest at the point of discovery. +- **Role-relevant** — tailor content to the language, framework, and threat surface the developer works in. +- **Continuous** — short, frequent refreshers beat an annual compliance video. Aim for touchpoints at least quarterly. + +## Training delivery patterns + +| Pattern | When it works best | +|---|---| +| Self-paced labs (platform-provided) | Baseline training, onboarding, async organizations | +| Just-in-time IDE nudges | Language-specific, integrated into daily workflow | +| Live workshops | Threat modeling, code review, high-engagement topics | +| CTF / bug bash events | Team building, gamification, surfacing advanced interest | +| Champion-led team sessions | Team-specific context, local tooling and codebase examples | +| Incident-driven retrospective labs | High relevance — recreating a real vulnerability builds lasting memory | + +## Reinforce in the AI era + +With AI coding assistants generating a growing share of code, developers need to learn to: + +- **Review AI-generated code** with the same scrutiny as hand-written code — AI assistants routinely produce SQL injection, path traversal, insecure deserialization, and other vulnerabilities. +- **Recognize hallucinated dependencies** — AI assistants sometimes suggest package names that do not exist, which attackers pre-register (a pattern called slopsquatting). Verify every suggested package. +- **Apply secure-coding judgment to AI output** — the developer is responsible for what they merge, regardless of who or what wrote it. +- **Use AI as a teaching moment** — when a scanner flags AI-generated code, treat it as a just-in-time training opportunity rather than just a fix-and-move-on task. + +See [IDE and AI-Assisted Development Security](../../2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md). + +## Measuring training effectiveness + +Completion rates are a compliance metric, not a security metric. Track: + +| Metric | What it measures | +|---|---| +| Security defect escape rate (pre-production vs production) | Whether training translates to fewer runtime vulnerabilities | +| Security findings per developer per quarter (trend) | Injection rate improvement over time | +| Mean time to remediate findings (MTTR) | Developer fluency with fixing security issues | +| % of PRs with at least one security finding | Coverage and discovery health | +| Developer satisfaction score for security tooling | Friction — high friction correlates with workarounds | +| Time-to-first-security-finding after onboarding | Leading indicator of onboarding effectiveness | + +## Maturity progression + +| Level | Focus | +|---|---| +| Starting | OWASP Top 10 awareness; annual (or onboarding) completion; basic injection and XSS labs | +| Developing | Role-specific training tied to stack; just-in-time IDE integration; quarterly refreshers | +| Maturing | ASVS-aligned curriculum; escape rate tracked per team; training completion tied to sprint planning | +| Advanced | Developer-led threat modeling; champions deliver peer training; custom labs from internal incidents | + +--- + +## Tools[^1] + +### Open-source + +- [OWASP Juice Shop](https://owasp.org/www-project-juice-shop/) — Modern, intentionally insecure web application covering the OWASP Top 10 and beyond. Ideal for workshops and self-study; includes a Capture the Flag mode. Best for broad web security awareness. +- [OWASP Security Knowledge Framework (SKF)](https://www.securityknowledgeframework.org/) — Provides security requirements, code examples, and labs mapped to ASVS. Supports integration into the development workflow. Best for teams wanting ASVS-aligned learning paths. +- [OWASP WebGoat](https://owasp.org/www-project-webgoat/) — Deliberately insecure Java application with interactive lessons. Good for teams on JVM stacks; covers a wide set of Java-specific vulnerabilities. +- [OWASP crAPI](https://github.com/OWASP/crAPI) — Completely Ridiculous API, a vulnerable API for practising OWASP API Top 10 attacks. Ideal for teams building or testing APIs. + +### Commercial + +- [Hack The Box](https://www.hackthebox.com/) — Hands-on hacking labs and training for both offensive and defensive skills. Best for engineers with security interest who want to go beyond awareness into technical depth. +- [Secure Code Warrior](https://www.securecodewarrior.com/) — Gamified, language-specific secure-coding training integrated into the developer workflow; supports tournament-style team challenges. Best for enterprise-scale developer programs with manager dashboards. +- [SecureFlag](https://www.secureflag.com/) — Hands-on secure-coding training in real, runnable environments across 30+ languages and frameworks. Best for breadth of language support. +- [Snyk Learn](https://learn.snyk.io/) — Free and integrated secure coding lessons mapped to real CVEs and language-specific vulnerabilities. Best for just-in-time learning tied to actual Snyk findings. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/1-People/1-2-Training/1-2-2-Security-CICD.md b/current-version/1-People/1-2-Training/1-2-2-Security-CICD.md index 7ae487a..d86c93a 100644 --- a/current-version/1-People/1-2-Training/1-2-2-Security-CICD.md +++ b/current-version/1-People/1-2-Training/1-2-2-Security-CICD.md @@ -1 +1,129 @@ -# Security CICD +# Security in CI/CD Training + +Secure coding protects the application; this training protects the **pipeline that builds and ships it**. CI/CD systems hold powerful credentials, run untrusted code, and pull in third-party dependencies and plugins — which makes them a prime target. High-profile breaches (e.g. SolarWinds, Codecov, and numerous compromised GitHub Actions) all abused the build and delivery pipeline rather than the application itself. + +Everyone who writes pipeline configuration — developers, platform engineers, SREs — needs to understand how these systems are attacked and how to harden them. + +## Why the pipeline is a high-value target + +Attackers target pipelines because the payoff is enormous: a single compromised build pipeline can simultaneously poison every artifact it produces, exfiltrate source code and secrets, and grant lateral movement into production environments — all through a mechanism that runs automatically on every push. The SolarWinds attack compromised the build system and inserted malicious code into signed, trusted software updates delivered to 18,000+ customers. Understanding this threat model is the starting point for CI/CD security training. + +## What to teach + +### The CI/CD threat model + +Cover the [OWASP Top 10 CI/CD Security Risks](https://owasp.org/www-project-top-10-ci-cd-security-risks/) in depth — particularly the risks that are non-obvious to developers: + +- **CICD-SEC-1 — Insufficient Flow Control**: No merge approval requirements; direct pushes to the main branch; no separation of duties in release pipelines. +- **CICD-SEC-2 — Inadequate Identity and Access Management**: Long-lived tokens with broad scope; no OIDC; shared service accounts; no token rotation. +- **CICD-SEC-3 — Dependency Chain Abuse**: Typosquatting, dependency confusion attacks, compromised transitive dependencies (e.g. `event-stream`). +- **CICD-SEC-4 — Poisoned Pipeline Execution (PPE)**: Untrusted code from a fork PR running in a privileged context with access to secrets. This is one of the most common and impactful CI/CD vulnerabilities. +- **CICD-SEC-6 — Insufficient Credential Hygiene**: Long-lived secrets in environment variables, visible in build logs, or stored as plaintext in configuration files. + +### Secrets handling + +The single most common and damaging pipeline security failure is credential exposure: + +- **Never hardcode** credentials, API keys, or tokens in pipeline configuration or code. Use the CI/CD platform's secret management (GitHub Secrets, GitLab CI/CD variables, Vault). +- Use **OIDC workload identity** where possible — the pipeline authenticates to cloud providers using a short-lived, automatically rotated OIDC token rather than a stored key. No secret to leak, no secret to rotate manually. + + ```yaml + # GitHub Actions: OIDC to AWS — no long-lived key required + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::123456789012:role/github-actions-role + aws-region: us-east-1 + ``` + +- Scope secrets to the minimum: a deployment token should only be able to deploy, not read source code or manage IAM. +- Audit secret access logs; rotate any secret that may have been exposed in a log or error message. + +See [Secrets Management](../../2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md) for a comprehensive treatment. + +### Least privilege in pipeline jobs + +```yaml +# GitHub Actions: least-privilege permissions block — deny all by default +permissions: + contents: read # read source code only + packages: write # push to GHCR only + id-token: write # OIDC token for cloud auth only +``` + +Teach developers to: +- Always declare an explicit `permissions:` block; never rely on the workflow-level default which may be overly broad. +- Audit what each job actually needs and remove anything it does not use. +- Treat pipeline tokens like production credentials — they often have equivalent or greater blast radius. + +### Pinning and provenance + +```yaml +# Unpinned (dangerous) — the tag can be moved at any time +- uses: actions/checkout@v4 + +# Pinned to an immutable digest (safe) +- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 +``` + +Teach developers that mutable tags on third-party Actions and container images are a supply-chain attack surface. A tag can be updated without warning to point to a malicious commit. + +### Runner hardening + +- Use **ephemeral runners** that are created fresh for each job and destroyed immediately after. A persistent runner accumulates state (secrets cached in memory, files on disk) that can be extracted by later jobs. +- **Restrict network egress** — a build job that can reach any internet host can be used for DNS exfiltration or to phone home to attacker infrastructure. Allowlist the registries and package sources the build actually needs. +- Treat self-hosted runners as **sensitive production infrastructure**: harden the OS, apply updates, monitor for anomalous processes, and rotate host credentials regularly. + +### Reading and triaging scanner output + +Not all developers arrive with the ability to interpret SAST, SCA, and IaC scanner results. Train them to: + +- Understand what each scanner type finds and where it has blind spots. +- Distinguish true positives from false positives using the context the scanner cannot see. +- Triage by severity, exploitability, and reachability — not raw counts. +- Route findings to the right owner (fix it themselves vs escalate to AppSec vs accept with documentation). + +## How to deliver it + +- Bake examples into the team's **actual** pipeline templates so lessons map to real configuration they will modify. +- Pair training with a hardened **paved-road** pipeline so the secure way is also the default way — developers who understand why the template is structured the way it is maintain it better. +- Use realistic exercises: have teams find and fix a poisoned-pipeline or leaked-token scenario in a safe environment. +- Keep platform and security engineers especially current — they design the controls everyone else inherits, so a gap in their knowledge propagates. + +## Common pitfalls + +- **Treating CI/CD security as "security team's problem"** — pipeline configuration is written by developers and platform engineers. They must own its security. +- **Long-lived tokens everywhere** — the path of least resistance is to create a PAT with broad scope and paste it into every pipeline. OIDC workload identity eliminates this pattern. +- **Never reviewing third-party Actions** — accepting a GitHub Actions update without reviewing what changed is equivalent to accepting a code change without review. +- **No egress monitoring** — without monitoring outbound network connections from runners, a data exfiltration via DNS or HTTP to an attacker-controlled host is invisible. +- **Shared self-hosted runners across security boundaries** — if a fork PR from an external contributor can run code on a self-hosted runner that also serves internal jobs, the isolation has been broken. + +## Maturity progression + +| Level | Practice | +|---|---| +| Starting | Secrets not hardcoded in pipeline config; branch protection enforced; SAST and SCA runs in CI | +| Developing | OIDC workload identity for cloud auth; Actions pinned to commit SHA; ephemeral runners for sensitive jobs | +| Maturing | Egress filtering on runners; Harden-Runner or equivalent monitoring; regular third-party Action audits | +| Advanced | Hermetic builds; full provenance generation (SLSA Level 2+); pipeline scanned with zizmor or similar; runner compromise detection | + +--- + +## Tools[^1] + +### Open-source + +- [OpenSSF Scorecard](https://github.com/ossf/scorecard) — Automated checks for security best practices on a repository: dependency pinning, branch protection, code review, vulnerability disclosure. Useful as a teaching baseline and a continuous metric. +- [StepSecurity Harden-Runner](https://github.com/step-security/harden-runner) — Network egress monitoring and runtime security for GitHub Actions runners. Generates an allowlist of outbound connections observed during the build, making unexpected calls visible. +- [zizmor](https://github.com/woodruffw/zizmor) — Static analysis for GitHub Actions workflow files. Detects PPE risks, overly broad permissions, unpinned Actions, and other configuration vulnerabilities. +- [actionlint](https://github.com/rhysd/actionlint) — A linter for GitHub Actions workflow files that catches syntax and logical errors before they hit CI. + +### Commercial + +- [GitHub Advanced Security](https://github.com/security/advanced-security) — Secret scanning, code scanning (CodeQL SAST), Dependabot SCA, and supply-chain features (dependency review, signing) integrated into GitHub. +- [GitLab Ultimate](https://about.gitlab.com/pricing/) — Built-in pipeline security scanning (SAST, DAST, SCA, secrets, container scanning) and compliance pipeline features baked into GitLab CI. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md b/current-version/1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md new file mode 100644 index 0000000..f45c865 --- /dev/null +++ b/current-version/1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md @@ -0,0 +1,108 @@ +# Security Culture and Awareness + +Tools and gates only work if people *want* security to succeed. A healthy **security culture** is what turns DevSecOps from a set of pipeline checks into a shared value. Where culture is poor, developers route around controls, hide findings, and treat security as someone else's problem. Where culture is strong, security becomes a normal part of how the team takes pride in its work. + +Culture is also the hardest thing to fix after the fact. Technical controls can be added overnight; cultural change takes months of consistent effort and must be led from the top. + +## Principles of a strong security culture + +- **Blameless** — treat vulnerabilities and incidents as learning opportunities, not occasions for punishment. Blame drives problems underground; psychological safety surfaces them. A team that fears blame for finding a bug will stop looking for bugs. +- **Shift-left by default** — security is everyone's job, owned closest to where the work happens, not bolted on at the end. The developer who writes the code is best positioned to secure it. +- **Low friction** — every unnecessary obstacle erodes goodwill. Invest in fast, accurate tooling and good developer experience so the secure path is also the easy path. Friction is the enemy of adoption. +- **Visible and rewarded** — celebrate good security behavior (a great threat model, a caught vulnerability, a well-written abuse case) as openly as a shipped feature. What gets rewarded gets repeated. +- **Led from the top** — leadership must fund security work, protect time for it, and model the behavior. Culture follows incentives. If the CISO and CTO never mention security in all-hands, teams will not either. + +## Practical ways to build it + +- **Reduce alert fatigue** — tune scanners, deduplicate findings, and prioritize by real risk so developers trust the signal. A developer who sees fifty medium-severity false positives every PR learns to ignore all findings. Noise is the fastest way to kill a security program. +- **Threat model as a team** — collaborative threat-modeling sessions spread security thinking far better than documents. The process of discussing "what can go wrong?" shapes how engineers think about future designs. +- **Blameless post-mortems after incidents** — the Goggle SRE blameless postmortem model, applied to security incidents, builds trust and generates actionable systemic improvements rather than scapegoating. +- **Awareness training for all staff** — phishing simulations and general awareness training for everyone, since social engineering targets people, not code. A developer's personal account compromise can become a business compromise. +- **Gamify and recognize** — capture-the-flag (CTF) events, bug-bash days, leaderboards, and shout-outs build engagement. Recognition in front of peers is often more motivating than financial incentives. +- **Embed in developer experience** — surface security feedback in the IDE and pull request, in the developer's language, at the moment it is actionable. Findings surfaced in the right place at the right time feel like help, not criticism. +- **Make metrics motivating, not punitive** — measure trends (mean time to remediate, escape rate) to improve the system, not to rank individuals or teams against each other. + +## Awareness program components + +A complete awareness program spans multiple audiences and channels: + +### Phishing simulations + +Send realistic (but safe) phishing campaigns to all staff to measure and improve click rates over time. Best practices: + +- Start with a baseline campaign before any training to understand where you are. +- Follow failures with **immediate, contextual micro-training** rather than punishment — the moment of failure is when learning is highest. +- Track click rates, report rates, and credential submission rates separately. +- Vary campaign types: credential harvesting, malicious attachment, pretexting, smishing (SMS phishing). +- Report trends to leadership, not individual names, to avoid creating a blame culture. + +### Role-based training + +Generic security training is less effective than training matched to the audience's actual threat surface: + +- **Developers** — secure coding, OWASP Top 10, AI-generated code review, secrets management. +- **DevOps / Platform engineers** — CI/CD pipeline security, supply-chain risks, container and IaC hardening. +- **System administrators** — privilege management, patch management, lateral movement awareness. +- **Finance and HR staff** — business email compromise (BEC), wire transfer fraud, social engineering. +- **Executives** — spear phishing, CEO fraud, data classification, regulatory obligations. + +### Onboarding + +Embed a mandatory, lightweight security module in every new employee's onboarding so the baseline is set from day one — before bad habits form. Include: password management policy, acceptable use, how to report a phishing email, who to contact for security questions. + +### Just-in-time nudges + +Surface policy reminders and security tips at decision points: + +- When a developer tries to push a secret — show why it is blocked and how to use the vault instead. +- When a reviewer approves a PR with a security warning — prompt them to confirm they have reviewed the finding. +- When a user grants broad access to a third-party app — remind them of the data minimization policy. + +### CTF and bug-bash events + +Periodic hands-on challenges build practical skills, create cross-team bonds around security, and surface talent for the champions program. A quarterly CTF event with prizes and a leaderboard dramatically increases security engagement. Bug bash days focused on a specific application or attack surface can find real vulnerabilities while training the team. + +## Measuring culture + +Culture is hard to measure directly, but proxies help: + +| Metric | What it signals | +|---|---| +| Champions program participation rate | Engagement and organizational investment | +| Training completion rates (by team) | Baseline compliance; low rates indicate friction | +| Phishing click rate trend | Improvement over time shows training effectiveness | +| Ratio of pre-merge vs post-merge findings | Cultural shift-left success | +| Mean time to remediate (MTTR) | Trust in the process; lower = less resistance to fixing | +| Developer satisfaction score for security tooling | Friction levels; tool adoption and quality | +| Security issues raised *by developers* (not by scanners) | Ultimate culture indicator — developers who see and report risk | + +Watch these over time and treat sustained friction as a signal to fix the system, not the people. + +## Common pitfalls + +- **Annual compliance training only** — a one-hour video at hire and then annually does not change behavior. Regular, relevant, just-in-time touchpoints do. +- **Naming and shaming phishing failures** — publicizing who clicked a phishing link creates fear, not learning. Blame-driven awareness training worsens psychological safety. +- **Ignoring developer experience as a culture factor** — a slow, noisy scanner that blocks builds on false positives is a culture problem. Developers who hate their security tools will route around all security processes. +- **Security awareness without security enablement** — telling developers they are responsible for security but not giving them time, tools, training, or champions support breeds frustration rather than ownership. +- **No executive modeling** — if senior leaders visibly bypass or ignore security controls, the message is clear: security is for other people. + +## Tools and platforms + +| Category | Examples | +|---|---| +| Phishing simulation | KnowBe4, Proofpoint Security Awareness Training, Hoxhunt, Gophish (open source — self-hosted) | +| Awareness training platforms | KnowBe4, SANS Security Awareness, Proofpoint, Infosec IQ | +| CTF platforms | Hack The Box (Enterprise), TryHackMe (Enterprise), PicoCTF, CTFd (open source, self-hosted) | +| Developer security training | Secure Code Warrior, Snyk Learn, SecureFlag, OWASP WebGoat, OWASP Juice Shop | +| Champions program management | Confluence/Jira (program tracking), OWASP Security Champions Playbook (framework) | +| Blameless postmortem tooling | Jira (incident templates), Confluence, GitHub incident retrospective templates | + +--- + +## Further reading + +- [OWASP SAMM — Education & Guidance](https://owaspsamm.org/model/governance/education-and-guidance/) +- [OWASP Security Culture project](https://owasp.org/www-project-security-culture/) +- [OWASP Security Champions Playbook](https://github.com/c0rdis/security-champions-playbook) +- [Google — Building Secure and Reliable Systems (culture chapters)](https://sre.google/books/building-secure-reliable-systems/) +- [Etsy — Blameless PostMortems and a Just Culture](https://www.etsy.com/codeascraft/blameless-postmortems/) diff --git a/current-version/2-Process/2-1-Design/2-1-1-Threat-modeling.md b/current-version/2-Process/2-1-Design/2-1-1-Threat-modeling.md index 459cd79..28f2f8f 100644 --- a/current-version/2-Process/2-1-Design/2-1-1-Threat-modeling.md +++ b/current-version/2-Process/2-1-Design/2-1-1-Threat-modeling.md @@ -1,145 +1,96 @@ # Threat Modeling -Threat modeling is a crucial component of the DevSecOps approach, focused on identifying and managing risks in a structured way. Here’s a more detailed look at this topic: +Threat modeling is a structured way to find security problems in a **design** before any code is written — the earliest and cheapest point to fix them. By reasoning about what you are building and how it could be attacked, teams uncover design flaws that no scanner can detect, because scanners only see implementation, not intent. -## What is Threat Modeling? +The cost of finding a design flaw in a whiteboard session is negligible. The cost of discovering the same flaw in production — after an incident — is orders of magnitude higher. Threat modeling is the discipline that closes that gap. -Threat modeling involves enumerating all potential attack vectors on an application, producing a list of threat scenarios along with mitigations. This holistic and collaborative process ensures comprehensive coverage of potential threats. +## The four key questions -Another important note is that Threat Modeling is a **Collaborative** and **Repeatable** process and it is a process **NOT** a project! +The [Threat Modeling Manifesto](https://www.threatmodelingmanifesto.org/) frames the practice around four questions: -### Key Outputs +1. **What are we working on?** — diagram the system, data flows, and trust boundaries. +2. **What can go wrong?** — enumerate threats against each component and flow. +3. **What are we going to do about it?** — decide on mitigations for the threats that matter. +4. **Did we do a good enough job?** — review and validate the model and its mitigations. -- **System Diagrams:** Detailed representations of the architecture and data flows. -- **Security Requirements:** Specific criteria for safeguarding the system. -- **Threat List:** Catalog of potential threats with mitigation strategies. +These questions are intentionally methodology-agnostic — they work whether your team uses sticky notes, a whiteboard, a formal tool, or code-based models. -### Terms +## Methodologies -- **Weakness:** A software defect or bug. (e.g., input validation errors, missing user email validation) -- **Vulnerability:** A weakness that can be exploited. (Ex: we can abuse the user email field to insert SQL statements) -- **Attack:** Exploitation of vulnerabilities. - - **Target:** The objective of the attack (e.g., sensitive data). - - **Attack Vector:** The path that the attacker can take to exploit a vulnerability (e.g., web interface). - - **Threat Actor:** The threat source (e.g., hacker, insider). -- **Attack Surface:** Anything that can be obtained, used, or attacked by a threat actor. -- **Risk:** Impact and likelihood of a threat being exploited (Risk = Impact x Likelihood). - - **Impact:** Size of negative consequences that each risk brings. - - **Likelihood:** Probability of a risk to happen. -- **Approach:** Describes how one could start with the process. -- **Methodology:** Describes the process itself. +- **STRIDE** — categorizes threats as Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, and Elevation of privilege. Each element in your data-flow diagram is examined against each STRIDE category. A good general-purpose starting point. +- **PASTA** — a seven-stage, risk-centric process (Process for Attack Simulation and Threat Analysis) that ties threats to business impact. Better suited to mature programs with defined risk appetite. +- **LINDDUN** — focuses on **privacy** threats (Linkability, Identifiability, Non-repudiation, Detectability, Disclosure of information, Unawareness, Non-compliance). Use alongside STRIDE for applications handling personal data. +- **Attack trees** — model how an attacker could reach a goal step by step. Excellent for high-value targets or specific threat scenarios where you want to reason about attacker economics. +- **OCTAVE** — operationally focused, suitable for organizations analyzing risk at the process and asset level rather than the feature level. -## Why Threat Modeling? +## Building the data-flow diagram -As benefits ofthreat modeling, we can say: +The data-flow diagram (DFD) is the foundation. A minimal DFD identifies: -- **Proactive Threat Identification:** Early discovery of potential security issues. -- **Cost Efficiency:** Mitigating threats early reduces remediation costs. -- **Prioritization:** Focus on the most critical vulnerabilities. -- **System Understanding:** Better comprehension of system interactions and data flows. +- **Processes** — components that transform or act on data (services, functions, jobs). +- **Data stores** — databases, caches, file systems, queues. +- **External entities** — actors outside the trust boundary (users, third-party services, partners). +- **Data flows** — how data moves between the above, including protocols and encryption status. +- **Trust boundaries** — lines across which data passes from a lower-trust to a higher-trust zone (or vice versa). Every crossing is a candidate threat. -## Who should be involved in the threat modeling? +Keep DFDs at the right level of abstraction: one diagram per service or bounded context is more useful than one giant diagram for the entire system. -- **Architect:** Knows how the application has been designed and how data flows across to ensure proper design and flow. -- **Developer:** Knows how the application was built, and the interactions between components to provide insight into code and interactions. -- **Tester:** Knows the requirements, and what the application is supposed to do, to validate requirements and behavior. -- **Security expert:** Knows about specific attack factors and vulnerabilities to identify and assess security risks. +## STRIDE applied — a worked example -But, the best answer to this question is, **it depends on the organization**. +For a REST API endpoint that accepts a user-uploaded file: -## When to perform Threat modeling? +| STRIDE category | Threat example | Mitigation | +|---|---|---| +| Spoofing | Caller forges user identity in request header | Validate JWT on every request, never trust client-supplied identity fields | +| Tampering | File content modified in transit | Enforce TLS; verify file hash after upload | +| Repudiation | Uploader denies submitting malicious file | Log upload events with authenticated user ID and file hash | +| Information disclosure | Error message leaks server path or stack trace | Sanitize error responses; log details server-side only | +| Denial of service | Attacker uploads gigabyte files to exhaust storage | Enforce file size limits and upload rate limits | +| Elevation of privilege | File is stored in a path the web server executes | Store uploads outside the web root; scan before serving | -Ideally, Threat Modeling should be performed early in the software design process. This allows for easier and cheaper fixes. +## Making it fit DevSecOps -In an Agile environment, Threat Modeling should be done during each sprint. But, we do not have to start from scratch each time. Each sprint only requires an iteration of the previous threat model output. +Traditional threat modeling was a heavyweight, document-driven exercise done once. To keep pace with agile delivery: -## Selecting the Right Approach & Methodology +- **Right-size it** — model the riskiest features and changes, not every story. A 30-minute whiteboard session beats a 40-page document nobody reads. +- **Do it continuously** — trigger a lightweight model update for any change that crosses a trust boundary, adds an external integration, or handles new categories of sensitive data. +- **Threat-model as code** — express models in version-controlled, diffable formats ([pytm](https://github.com/OWASP/pytm), [threagile](https://threagile.io/)) so they evolve with the system and integrate into CI pipelines for automated risk reporting. +- **Make it collaborative** — involve developers, architects, product managers, and security champions; the conversation is often more valuable than the artifact itself. +- **Close the loop** — every identified threat should produce a ticket in the backlog. Unmitigated threats should have an explicit risk-acceptance decision, not be silently ignored. -### Common Methodologies +## When to threat model -Common Threat Modeling methodologies are: +| Trigger | Scope | +|---|---| +| New service or major feature | Full model of the new component and its integrations | +| New external integration | Trust boundary analysis for the integration and its data | +| Authentication or authorization change | Focused STRIDE analysis on identity and access paths | +| Post-incident review | Update existing model to reflect how the attacker actually moved | +| Periodic refresh | Annual or semi-annual full model review | -- **PASTA (Process for Attack Simulation and Threat Analysis):** Focuses on business impact. -- **Microsoft Threat Modeling:** Uses data flow diagrams (DFDs) to identify threats. -- **OCTAVE (Operationally Critical Threat, Asset, and Vulnerability Evaluation):** Emphasizes organizational risk. -- **TRIKE:** A security auditing framework. -- **VAST (Visual, Agile, and Simple Threat):** Supports Agile development with automation. +## Common pitfalls -## Approaches +- **Modeling too late** — threat modeling *after* code is written captures fewer high-impact findings and produces expensive rework. Start during design. +- **Doing it alone** — security-team-only threat models miss the developer's knowledge of implementation nuance. Threat modeling is a team sport. +- **Treating it as a one-time gate** — a threat model written at project kickoff and never updated is misleading, not helpful. +- **Producing threats without owners** — every threat that warrants action must have an assigned owner and a ticket. Unowned threats disappear. +- **Ignoring the "did we do a good enough job?" question** — review your threat model against actual test results and penetration findings to calibrate model quality over time. -| **Approach** | **Steps** | -|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Asset-Centric** | 1. Identify and classify assets.
2. Diagram components and data flows.
3. Identify threats specific to each element. | -| **Attacker-Centric** | 1. Define potential threat actors (e.g., insiders, external hackers).
2. Determine their motives, means, and opportunities.
3. List and prioritize potential threats. | -| **Application-Centric** | 1. Create detailed diagrams of the application.
2. Identify threats for each element.
3. Use threat classification models (e.g., STRIDE, OWASP Top 10).
4. Rank threats using risk classification models (e.g., DREAD - Damage, Reproducibility, Exploitability, Affected Users, Discoverability). | +## Metrics -## Detailed Steps for Each Approach +- Number of threat-modeled features per quarter vs total features shipped. +- Average threats identified per model (rising over time suggests improving depth; sudden drops suggest model quality degraded). +- Percentage of modeled threats with closed mitigations within the sprint. +- Vulnerabilities discovered in production that were not in the threat model (escape rate — a calibration metric). -### Asset-Centric +## Maturity progression -1. Asset Identification: - - List all assets, including data, software, and hardware. - - Classify assets based on their criticality and sensitivity. -2. Component Diagramming: - - Use data flow diagrams (DFDs) to map out interactions. - - Highlight trust boundaries and data entry points. -3. Threat Identification: - - Analyze each component for possible threats. - - Use tools like Microsoft Threat Modeling Tool to automate threat discovery. -4. Threat Mitigation: - - Develop specific countermeasures for each identified threat. - - Prioritize mitigations based on risk assessment. - -### Attacker-Centric - -1. Threat Actor Identification: - - Identify potential attackers (e.g., external hackers, malicious insiders). - - Categorize actors by their access level and intent. -2. Attacker Profiling: - - Understand attackers’ goals and capabilities. - - Use threat intelligence sources to gather information about typical attack methods. -3. Threat Enumeration: - - List potential attack scenarios. - - Use attack trees to map out how an attacker might exploit vulnerabilities. -4. Threat Mitigation: - - Implement defenses like intrusion detection systems, access controls, and encryption. - - Regularly update threat profiles and defenses based on new intelligence. - -### Application-Centric - -1. Application Diagramming: - - Create detailed architecture diagrams. - - Include data flows, components, and interactions. -2. Threat Identification: - - Apply models like STRIDE or OWASP Top 10 to each component. - - Identify threats such as spoofing, tampering, and data breaches. -3. Risk Assessment: - - Use the DREAD model to evaluate threats. - - Rank threats based on their potential impact and exploitability. -4. Threat Mitigation: - - Develop countermeasures for high-risk threats. - - Implement secure coding practices and conduct regular security reviews. - -## What is DREAD? - -DREAD is a risk assessment model used in cybersecurity to evaluate and prioritize potential threats. The acronym stands for: - -- **Damage potential:** Assessing the potential damage that could result from a successful exploit. -- **Reproducibility:** Evaluating how easily the exploit can be replicated. -- **Exploitability:** Determining the ease with which the vulnerability can be exploited. -- **Affected users:** Identifying the number of users or systems affected by the vulnerability. -- **Discoverability:** Assessing how easily the vulnerability can be discovered. - -Each of these factors is typically scored on a scale, often from 0 to 10, with higher scores indicating a greater level of risk. - -## Practical Steps for Threat Modeling - -1. **Define Scope:** Identify boundaries of the system and critical assets. -2. **Create Diagrams:** Develop DFDs and architecture diagrams. -3. **Identify Threats:** Use methodologies like STRIDE to discover potential threats. -4. **Analyze Threats:** Assess risk using models like DREAD. -5. **Develop Mitigations:** Define strategies to mitigate identified threats. -6. **Review and Iterate:** Regularly update the threat model throughout the development lifecycle. +| Level | Practice | +|---|---| +| Starting | Ad-hoc whiteboard sessions for highest-risk features; output is a list of threats in the backlog | +| Developing | STRIDE applied consistently to all new features crossing trust boundaries; DFDs stored in the repo | +| Defined | Threat-model-as-code (pytm or threagile) integrated into CI; model reviews at sprint milestones | +| Advanced | Automated threat generation from architecture diagrams; threat model findings correlated with SAST/DAST/pentest findings | --- @@ -147,22 +98,28 @@ Each of these factors is typically scored on a scale, often from 0 to 10, with h ### Open-source -- [CAIRIS](https://cairis.org/): A tool for building models and conducting risk assessments based on these models. -- [Microsoft Threat Modeling Tool](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool) - A tool for creating data flow diagrams and identifying threats using STRIDE. -- [OWASP Threat Dragon](https://owasp.org/www-project-threat-dragon/) - An open-source tool for creating threat model diagrams and managing threats. -- [threat-composer](https://github.com/awslabs/threat-composer?tab=readme-ov-file) - A simple threat modeling tool to help humans to reduce time-to-value when threat modeling. +- [OWASP pytm](https://github.com/OWASP/pytm) — A Python-based framework for expressing threat models as code. Generates DFDs, sequence diagrams, and STRIDE reports from a Python definition file. Integrates into CI. +- [OWASP Threat Dragon](https://owasp.org/www-project-threat-dragon/) — Free, open-source threat modeling tool with a visual DFD editor and STRIDE categorization. Stores models as JSON for version control. +- [OWASP ThreatAtlas](https://github.com/OWASP/ThreatAtlas) — A community-maintained, structured knowledge base of real-world threats mapped to attack patterns, MITRE ATT&CK techniques, and mitigations. Where Threat Dragon helps you *create* a model, ThreatAtlas helps you *populate* it with curated, evidence-based threat intelligence drawn from documented incidents. Use it during the "what can go wrong?" phase to ensure your threat library reflects the actual attacker landscape rather than only theoretical concerns. +- [Threagile](https://threagile.io/) — Agile, YAML-based threat modeling. Takes a YAML model of your architecture and outputs a risk report with data-flow diagrams. Designed for CI integration. +- [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) — MITRE CTID project for modeling sequences of adversary actions using ATT&CK techniques. Useful for post-incident and red team threat analysis. ### Commercial -- [IriusRisk](https://www.iriusrisk.com/threat-modeling-platform) - A platform for automated threat modeling and risk management. -- [ThreatModeler](https://threatmodeler.com/) - An enterprise-grade tool for automated threat modeling, integrating with CI/CD pipelines. +- [IriusRisk](https://www.iriusrisk.com/) — Automated threat modeling platform with rules-based threat generation from architecture questionnaires. Integrates with Jira for backlog creation. +- [SD Elements](https://www.securitycompass.com/sdelements/) — Combines threat modeling with security requirements management; generates tasks directly into the development backlog. +- [Microsoft Threat Modeling Tool](https://aka.ms/threatmodelingtool) — Free from Microsoft; focuses on DFD-based STRIDE analysis. Best suited to Microsoft-stack environments. --- ### Links -- [Awesome Threat Modeling](https://github.com/hysnsec/awesome-threat-modelling) -- [OWASP - Threat Modeling](https://owasp.org/www-community/Threat_Modeling) -- [Threat Modeling Cheat Sheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Threat_Modeling_Cheat_Sheet.md) - [^1]: Listed in alphabetical order. + +## Further reading + +- [Threat Modeling Manifesto](https://www.threatmodelingmanifesto.org/) +- [OWASP Threat Modeling Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Threat_Modeling_Cheat_Sheet.html) +- [OWASP ThreatAtlas](https://github.com/OWASP/ThreatAtlas) +- [Adam Shostack — Threat Modeling: Designing for Security](https://www.wiley.com/en-us/Threat+Modeling%3A+Designing+for+Security-p-9781118809990) +- [STRIDE per Element — Microsoft Security Blog](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats) diff --git a/current-version/2-Process/2-1-Design/2-1-2-Secure-design-and-requirements.md b/current-version/2-Process/2-1-Design/2-1-2-Secure-design-and-requirements.md new file mode 100644 index 0000000..34c40b6 --- /dev/null +++ b/current-version/2-Process/2-1-Design/2-1-2-Secure-design-and-requirements.md @@ -0,0 +1,117 @@ +# Secure Design and Requirements + +Threat modeling asks "what can go wrong?"; **secure design and requirements** answer "what must be true for this to be safe?" — *before* implementation begins. Security requirements that are written down become testable, and design decisions made early are far cheaper than retrofits. A whole class of vulnerabilities — the [OWASP Top 10's "Insecure Design"](https://owasp.org/Top10/A04_2021-Insecure_Design/) category — exists precisely because security was never a design input. + +## Secure-by-design principles + +These principles are not checklists to be stamped once and forgotten — they are design lenses applied throughout every architecture and feature decision: + +- **Least privilege** — every component, service, and identity gets only the access it needs, for only the duration it needs it. An overprivileged service that gets compromised becomes a high-blast-radius incident. +- **Defense in depth** — never rely on a single control; assume any one layer can fail. A WAF is not a substitute for input validation; encryption at rest is not a substitute for access control. +- **Fail securely** — errors and edge cases must default to denying access, not granting it. An unhandled exception that returns a `200 OK` with empty data is less dangerous than one that returns a `500` with a stack trace — but both are worse than returning a clean `403`. +- **Minimize attack surface** — fewer features, ports, endpoints, and dependencies mean fewer ways in. Disable or remove anything not required. Every "just in case" API endpoint is a liability. +- **Secure defaults** — the out-of-the-box configuration should be the safe one; security should not require opt-in. Encryption, authentication, and safe error handling should be on by default. +- **Complete mediation** — check authorization on every access to every resource, not just the first request in a session. Cached authorization decisions become stale; privileged routes must validate on every call. +- **Separation of duties** — no single entity should be able to complete a high-risk action alone. Critical operations (e.g., production deploys, key rotation) require two parties. +- **Privacy by design** — build in data minimization and protection from the start. Collect only what you need; retain only as long as required. See [Data Protection](../../3-Governance/3-2-Data-protection.md). + +## Security requirements + +Principles are not enough — they must be translated into concrete, verifiable requirements that live in the same backlog as functional requirements. + +### Using OWASP ASVS + +The [OWASP Application Security Verification Standard (ASVS)](https://owasp.org/www-project-application-security-verification-standard/) provides a catalog of hundreds of security requirements organized by category (authentication, session management, cryptography, API, etc.) at three levels: + +- **Level 1** — opportunistic; suitable for all applications. Covers basic security hygiene. +- **Level 2** — standard; suitable for applications handling sensitive data. The target for most business applications. +- **Level 3** — advanced; for critical applications (financial, healthcare, infrastructure). Requires formal verification of controls. + +Select your ASVS level based on the application's risk classification, then import the relevant requirements into your backlog at project kick-off. + +### Abuse cases alongside user stories + +For every significant user story, write a corresponding abuse case that describes the same scenario from an attacker's perspective: + +> **User story:** "As a customer, I can reset my password using my email address." +> +> **Abuse case:** "As an attacker, I can trigger password resets for accounts I do not own, either locking out legitimate users or using predictable tokens to take over accounts." +> +> **Security acceptance criteria:** Rate-limit reset requests to 5 per hour per account; reset tokens must be cryptographically random (≥128 bits), single-use, and expire in 15 minutes; token delivery channel must be confirmed before issuing. + +### Security acceptance criteria in stories + +Add a security acceptance criteria section to your story template alongside functional acceptance criteria. This makes security testable by QA and automated tests, not optional. + +``` +## Security Acceptance Criteria +- [ ] Input is validated server-side (type, length, allowlist where applicable) +- [ ] Output is encoded for the rendering context +- [ ] Authorization check performed for every state change +- [ ] Sensitive fields not logged or included in error responses +``` + +## Secure design patterns and paved roads + +Reusing vetted patterns beats reinventing security per project: + +- **Centralized authentication and authorization** — use a shared, audited auth library or identity provider rather than bespoke per-service implementations. Custom auth code is one of the most common sources of high-severity vulnerabilities. +- **Centralized input validation and output encoding** — a shared library that enforces allowlists, maximum lengths, and context-aware encoding eliminates entire vulnerability classes across every consumer. +- **Platform paved road** — golden templates, hardened base images, pre-configured infrastructure modules, and approved building blocks let product teams inherit secure design rather than design it from scratch. The paved road makes the secure choice the path of least resistance. +- **Architecture decision records (ADRs)** — document security trade-offs and rationale in version-controlled ADRs. Future teams need to understand *why* a design is the way it is, not just what it is. An undocumented security constraint is a constraint that gets accidentally removed. + +## Design review checklist + +Run this at the end of every design phase before implementation begins: + +- [ ] Authentication, authorization, and session management fully designed — not left as an implementation detail. +- [ ] Sensitive data classified; encryption strategy chosen for data at rest and in transit. +- [ ] All third-party integrations enumerated; trust level and data sharing scope defined for each. +- [ ] Error handling and logging strategy defined — sensitive data must not appear in logs or error responses. +- [ ] Abuse cases documented for every high-value or high-risk feature. +- [ ] ASVS level selected and applicable requirements imported into the backlog. +- [ ] Threat model created or updated for the design — see [Threat Modeling](2-1-1-Threat-modeling.md). +- [ ] Data flows across trust boundaries documented and reviewed. +- [ ] No hardcoded credentials, keys, or environment-specific values in design artifacts. + +## Common pitfalls + +- **Delegating auth to "the framework"** without understanding what the framework actually enforces. Frameworks provide primitives; correct design is still required. +- **Designing for the happy path only** — edge cases, error conditions, and concurrent access patterns are where security breaks. +- **ASVS level mismatch** — selecting Level 1 for a system that handles payment data or health records because it is "quicker to implement." +- **No security requirements in the backlog** — security work that isn't tracked doesn't get estimated, prioritized, or completed. +- **Paved road as an island** — building golden templates once and never updating them. Stale templates propagate known vulnerabilities across every new service. + +## Industry direction + +Regulators and vendors are converging on secure-by-design as a baseline expectation. [CISA's Secure by Design](https://www.cisa.gov/securebydesign) initiative asks software producers to take ownership of customer security outcomes and design products that are secure out of the box. The EU Cyber Resilience Act takes this further by making security-by-design a legal obligation for products with digital elements sold in the EU. + +## Maturity progression + +| Level | Practice | +|---|---| +| Starting | Security principles referenced in design reviews; ASVS Level 1 requirements added to high-risk stories | +| Developing | Abuse cases written for all significant features; ASVS level selected per application; security acceptance criteria in story template | +| Defined | Paved road with golden templates and shared libraries; ADRs document security decisions; ASVS requirements tracked in backlog | +| Advanced | Automated ASVS requirement generation from threat model output; design reviews gated on completion of abuse cases and security criteria | + +## Tools + +| Category | Examples | +|---|---| +| Security requirements management | SD Elements (generates tasks from questionnaire), Jira (with security issue types and templates), OWASP ASVS spreadsheet | +| ASVS tooling | OWASP ASVS project (PDF/spreadsheet), OWASP SKF (Security Knowledge Framework — maps ASVS to code examples) | +| Threat modeling (link with design) | OWASP Threat Dragon, Threagile, IriusRisk — see [Threat Modeling](2-1-1-Threat-modeling.md) | +| Architecture diagramming | draw.io (supports DFDs), Mermaid (version-controllable diagrams as code), PlantUML, Structurizr | +| Secure design patterns reference | OWASP Cheat Sheet Series, OWASP Proactive Controls, OWASP ASVS | + +--- + +## Further reading + +- [OWASP ASVS](https://owasp.org/www-project-application-security-verification-standard/) +- [OWASP Top 10 — A04 Insecure Design](https://owasp.org/Top10/A04_2021-Insecure_Design/) +- [OWASP Proactive Controls](https://owasp.org/www-project-proactive-controls/) +- [OWASP Security Knowledge Framework (SKF)](https://owasp.org/www-project-security-knowledge-framework/) +- [CISA Secure by Design](https://www.cisa.gov/securebydesign) +- [EU Cyber Resilience Act](https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act) diff --git a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md index 5ac88a2..bddc38a 100644 --- a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md +++ b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md @@ -1,23 +1,129 @@ # Pre-commit -The Pre-commit phase is important because it can prevent security issues before they are submitted to a central (Git) repository. - -Making sure that there are no secrets in the code, and that the code follows certain guidelines (According to the Linter rules) will result in a higher quality code. - -In the following, we take a look into different types of pre-commit actions that are as follows: - -1. Secrets Management -2. Linting Code - -**Pre-commit** is a git feature that can be leveraged as part of the **shift-left security** approach where the developers are empowered to view the issues in the source code earlier in the SDLC process. When the developer runs a git-commit command to commit the code into their local repository, **pre-commit hook** check can be integrated with a security scanning tool executed to look for code quality issues, hard-coded secrets, insecure code, vulnerable dependencies/opensource libraries, etc.. - -It is to be noted that pre-commit hooks are at the developer's local repository level and not the remote repository commonly used by all the developers working on the same project/application. In such cases when it's required to prevent security issues before they are submitted to a remote/central (Git) repository **pre-push hook** or **git-push** checks can be configured. Refer: - -Another alternative approach to scan the source code for security issues (such as hardcoded-secrets, insecure code and vulnerable dependencies/opensource libraries) is the use of **SAST/SCA IDE plugins**. This works together with the IDEs used by developers while they write the code. Whereas, git-commit and git-push actions are used after the code is written by the developer. It is necessary to discern these distinct use-cases in order to implement the proper security controls at various levels based on the requirement. - -The following image can give you a better view of what the pre-commit means and why we must consider it. - -![Pre Commit](/current-version/assets/images/pre-commit.png) +Pre-commit hooks are the **earliest possible shift-left gate** — they run on the developer's machine *before* code is even committed, giving feedback in seconds rather than minutes (CI) or days (review). Catching a leaked secret, a syntax error, or an obvious vulnerability here is the cheapest fix in the entire lifecycle. + +## What pre-commit hooks are + +Git supports client-side hooks that fire on events like `commit`, `push`, and `merge`. Managing these by hand across a team is painful and inconsistent: hooks live in `.git/hooks/`, which is not committed to the repository, so every developer's environment diverges over time. + +The widely adopted [pre-commit](https://pre-commit.com/) framework solves this. It installs, versions, and runs hooks consistently by reading a `.pre-commit-config.yaml` file that *is* committed to the repo. Every developer runs the same checks against the same tool versions, and onboarding is a one-time `pre-commit install`. + +```bash +# One-time setup per developer +pip install pre-commit +pre-commit install # installs the git hook +pre-commit install --hook-type pre-push # optional: also run on push +``` + +## A practical `.pre-commit-config.yaml` + +```yaml +# .pre-commit-config.yaml +repos: + # Secret scanning — highest priority, runs first + - repo: https://github.com/gitleaks/gitleaks + rev: v8.21.2 + hooks: + - id: gitleaks + + # General file hygiene + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-json + - id: check-toml + - id: detect-private-key + - id: check-added-large-files + args: ['--maxkb=500'] + - id: no-commit-to-branch + args: ['--branch', 'main', '--branch', 'master'] + + # Python SAST + - repo: https://github.com/PyCQA/bandit + rev: 1.7.9 + hooks: + - id: bandit + args: ['-c', 'pyproject.toml'] + files: '\.py$' + + # Semgrep for polyglot SAST (fast subset of rules) + - repo: https://github.com/returntocorp/semgrep + rev: v1.x.x + hooks: + - id: semgrep + args: ['--config', 'p/default', '--error'] +``` + +Pin `rev` values to exact tags or SHAs, not `latest`, to make hook execution reproducible and to avoid supply-chain attacks via mutable tags. + +## What to run at pre-commit + +Keep hooks **fast** — hooks that exceed 10–15 seconds get bypassed or disabled. Optimize for signal-to-noise and speed: + +| Check | Why | Typical duration | +|---|---|---| +| Secret scanning | Blocks credentials before they enter history — the most important hook | < 2s | +| Detect private key | Catches PEM/key files committed accidentally | < 1s | +| Large file blocking | Prevents binaries bloating git history | < 1s | +| YAML/JSON/TOML validation | Catches broken config files before they reach CI | < 1s | +| Security linting (Semgrep/Bandit) | Fast rule-based SAST for the most common vulnerability patterns | 2–10s | +| Code formatting (Black, Prettier) | Eliminates style noise in code review | 2–5s | +| No-commit-to-branch | Prevents accidental direct commits to protected branches | < 1s | + +Avoid running full test suites, slow SAST scans, or network-dependent checks at pre-commit. Those belong in CI. + +## Running hooks in CI + +Client-side hooks improve developer experience but are **not a security control on their own** — any developer can skip them with `--no-verify`. Always mirror the same checks server-side in CI: + +```yaml +# GitHub Actions example — mirrors pre-commit checks +- name: Run pre-commit hooks + uses: pre-commit/action@v3.0.1 + env: + SKIP: no-commit-to-branch # skip branch-protection hooks in CI context +``` + +This creates a two-layer model: +- **Pre-commit (local):** fast feedback for the developer, zero round-trip time. +- **CI (server-side):** authoritative, un-bypassable enforcement. + +A finding blocked in CI but caught locally first costs nothing. A finding that reaches CI first costs a pipeline run and a developer context-switch. + +## Keeping hooks up to date + +Hook versions drift. Run `pre-commit autoupdate` periodically (or as a scheduled CI job) to pull the latest revisions of each hook: + +```bash +pre-commit autoupdate +git commit -am "chore: update pre-commit hook versions" +``` + +## Common pitfalls + +- **Skipping with `--no-verify`** — a common response to slow or noisy hooks. Fix the noise; don't suppress the gate. If developers reach for `--no-verify` routinely, the hooks are misconfigured. +- **Not pinning hook versions** — using `rev: main` or a branch means hook behavior silently changes. Pin to a tag or SHA. +- **Running too much** — hooks that take 30+ seconds drive developers to bypass them. Keep pre-commit under 15 seconds total. +- **Treating pre-commit as the only gate** — it is not. Enforce the same checks in CI. +- **No onboarding documentation** — if `pre-commit install` is not in the project README or onboarding guide, new developers skip it. + +## Metrics + +- Percentage of team members with hooks installed (measure via CI — jobs that skip hooks without explanation can be flagged). +- Number of secrets blocked at pre-commit vs caught in CI or later (pre-commit blocks should be the large majority). +- Hook execution time trend — rising times indicate hook bloat and predict bypass rates. + +## Maturity progression + +| Level | Practice | +|---|---| +| Starting | `pre-commit` installed with secret scanning and basic file hygiene; developers install manually | +| Developing | Standard `.pre-commit-config.yaml` committed to all repos; onboarding automates `pre-commit install`; mirrored in CI | +| Defined | Hook versions pinned and auto-updated by a scheduled job; security linting (Semgrep) included; metrics tracked | +| Advanced | Org-wide hook baseline enforced via a shared config; violations in CI block merge; coverage tracked per repo | --- @@ -25,10 +131,19 @@ The following image can give you a better view of what the pre-commit means and ### Open-source -- [Pre-Commit](https://pre-commit.com/) - A framework for managing and maintaining multi-language pre-commit hooks. +- [Husky](https://typicode.github.io/husky/) — Git hooks manager popular in JavaScript/Node projects. Hooks are defined in `package.json` or `.husky/`. Works well with lint-staged for running checks only on staged files. +- [Lefthook](https://github.com/evilmartians/lefthook) — Fast, polyglot Git hooks manager written in Go. Supports parallel hook execution and per-file filtering. Good alternative to `pre-commit` for multi-language monorepos. +- [pre-commit](https://pre-commit.com/) — The most widely adopted multi-language framework for managing pre-commit hooks. Declarative YAML config, plugin ecosystem, CI integration, autoupdate support. +- [lint-staged](https://github.com/lint-staged/lint-staged) — Runs linters only on git-staged files. Often paired with Husky to keep pre-commit fast by scoping checks to changed files only. -### Links +--- -- [Wikipedia - Lint (software)](https://en.wikipedia.org/wiki/Lint_(software)) +### Links [^1]: Listed in alphabetical order. + +## Further reading + +- [pre-commit documentation](https://pre-commit.com/) +- [OWASP Cheat Sheet — Vulnerable Dependency Management](https://cheatsheetseries.owasp.org/cheatsheets/Vulnerable_Dependency_Management_Cheat_Sheet.html) +- [Gitleaks — secret scanning hook](https://github.com/gitleaks/gitleaks) diff --git a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md index 1d2441c..ed1b9ad 100644 --- a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md +++ b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md @@ -1,66 +1,194 @@ -# Take care secrets and credentials +# Secrets Management -*How can you ensure that sensitive information are not pushed to a repository?* +Hardcoded secrets — API keys, passwords, tokens, private keys — are one of the most common and most damaging mistakes in software delivery. Once a secret reaches a git repository it must be considered compromised: history is hard to scrub, repos get cloned and forked, and automated bots scan public commits within seconds of a push. Secrets management spans **preventing** secrets from being committed and **handling** the secrets applications legitimately need at runtime. -This is one of the [OWASP Top Ten issues](https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure) and -several bug bounties write-ups are related to this kind of issue, eg hard-coded credentials pushed by mistake. +## Why this matters -You should scan your commits and your repository, and detect any sensitive information such as password, secret key, confidential, etc. -following the process shown in the picture. +A single leaked AWS access key can result in complete account takeover, data exfiltration, and cloud bill fraud within minutes. The 2022 Toyota source code exposure and numerous cloud breaches trace back to credentials committed to source control. Preventing secrets from entering repositories is one of the highest-impact, lowest-effort security investments a team can make. -The ideal approach is detecting and preventing the exposure of sensitive data before that they hit the repository, -because they are then visible in the history. In case of code hosting platforms, secrets can still linger -on the web and be searchable after you remove them from the repository. +## Detecting and preventing leaked secrets -A complimentary approach is scanning the repo for sensitive information, and then remove them; -note that when a credential is leaked, it is already compromised and should be invalidated. +Apply detection at every layer — defense in depth works here too: -## Detecting secrets in several locations +### Layer 1: Pre-commit (local) -- **Detecting existing secrets** by searching in a repository for existing secrets. -- **Using Pre-commit hooks** in order to prevent secrets for entering our code base. -- **Detecting secrets in a pipeline** . +Block secrets before they enter history. This is the cheapest catch because no pipeline time is consumed and no rotation is required. -## Why Detecting Secrets? +```yaml +# .pre-commit-config.yaml +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.21.2 + hooks: + - id: gitleaks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: detect-private-key +``` -- The secrets should not be hardcoded. -- The secrets should not be unencrypted. -- The secrets should not be stored in source code. -- The code history does not contain inadvertent secrets. +See [Pre-commit](2-2-1-1-Pre-commit.md) for full framework setup. -## Where and when to Detect Secrets? +### Layer 2: CI pipeline scanning -![Pre Commit](/current-version/assets/images/pre-commit.png) +Mirror the same detection server-side so it cannot be bypassed with `--no-verify`. Run on every pull request and on full git history at least weekly. -Well, the best location is the **pre-commit** location, This ensure that before a secret actually enters your code base, it is intercepted, and the developer or to committer gets a message. Using **SAST IDE plugins** comes in handy while trying to fix such issues where the IDE warnings can be found as soon as the developer writes an insecure code with security misconfigurations. Another location is the build server or the **build** process. The build server retrieves source code, which is already committed and then it can analyze the source code where it contains new secrets or when it contains known secrets that the secrets are actually validated or audited. +```yaml +# GitHub Actions example +- name: Secret scan (TruffleHog) + uses: trufflesecurity/trufflehog@main + with: + path: ./ + base: ${{ github.event.repository.default_branch }} + head: HEAD + extra_args: --only-verified +``` ---- +### Layer 3: Push protection + +Platform-level push protection (GitHub Secret Scanning push protection, GitLab secret detection) rejects pushes that contain recognized secret patterns server-side, before the commit is accepted. Enable for all repositories — this is a free, high-signal defense. + +### Layer 4: Historical scanning + +New commits are not the only risk. Periodically scan full git history to catch secrets committed before scanning was in place. + +```bash +# Full-history scan with TruffleHog +trufflehog git file://. --since-commit HEAD~500 --only-verified --fail +``` + +### Layer 5: Public exposure monitoring + +Subscribe to GitHub secret scanning alerts (for public repos) and consider services that monitor paste sites and code-hosting platforms for your organization's credential patterns. + +## Incident response for a leaked secret + +If a secret is discovered in history: + +1. **Rotate it immediately** — revoke the exposed credential in the issuing system first, before anything else. Removing it from history does not protect you; bots may have already scraped it. +2. **Audit usage logs** — check the credential's access logs for unauthorized use. +3. **Clean history (optional)** — use `git filter-repo` or BFG Repo Cleaner to remove the secret, then force-push and notify all cloners. This is secondary to rotation. +4. **Document and notify** — follow your incident response process; if personal data was accessible via the credential, privacy breach obligations may apply. + +## Managing the secrets applications need at runtime + +Applications and pipelines legitimately need credentials. The question is how to provide them safely. + +### Never do this + +- Hardcode secrets in source code. +- Store secrets in `.env` files committed to the repo. +- Bake secrets into container images at build time. +- Pass secrets as plain-text environment variables in CI job definitions. +- Share secrets in Slack, email, or Confluence pages. + +### Use centralized secret vaults + +A dedicated secrets manager is the foundation: + +- Secrets are stored encrypted with access controls and audit logs. +- Applications retrieve secrets at runtime via API, not at build time. +- Access is controlled by identity (IAM role, service account, workload identity) rather than by shared passwords. + +```bash +# HashiCorp Vault: read a secret at runtime +vault kv get -field=api_key secret/myapp/prod +``` + +### Use dynamic / short-lived secrets + +Static, long-lived credentials are a liability — if leaked, they remain valid until someone notices and rotates them. Dynamic secrets expire automatically: -Here are some helpful tools to automatically scan repositories for sensitive information. -Scans can be implemented directly in our pipeline, and be repeatable and efficient. +```hcl +# Vault database secrets engine — generates a PostgreSQL credential valid for 1 hour +path "database/creds/my-role" { + capabilities = ["read"] +} +``` + +HashiCorp Vault, AWS Secrets Manager, and similar platforms can generate database credentials, cloud IAM credentials, and TLS certificates on demand with a short TTL. + +### Use workload identity / OIDC for CI/CD + +The strongest pattern for CI/CD pipelines: no long-lived cloud credentials stored anywhere. Instead, the CI platform issues a short-lived OIDC token that the cloud provider's IAM validates, granting a scoped role. + +```yaml +# GitHub Actions — OIDC-based AWS access (no stored AWS keys) +permissions: + id-token: write + contents: read + +steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::123456789012:role/my-github-actions-role + aws-region: us-east-1 +``` + +This eliminates AWS access keys from GitHub secrets entirely. Apply the same pattern for GCP (Workload Identity Federation) and Azure (federated credentials). + +### Rotation + +Automate rotation so credentials change on a schedule and after any potential exposure: + +- Cloud secret managers (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager) support automatic rotation with Lambda/Function hooks. +- Vault supports lease renewal and automatic rotation for supported secret engines. +- Track rotation cadence per secret type; critical credentials (production database passwords) should rotate more frequently than low-risk ones. + +### Least privilege and scoping + +Every secret should grant the minimum access needed, for the minimum time: + +- A CI job that only reads from S3 should not have a credential that can also delete objects or access other buckets. +- Scope API keys to specific endpoints or operations where the platform supports it. +- Use separate credentials per environment — never share a production credential with staging or development. + +## Metrics + +- Number of secrets detected at pre-commit vs CI vs in production (pre-commit share should be highest and rising). +- Number of active long-lived credentials vs short-lived / dynamic credentials (drive toward dynamic). +- Mean time to rotate a credential after discovery. +- Percentage of CI pipelines using OIDC / workload identity vs stored static keys. +- Age distribution of static credentials in use — aged credentials are a risk indicator. + +## Maturity progression + +| Level | Practice | +|---|---| +| Starting | Gitleaks or TruffleHog as a pre-commit hook; `.env` files in `.gitignore`; basic secret rotation on request | +| Developing | CI pipeline scanning on all PRs; push protection enabled; secrets stored in a vault; no static cloud keys in CI | +| Defined | Dynamic secrets for databases and cloud; OIDC for all CI/CD cloud access; automated rotation with audit logging | +| Advanced | Zero static credentials in production; secrets access tied to workload identity and attested pipeline provenance; anomaly detection on secret access patterns | + +--- ## Tools[^1] ### Open-source -- [Git Hound](https://github.com/ezekg/git-hound) - Git plugin that prevents sensitive data from being committed -- [git-secrets](https://github.com/awslabs/git-secrets) - Prevents you from committing secrets and credentials into git repositories -- [Github Secret Scanning](https://docs.github.com/en/code-security/secret-scanning) - Github built in feature for secret detection -- [gittyleaks](https://github.com/kootenpv/gittyleaks) - Find sensitive information for a git repo -- [Repo-supervisor](https://github.com/auth0/repo-supervisor) - Scan your code for security misconfiguration, search for passwords and secrets -- [truffleHog](https://github.com/dxa4481/truffleHog) - Searches through git repositories for high entropy strings and secrets, digging deep into commit history +- [detect-secrets](https://github.com/Yelp/detect-secrets) — Yelp's enterprise-grade secret detector. Maintains a baseline file of accepted findings so teams can manage existing issues without noisy blocking. +- [Gitleaks](https://github.com/gitleaks/gitleaks) — Fast, widely adopted secret scanner for git repos, history, and CI pipelines. Configurable rule sets and pre-commit hook support. +- [HashiCorp Vault](https://www.vaultproject.io/) — Full-featured secrets management platform. Supports dynamic secrets, leasing, rotation, PKI, and multiple auth methods. Open-source and enterprise editions. +- [TruffleHog](https://github.com/trufflesecurity/trufflehog) — Finds and actively *verifies* leaked credentials (confirms the credential is still valid) across git history, S3, Jira, Slack, and more. -### Commercial +### Commercial / managed -- [BluBracket](https://blubracket.com) - Prevent secrets and credentials in code -- [GitGuardian](https://gitguardian.com) - Keep secrets out of your source code -- [GitHub Advanced Security](https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning) - GitHub scans repositories for known types of secrets, to prevent fraudulent use of secrets that were committed accidentally -- [Nightfall](https://nightfall.ai) - Find and protect secrets and keys across the cloud -- [Spectralops](https://spectralops.io) - Developer-first Cloud Security -- [TruffleSecurity](https://trufflesecurity.com) - Unhearth your secrets +- [1Password Secrets Automation](https://developer.1password.com/) — Syncs secrets from 1Password vaults to apps and infrastructure via CLI, SDKs, and Kubernetes operator. +- [Akeyless](https://www.akeyless.io/) — SaaS zero-knowledge platform for secrets, certificates, and key management with a free tier. +- [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) — Managed secret storage with native rotation for RDS, Redshift, and custom Lambda rotators. +- [Azure Key Vault](https://azure.microsoft.com/en-us/products/key-vault/) — Managed key and secret storage for Azure workloads. +- [Doppler](https://www.doppler.com/) — SecretOps platform that syncs secrets across environments and injects them at runtime. Good developer UX for teams without a dedicated Vault deployment. +- [GCP Secret Manager](https://cloud.google.com/secret-manager) — Google Cloud's managed secret storage with IAM-based access control and audit logging. --- ### Links [^1]: Listed in alphabetical order. + +## Further reading + +- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html) +- [GitHub — About secret scanning](https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning) +- [HashiCorp Vault tutorials](https://developer.hashicorp.com/vault/tutorials) +- [GitHub OIDC — Configuring OpenID Connect in AWS](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) diff --git a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md index 052c08b..56b7d6a 100644 --- a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md +++ b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md @@ -1,49 +1,120 @@ # Linting Code -## What Is Linting? +Linting analyzes source code for stylistic issues, bugs, and suspicious patterns without running it. While linters started as style and quality tools, modern linters and their security plugins catch a meaningful share of security problems — making linting a fast, low-friction first line of defense that fits naturally in pre-commit and CI. -Linting is the automated checking of your source code for programmatic and stylistic errors. This is done by using a lint tool (otherwise known as linter). A lint tool is a basic static code analyzer. +## Why linting matters for security -## What can Linting do? +- **Consistency reduces risk** — consistent, readable code is easier to review and less likely to hide bugs in unexpected places. +- **Security rules catch real flaws** — many linters detect dangerous functions, injection-prone patterns, weak crypto usage, insecure randomness, and hardcoded values. +- **Fast feedback** — linters run in seconds on a developer's machine, so they belong at pre-commit and on every pull request without meaningfully slowing the pipeline. +- **Bridge to SAST** — lightweight, rule-based scanners like Semgrep blur the line between linting and [SAST](../../2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md), giving security depth at lint speed. -- Linting can **detect errors** in a code and errors that can lead to a security vulnerabilities. -- Linters Can Also **detect formatting or styling issues** and makes the code more readable for more secure code. -- Linters can **suggest best practices**. -- Also they can **increases overall quality of the code**. -- Since everybody follows the same linting rules it **makes maintenance of code easier**. +## Where to run it -## Basic Lint Tools +Run linting at every layer for maximum coverage without introducing bottlenecks: -Lint tools are the most basic form of static analysis. Using lint tools can be helpful for identifying common errors, such as: +- **IDE** — real-time feedback as the developer types. This is the lowest-friction catch — the developer sees the issue at the moment of creation. IDE plugins for ESLint, Bandit, Semgrep, and language servers can highlight problems inline. +- **Pre-commit** — block obvious issues before they enter history. Scope checks to changed files only (using `lint-staged` or Lefthook's `glob` filtering) to keep execution fast. See [Pre-commit](2-2-1-1-Pre-commit.md). +- **CI** — authoritative enforcement that cannot be bypassed. Fail the build on new violations. Run the full rule set here, not just the fast subset used at pre-commit. -- Indexing beyond arrays. -- Dereferencing null pointers. -- (Potentially) dangerous data type combinations. -- Unreachable code. -- Non-portable constructs. +## Scope to lint -## Advanced Static Analysis Tools +### Application code -Advanced static analysis tools typically deliver: +Enable security rule sets in language-specific linters. Do not run only style rules — security rules are where the risk is: -- Pattern-based simulation. -- Quality and complexity metrics. -- Best practice recommendations for developers. -- Support for multiple safety and security-focused coding standards. -- Out-of-the-box certification for use in the development of safety-critical applications. +| Language | Linter | Security rules | +|---|---|---| +| Python | Bandit, Semgrep, Ruff | B-prefix rules (Bandit); `p/python` rule set (Semgrep) | +| JavaScript / TypeScript | ESLint + `eslint-plugin-security`, Semgrep | `no-eval`, `no-new-func`, XSS patterns, `detect-non-literal-regexp` | +| Go | golangci-lint (includes gosec) | gosec rules: G101–G601 | +| Java | SpotBugs + find-sec-bugs, Semgrep | `find-sec-bugs` plugin detects SQL injection, XXE, SSRF | +| Ruby | Brakeman | Full Rails-aware security analysis | +| PHP | PHPCS + Security Audit, Psalm | `security-audit` sniffs | +| Kotlin / Android | Detekt + detekt-rules-security | Android-specific security rules | -## Issues with Linters +### Infrastructure as code -- Not every language has "quality" standard linter tools available, each framwork usually has one or several linters. +Lint IaC files for misconfiguration: -- Different versions or configurations can lead to different results. -- Since some linters are very verbose and information overload can lead to focusing on "unimportant" issues. +- **Dockerfile** — `hadolint` enforces best practices: no `latest` tag, `USER` instruction set, shell injection in `RUN` commands. +- **Terraform** — `tflint` and `tfsec` / `Trivy` catch misconfigurations before `terraform apply`. +- **Kubernetes manifests** — `kube-linter` checks for privilege escalation, missing resource limits, host network access. +- **Helm charts** — `helm lint` + `kube-linter` on rendered templates. -## Where and When to Use Linter +See [IaC Scanning](../../2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md) for deeper coverage. -![Pre Commit](/current-version/assets/images/pre-commit.png) +### Configuration and data files -You can perform it in the **pre-commit** phase, so locally before actually committing code to your local repository to your local clone. Another phase where you often see linting is during the **build** phase, So here the build server pulls the code from the Git repository and performs linting on it and reports back that results from linting phase. +Validate YAML/JSON/TOML in CI to prevent malformed or unsafe config from reaching deployment: + +```yaml +# .pre-commit-config.yaml entry +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-yaml + - id: check-json + - id: check-toml +``` + +## Practical Semgrep example + +Semgrep lets you write custom rules in YAML to enforce project-specific security patterns: + +```yaml +# semgrep-rules/no-md5.yaml +rules: + - id: no-md5-for-hashing + patterns: + - pattern: hashlib.md5(...) + message: "MD5 is cryptographically broken. Use hashlib.sha256() or better." + languages: [python] + severity: ERROR + metadata: + category: security + cwe: CWE-327 +``` + +Run it in CI: + +```bash +semgrep --config semgrep-rules/ --error --json > semgrep-results.json +``` + +## Baseline management + +New projects inherit years of existing lint violations. Blocking on all of them at once is counterproductive. Manage this with baselines: + +- **Semgrep baseline** — `semgrep --baseline-commit ` reports only findings introduced after the baseline commit, not the historical backlog. +- **ESLint** — use `eslint --report-unused-disable-directives` and dedicate a sprint to clearing violations incrementally. +- **detect-secrets baseline** — generate a baseline file with `detect-secrets scan > .secrets.baseline` and commit it. New secrets are flagged against the baseline. + +Treat clearing lint debt as technical debt: schedule it, track it, and do not let it grow by blocking new violations. + +## Common pitfalls + +- **Security rules disabled** — style linting without security rules enabled misses the most valuable signal. Audit your `.eslintrc` / `pyproject.toml` to confirm security plugins are active. +- **Noisy rules driving suppression** — if developers add `# noqa`, `// eslint-disable`, or `// nosec` comments routinely, the rules are misconfigured. Tune or replace noisy rules instead of suppressing them everywhere. +- **Only running in CI, not at pre-commit** — slow feedback loops mean developers context-switch after forgetting what the code was doing. +- **Linting only changed files in CI** — fine for speed, but run full-repo linting on a schedule (weekly) to catch violations in unchanged files. +- **Ignoring `lint-staged` performance** — on large repos, running linters against all files at pre-commit is slow. Scope to staged files. + +## Metrics + +- Number of security-category lint violations introduced per sprint (should trend toward zero). +- `# noqa` / `// eslint-disable` suppression count per repo (rising counts indicate noise problems or avoidance). +- Time from lint violation to fix (measures how actionable feedback is). +- Percentage of repos with security lint rules enabled (org-level metric). + +## Maturity progression + +| Level | Practice | +|---|---| +| Starting | Style linter running in CI; security rules added to at least one language linter | +| Developing | Security linting (Semgrep or equivalent) at pre-commit and CI; IaC linting for Dockerfile and Terraform; baseline managed | +| Defined | Custom Semgrep rules for project-specific patterns; IDE plugins standard in developer tooling; violations trend tracked | +| Advanced | Org-wide shared Semgrep rule library; lint results fed into ASPM for correlation with runtime findings; suppressions reviewed in security audits | --- @@ -51,10 +122,27 @@ You can perform it in the **pre-commit** phase, so locally before actually commi ### Open-source -- [Pre-Commit](https://pre-commit.com/) - A framework for managing and maintaining multi-language pre-commit hooks. +- [Bandit](https://github.com/PyCQA/bandit) — Finds common security issues in Python code. Checks for dangerous calls (`exec`, `eval`, `pickle`), weak crypto, SQL injection patterns, and more. Integrates with pre-commit and CI. +- [Brakeman](https://brakemanscanner.org/) — Static analysis specifically for Ruby on Rails. Detects SQL injection, XSS, mass assignment, and other Rails-specific security issues. +- [ESLint](https://eslint.org/) — Pluggable JavaScript/TypeScript linter. Add `eslint-plugin-security` and `eslint-plugin-no-unsanitized` for security rules covering `eval`, regular expression injection, and unsafe HTML insertion. +- [golangci-lint](https://golangci-lint.run/) — Fast aggregator of Go linters. Includes `gosec` for security analysis (hardcoded credentials, SQL injection, weak crypto, file permissions). +- [hadolint](https://github.com/hadolint/hadolint) — Dockerfile linter that enforces best practices: avoid `latest` tags, set non-root `USER`, avoid shell injection in `RUN`. +- [Semgrep](https://semgrep.dev/) — Fast, multi-language static analysis using readable YAML pattern rules. Community registry contains thousands of security rules. Supports custom rules for project-specific patterns. +- [SpotBugs + find-sec-bugs](https://find-sec-bugs.github.io/) — SpotBugs is a Java bytecode analyzer; find-sec-bugs adds 130+ security bug patterns covering OWASP Top 10 for Java/Kotlin. + +### Commercial + +- [SonarQube / SonarCloud](https://www.sonarsource.com/products/sonarqube/) — Code quality and security analysis across 30+ languages. Community edition is free; commercial editions add security hotspot management, portfolio reporting, and branch analysis. --- ### Links -- [Preforce](https://www.perforce.com/blog/qac/what-lint-code-and-why-linting-important) +[^1]: Listed in alphabetical order. + +## Further reading + +- [OWASP Code Review Guide](https://owasp.org/www-project-code-review-guide/) +- [Semgrep rule registry](https://semgrep.dev/r) +- [gosec — Go security checker](https://github.com/securego/gosec) +- [OWASP Cheat Sheet — Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html) diff --git a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md index af5deed..63f66a5 100644 --- a/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md +++ b/current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md @@ -1,51 +1,225 @@ # Repository Hardening -Securing a code repository involves implementing a variety of practices and techniques to protect it from unauthorized access, data breaches, and other security threats. By doing so, you can ensure the integrity, confidentiality, and availability of the code and its associated resources. - -## Objectives - -- **Prevent Unauthorized Access:** Ensure that only authorized personnel can access and modify the repository. -- **Protect Sensitive Information:** Safeguard secrets, passwords, and other sensitive data. -- **Maintain Code Integrity:** Ensure that the code is not tampered with or corrupted. -- **Compliance:** Adhere to regulatory and industry standards for code security. - -## Key Concepts - -- **Access Control:** Managing who can access the repository and what actions they can perform. -- **Secrets Management:** Handling sensitive data such as API keys and passwords securely. -- **Audit and Monitoring:** Keeping track of repository activities to detect and respond to security incidents. -- **Code Quality and Security:** Ensuring the codebase is free from vulnerabilities and adheres to security best practices. -- **Backup and Recovery:** Ensuring data is backed up and can be restored in case of a failure or breach. - -## Best Practices for Repository Hardening - -1. **Access Control** - - **Principle of Least Privilege:** Grant the minimum necessary permissions to users. - - **Role-Based Access Control (RBAC):** Define roles with specific permissions and assign users to these roles. - - **Multi-Factor Authentication (MFA):** Require MFA for accessing the repository to add an extra layer of security. - - **SSH Keys and Token Management:** Use SSH keys or personal access tokens instead of passwords for authentication. -2. **Secrets Management** - - **Environment Variables:** Use environment variables to manage secrets in CI/CD pipelines. - - **Secret Management Tools:** Use tools like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault to store and manage secrets securely. - - **Scanning for Secrets:** Use tools like GitSecrets, TruffleHog, and Talisman to scan the repository for accidentally committed secrets. -3. **Audit and Monitoring** - - **Audit Logs:** Enable and regularly review audit logs to monitor access and changes to the repository. - - **Activity Alerts:** Set up alerts for suspicious activities, such as failed login attempts or unexpected repository modifications. - - **Repository Scanning:** Regularly scan the repository for vulnerabilities using tools like SonarQube or CodeQL. -4. **Code Quality and Security** - - **Static Code Analysis:** Integrate static analysis tools to detect security vulnerabilities and code quality issues. - - **Code Reviews:** Implement a mandatory code review process to ensure that all code changes are reviewed by peers. - - **Dependency Management:** Regularly update dependencies and use tools like Dependabot or Snyk to detect vulnerabilities in third-party libraries. -5. **Backup and Recovery** - - **Regular Backups:** Ensure that repository data is backed up regularly and stored securely. - - **Disaster Recovery Plan:** Develop and test a disaster recovery plan to restore repository data in case of a breach or failure. +The source repository is the single source of truth for what gets built and shipped. If an attacker can push malicious code, alter history, or weaken CI/CD protections, every downstream control inherits that compromise. A developer account takeover that reaches an unprotected repository is a supply-chain incident. **Repository hardening** locks down the repo itself so that what enters the pipeline is trustworthy. + +## Branch and merge protection + +Unprotected branches are the most common repository vulnerability. Every commit to a default or release branch without review is a potential injection point. + +**GitHub branch protection settings to enable:** + +``` +Branch protection rule for: main, master, release/* + [x] Require a pull request before merging + [x] Require approvals: 2 + [x] Dismiss stale pull request approvals when new commits are pushed + [x] Require review from Code Owners + [x] Require status checks to pass before merging + [x] Require branches to be up to date before merging + Status checks: ci/build, security/sast, security/secrets + [x] Require conversation resolution before merging + [x] Require signed commits + [x] Do not allow bypassing the above settings + [x] Restrict who can push to matching branches + [x] Block force pushes + [x] Allow deletions: NO +``` + +**CODEOWNERS** ensures that changes to high-risk paths require review from the team that owns them: + +``` +# .github/CODEOWNERS +# Auth and crypto: require security team review +/src/auth/ @org/security-team +/src/crypto/ @org/security-team + +# CI/CD configuration: require platform team + security review +/.github/workflows/ @org/platform-team @org/security-team +/Dockerfile @org/platform-team +/terraform/ @org/platform-team @org/security-team +``` + +## Identity and access + +### Human identities + +- Grant the **minimum role** required. Most contributors need only Write access; Admin should be held by a small, named group. +- Enforce **MFA for all contributors** at the organization level. Do not allow HTTP basic auth or personal access tokens as the sole authentication method. +- Integrate with your **corporate identity provider** (SSO) so that offboarding automatically revokes repository access. +- Review access quarterly; remove dormant accounts — accounts that have not committed or reviewed in 90 days are an unnecessary attack surface. + +### Machine identities + +- **Deploy keys** — scope to a single repository, grant read-only unless write is strictly required, rotate on a schedule. +- **Bot accounts** — treat like service accounts: named, scoped, audited. Do not use a human's account as a bot. +- **Personal access tokens (PATs)** — enforce expiry, grant minimal scope, require documented justification for fine-grained PAT exceptions. +- **Prefer short-lived tokens** — use OIDC and workload identity wherever possible rather than long-lived PATs or service account keys. See [Secrets Management](2-2-1-2-Secrets-Management.md). + +## Integrity of code and history + +### Signed commits and tags + +Commit signing lets consumers verify that a commit was made by the claimed author and has not been altered. Without signing, `git log --author` is trivially spoofable. + +```bash +# Configure GPG signing globally +git config --global commit.gpgsign true +git config --global user.signingkey + +# Or use SSH signing (simpler key management) +git config --global gpg.format ssh +git config --global user.signingkey ~/.ssh/id_ed25519.pub +git config --global commit.gpgsign true + +# Or use Sigstore gitsign (keyless, ties signing to OIDC identity) +git config --global gpg.x509.program gitsign +git config --global gpg.format x509 +git config --global commit.gpgsign true +``` + +Require signed commits in branch protection so unsigned commits are rejected server-side. + +### Protect tags and releases + +Tags feed the release pipeline. An attacker who can move or delete a tag can make a different commit ship as a release. + +```bash +# GitHub: protect release tags +# Settings > Tags > Add rule: v* → enable tag protection +``` + +Sign release tags: +```bash +git tag -s v1.2.3 -m "Release v1.2.3" +git push origin v1.2.3 +``` + +## Hardening the automation surface + +CI/CD workflows have privileged access and are a high-value target. The repository itself is the attack surface for workflow injection. + +### Restrict workflow permissions + +Set least-privilege permissions at the workflow and job level: + +```yaml +# Set read-only default permissions for the entire workflow +permissions: + contents: read + +jobs: + build: + permissions: + contents: read + packages: write # only the jobs that need it get elevated scope +``` + +Never use `permissions: write-all` unless you have an explicit, documented reason. + +### Pin third-party Actions to digest + +Mutable tags (`@v3`, `@main`) can be silently updated to contain malicious code. Pin to immutable SHA digests: + +```yaml +# Bad — mutable tag +- uses: actions/checkout@v4 + +# Good — pinned to immutable digest +- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 +``` + +Use [Dependabot for Actions](https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/keeping-your-actions-up-to-date-with-dependabot) to keep digests current without manual tracking. + +### Control fork pull request permissions + +By default, workflows from forked PRs cannot access secrets, but they can run code in your CI environment. Set explicit policies: + +```yaml +# Only allow fork PRs from approved contributors to trigger full CI +on: + pull_request_target: + types: [opened, synchronize] +``` + +Avoid `pull_request_target` with checkout of untrusted code — it is a known attack vector for secret exfiltration. + +## Platform security features + +Enable the full suite of built-in platform protections: + +| Feature | Platform | Purpose | +|---|---|---| +| Secret scanning + push protection | GitHub Advanced Security, GitLab | Block and alert on committed secrets | +| Dependabot / Dependency review | GitHub | Alert on and auto-PR vulnerable dependencies | +| Code scanning (CodeQL) | GitHub Advanced Security | SAST integrated into PR workflow | +| Audit log | GitHub / GitLab | Track org-level events (member changes, settings changes) for incident investigation | +| Compliance frameworks | GitLab Ultimate | Enforce org-wide branch protection and merge request policies | + +## Measuring your posture + +[OpenSSF Scorecard](https://github.com/ossf/scorecard) automatically evaluates a repository against 20+ security practices and produces a 0–10 score. Run it in CI and track the score over time: + +```yaml +- name: OpenSSF Scorecard + uses: ossf/scorecard-action@main + with: + results_file: results.sarif + results_format: sarif + publish_results: true +``` + +Target Scorecard categories include: Branch-Protection, Code-Review, Signed-Releases, Token-Permissions, Pinned-Dependencies, SAST, and more. + +## Common pitfalls + +- **Force-push allowed on the default branch** — enables history rewriting and silent code injection. +- **Admin bypass of branch protection** — if admins can bypass protections, the protection is organizational theater, not a technical control. +- **Shared bot account credentials** — a shared PAT for CI that multiple pipelines use is a single point of failure and makes audit logs unattributable. +- **Actions pinned to branch names** — `@main` or `@master` in workflow `uses:` is a supply-chain risk. Pin to SHA. +- **No CODEOWNERS for security-sensitive paths** — security infrastructure (auth, crypto, CI config) must require security review; it should not be mergeable by any repo member. + +## Metrics + +- OpenSSF Scorecard score trend per repository. +- Percentage of repositories with branch protection fully configured. +- Number of repositories with force-push enabled on default branch (should be zero). +- Number of long-lived PATs in use vs OIDC/workload identity adoption. +- Commit signing coverage (percentage of commits signed on protected branches). + +## Maturity progression + +| Level | Practice | +|---|---| +| Starting | Default branch protected (require PR + 1 review); MFA enforced at org level; secret scanning enabled | +| Developing | CODEOWNERS for sensitive paths; status checks required; Dependabot enabled; Actions pinned to digests | +| Defined | Commit signing required; OIDC for CI/CD; Scorecard running in CI; admin bypass disabled; quarterly access review | +| Advanced | Org-wide policy enforced via Allstar or OPA; full audit log retention and alerting on policy violations; provenance tied to signed commits | + +--- + +## Tools[^1] + +### Open-source + +- [Allstar](https://github.com/ossf/allstar) — OpenSSF GitHub App that continuously enforces security policies (branch protection, MFA, binary artifacts) across an organization's repositories and files issues when violations are detected. +- [gitsign](https://github.com/sigstore/gitsign) — Keyless git commit signing via Sigstore. Signs commits using OIDC identity (GitHub, Google, Microsoft) — no local GPG key management required. +- [OpenSSF Scorecard](https://github.com/ossf/scorecard) — Automated assessment of repository security best practices across 20+ checks. Integrates with GitHub Actions and publishes results to the OpenSSF API. +- [Renovate](https://github.com/renovatebot/renovate) — Automated dependency update tool; keeps Actions digests and dependency versions current. Alternative to Dependabot with more configuration flexibility. + +### Commercial + +- [GitHub Advanced Security](https://github.com/security/advanced-security) — Secret scanning with push protection, CodeQL code scanning, and dependency review integrated into the GitHub PR workflow. +- [GitLab Ultimate](https://about.gitlab.com/pricing/) — Compliance frameworks, protected branches, security policies, and merge request approvals enforced at the group level. --- ### Links -- [GitHub Security Best Practices](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure) -- [GitLab Security Guide](https://docs.gitlab.com/ee/user/application_security/) -- [HashiCorp Vault Documentation](https://www.vaultproject.io/docs) -- [OWASP Secure Coding Practices](https://owasp.org/www-project-secure-coding-practices-quick-reference-guide/) -- [SonarQube Documentation](https://docs.sonarqube.org/latest/) +[^1]: Listed in alphabetical order. + +## Further reading + +- [OpenSSF Scorecard documentation](https://github.com/ossf/scorecard/blob/main/docs/checks.md) +- [GitHub — Hardening security for GitHub Actions](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions) +- [OWASP Top 10 CI/CD Security Risks — CICD-SEC-8: Ungoverned Usage of 3rd Party Services](https://owasp.org/www-project-top-10-ci-cd-security-risks/) +- [Sigstore gitsign](https://docs.sigstore.dev/signing/gitsign/) diff --git a/current-version/2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md b/current-version/2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md new file mode 100644 index 0000000..3ab6646 --- /dev/null +++ b/current-version/2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md @@ -0,0 +1,146 @@ +# IDE and AI-Assisted Development Security + +The developer's "inner loop" — the IDE and the moment-to-moment writing of code — is now the front line of shift-left security, and it has changed dramatically with the rise of AI coding assistants. Securing this stage means both giving developers real-time security feedback *and* managing the new risks introduced when a large share of code is generated by AI. + +## Real-time feedback in the IDE + +The fastest feedback loop of all is in the editor, before a single line is committed. IDE-integrated security tooling provides: + +- **Inline SAST findings** — as the developer writes code, the plugin highlights insecure patterns (e.g., SQL string concatenation, use of `eval`, hardcoded credentials) with the same context a code reviewer would bring — but instantly. +- **SCA / dependency awareness** — warnings when a dependency with known CVEs is imported, before the lock file is updated. +- **Secret detection** — flags potential credentials as they are typed, not after a push. +- **Fix suggestions** — modern tools (Snyk, GitHub Copilot Autofix, SonarLint) provide remediation suggestions inline, turning a finding into a learning moment. + +IDE feedback complements — it does not replace — the authoritative scans in CI. A developer can suppress or ignore an IDE warning; a CI gate cannot be merged around (when properly configured). + +### Setting up Semgrep in VS Code + +```json +// .vscode/settings.json (commit to repo for team standardization) +{ + "semgrep.enabled": true, + "semgrep.rules": ["p/owasp-top-ten", "p/secrets", "p/default"], + "semgrep.scanOnSave": true, + "semgrep.showStatusBarItem": true +} +``` + +### Setting up Snyk in VS Code or JetBrains + +Install via the marketplace. Authenticate once with `snyk auth`. The plugin then scans open files in real time for SAST (Snyk Code), SCA (Snyk Open Source), and IaC (Snyk IaC) findings. Findings appear as inline annotations and in the Problems panel. + +## Risks of AI coding assistants + +Tools like GitHub Copilot, Cursor, and other LLM-based assistants now generate a substantial portion of new code. AI accelerates output at machine speed — including insecure output. The specific risks: + +### Insecure code generation + +Models are trained on the full breadth of public code — which includes decades of insecure patterns. They reproduce what they learned: + +- SQL built by string concatenation instead of parameterized queries. +- `eval()` used for dynamic execution. +- Weak or deprecated cryptographic primitives (`MD5`, `SHA1`, `DES`, `ECB` mode). +- Missing authorization checks on sensitive endpoints. +- Hardcoded credentials and magic strings. + +AI does not understand security intent — it pattern-matches on what "looks like" code that works. Review generated code with the same critical eye as code from an unknown external contributor. + +### Hallucinated dependencies ("slopsquatting") + +LLMs sometimes suggest package names that do not exist in any registry. Attackers monitor for these hallucinated names and pre-register matching packages with malicious payloads. A developer who copies the `npm install` or `pip install` command from a generated snippet and runs it without verification may execute malware. + +**Mitigation:** always verify that a dependency exists, is the correct package (not a typosquat), and has a reasonable download count and publication history before installing it. + +### Context leakage via prompts + +Code, API keys, internal architecture details, and customer data pasted into a prompt may be retained by or transmitted to third-party services. Enterprise-managed or self-hosted models avoid this risk; standard SaaS coding assistants may not. + +**Mitigation:** define a clear AI usage policy specifying which tools are approved, what data categories may be shared, and when enterprise/on-premises alternatives are required. + +### Prompt injection + +Coding assistants that read external content — files, issues, pull request descriptions, web pages — can be manipulated by attacker-controlled text embedded in that content. An issue comment containing `` is a prompt injection attempt. + +**Mitigation:** treat content fed to AI from external or user-controlled sources as untrusted. Validate AI-proposed changes that modify security-relevant paths (auth, crypto, CI config) with extra scrutiny. See [AI Governance and Risk](../../3-Governance/3-4-AI-Governance-and-Risk.md). + +### Unreviewed volume + +AI dramatically increases output volume. If review practices don't scale accordingly, flaws slip through not because reviewers are less careful — but because there is simply more code to review. + +**Mitigation:** require human review of all AI-generated code; consider flagging AI-generated PRs for enhanced review (e.g., mandatory security champion review for changes to sensitive modules). + +## Guardrails for AI-assisted development + +| Risk | Guardrail | +|---|---| +| Insecure generated code | Run SAST, SCA, and secret scanning on all code regardless of origin; apply same gate thresholds | +| Hallucinated dependencies | Verify every new dependency before installing; use SCA in CI to catch package-level risks | +| Context leakage | Enforce AI usage policy; use enterprise/self-hosted models for sensitive work | +| Prompt injection | Treat AI suggestions on security-sensitive paths as requiring elevated review | +| Unreviewed volume | CODEOWNERS + required review for high-risk paths; AI-generated-code label for tracking | + +### AI usage policy essentials + +An AI usage policy for engineering should cover at minimum: + +1. **Approved tools** — which AI assistants are sanctioned and why. +2. **Data handling** — what categories of data (PII, secrets, IP) may not be shared with third-party AI services. +3. **Self-hosted / enterprise options** — when to use GitHub Copilot Business (data not used for training) vs community tools. +4. **Code ownership** — generated code is the author's responsibility; AI authorship is not a liability shield. +5. **Review requirements** — all AI-generated code is subject to the same review and gate standards as human-written code. + +## Using AI defensively + +AI is not only a risk — it is also a tool for the security team: + +- **AI-assisted triage** — tools like Semgrep Autofix, Snyk DeepCode, and GitHub Copilot Autofix suggest remediations for scanner findings, reducing the time from finding to fix. +- **Automated false positive analysis** — LLM-based analysis can assess whether a SAST finding is reachable and exploitable in context, reducing noise. +- **Threat modeling assistance** — AI tools can help generate threat enumeration from a system description, bootstrapping the threat modeling conversation. +- **Security code review** — AI-assisted PR review tools surface security-relevant patterns that human reviewers might miss in high-volume PRs. + +The arms-race framing — AI accelerates attacks, so defenders must use AI too — is real. Invest in defensive AI tooling to keep pace. + +## Common pitfalls + +- **Merging AI-generated code without review** — "Copilot wrote it" is not a substitute for review. Generated code regularly contains subtle security issues. +- **No IDE security tooling standardized** — if IDE security plugins are optional and unchosen by most developers, the inner-loop benefit evaporates. Commit IDE config to the repo and onboard developers to it. +- **AI usage policy as a document nobody reads** — effective policies are enforced technically (approved tools listed in software inventory, browser extensions allowed list, network egress controls) not just communicated. +- **Trusting AI-suggested fixes without understanding them** — AI remediation suggestions can themselves introduce new issues. Understand the fix before applying it. + +## Maturity progression + +| Level | Practice | +|---|---| +| Starting | IDE security plugins recommended (Snyk or Semgrep); basic AI usage guidance documented | +| Developing | IDE config standardized and committed to repo; AI usage policy published; SAST/SCA gates apply to AI-generated code explicitly | +| Defined | AI-generated PRs labeled and tracked; enhanced review for AI changes on security-sensitive paths; prompt injection awareness in training | +| Advanced | AI-assisted triage in ASPM to reduce noise; AI-generated PR volume and finding rate tracked; red-team exercises on prompt injection | + +--- + +## Tools[^1] + +### Open-source + +- [Semgrep IDE extensions](https://semgrep.dev/docs/extensions/overview) — VS Code and JetBrains plugins for real-time static analysis. Highlights security findings inline with fix suggestions. Backed by the Semgrep rule registry. +- [Trivy VS Code plugin](https://github.com/aquasecurity/trivy-vscode) — Vulnerability and misconfiguration scanning for container images and IaC files directly within the editor. + +### Commercial + +- [GitHub Copilot Autofix / Advanced Security](https://github.com/security/advanced-security) — AI-assisted vulnerability detection in pull requests with generated fix suggestions. Part of GitHub Advanced Security. +- [Snyk (IDE plugins)](https://snyk.io/) — Available for VS Code, JetBrains, Eclipse, and Visual Studio. Surfaces SCA (open source vulnerabilities), SAST (Snyk Code), and IaC findings inline. Fix suggestions powered by DeepCode AI. +- [SonarLint](https://www.sonarsource.com/products/sonarlint/) — Real-time code quality and security analysis in the IDE. Syncs rule configuration with SonarQube/SonarCloud for team consistency. +- [Checkmarx One IDE plugins](https://checkmarx.com/) — IDE integration for SAST, SCA, IaC, and API security findings. + +--- + +### Links + +[^1]: Listed in alphabetical order. + +## Further reading + +- [OWASP LLM Top 10 — LLM Security Risks](https://owasp.org/www-project-top-10-for-large-language-model-applications/) +- [NCSC — Guidelines for secure AI system development](https://www.ncsc.gov.uk/collection/guidelines-secure-ai-system-development) +- [GitHub — Responsible use of GitHub Copilot](https://docs.github.com/en/copilot/responsible-use-of-github-copilot-features) +- [AI Governance and Risk](../../3-Governance/3-4-AI-Governance-and-Risk.md) diff --git a/current-version/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md b/current-version/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md index 946e125..523f4fc 100644 --- a/current-version/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md +++ b/current-version/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md @@ -1,25 +1,143 @@ -# Static scanning is an important part of the process +# Static Application Security Testing (SAST) -![Static scanning diagram showing analysis process](/current-version/assets/images/Static scanning.png) +Static Application Security Testing analyzes an application's **source code, bytecode, or binaries without executing it** — a white-box technique that examines the code from the inside. Because it runs early (in the IDE, at pre-commit, and in CI) and needs no running application, SAST is a cornerstone of shift-left security. -Static Code Analysis or Source Code Analysis is usually part of a Code Review (white-box testing) and it is a method of computer program debugging that is done by examining the code without executing the program. +## How SAST works mechanically -Static scanning is good way finding coding issues such as: +SAST tools use one or more of these techniques depending on their depth and language support: -- Syntax violations -- Security vulnerabilities -- Programming errors -- Coding standard violations -- Undefined values +- **Pattern matching / AST analysis** — the simplest and fastest approach. The tool parses source code into an Abstract Syntax Tree (AST) and matches against known-vulnerable patterns (e.g., "string concatenation used as SQL query argument"). Semgrep and Bandit use this approach. Fast, low false-positive rate, but misses vulnerabilities that span multiple functions. +- **Dataflow / taint analysis** — the most powerful technique. The tool tracks how untrusted input (a *source*, such as `request.getParameter()`) flows through the application until it reaches a dangerous operation (a *sink*, such as `executeQuery()`). If tainted data reaches a sink without sanitization, it is flagged. CodeQL and Checkmarx use this approach. More thorough, higher false-positive rate, slower. +- **Control flow analysis** — maps all possible execution paths through a function or module to find paths that lead to dangerous states (e.g., null dereference, unhandled exception disclosing information). +- **Semantic analysis** — understands language idioms and framework conventions rather than just syntax, reducing false positives for framework-specific patterns. -For more information about the Static Code Analysis please visit [the OWASP page](https://owasp.org/www-community/controls/Static_Code_Analysis) -To achieve a better result we can combine static security scanning and 3rd party code (open-source libraries (dependency) scanning. -To doing this part better and more complete (prevent misconfigurations), we can bring up IaC (Infrastructure as code) security scan too. For example check Terraform, helm, Ansible code, etc. -So according to the above lines the possible actions in this step are as follows: +The practical implication: faster pattern-matching tools are suitable for IDE and pre-commit; deeper dataflow tools belong in nightly CI scans. -- Static Code Analysis (known as SAST) -- Open-source libraries (3rd party / dependency) scanning (known as SCA) -- IaC Security scanning +## What SAST finds + +By tracing data and control flow through the code, SAST detects flaws such as: + +- Injection (SQL, command, LDAP) from untrusted input reaching dangerous sinks +- Cross-site scripting (XSS) and unsafe output handling +- Hardcoded secrets and weak cryptography +- Insecure deserialization and path traversal +- Coding-standard and error-handling violations that lead to security bugs + +## Strengths and limitations + +**Strengths:** runs without a deployed app, finds issues at the earliest stage, points directly to the vulnerable line, and covers code paths that dynamic testing might never reach. + +**Limitations:** SAST cannot see runtime or environment context — it produces **false positives** (flagging safe code as vulnerable) and can miss flaws that only appear at runtime (logic bugs, auth issues that depend on data state). The key to a healthy SAST program is managing noise. + +## The SAST tuning process + +A SAST program that is not actively tuned will degrade. Teams learn to ignore alerts, and real findings get buried. Follow this cycle: + +1. **Establish baseline** — run the tool in report-only mode for 2–4 weeks. Record all findings. This is the debt you already own; do not gate on it immediately. +2. **Review a sample** — triage 50–100 random findings manually. Measure: what fraction are genuine vulnerabilities? What fraction are false positives? Which rule categories produce the most noise? +3. **Suppress high-noise rules** — rules with > 80% false positive rate for your codebase should be disabled or scoped. Document the suppression with justification. +4. **Gate on new findings only** — using the baseline snapshot, block pull requests only on findings that are *new* since the baseline. This removes legacy debt from the gate and makes it actionable. +5. **Reduce the baseline progressively** — allocate sprint capacity to address the existing backlog. Track baseline count month-over-month. +6. **Re-tune quarterly** — as the codebase and frameworks evolve, repeat the sample review to catch new noise sources. + +## SAST scan modes: when to use each + +| Mode | Tool | Scope | Latency | Purpose | +|---|---|---|---|---| +| IDE plugin | Semgrep LSP, Snyk Code, SonarLint | File being edited | < 1 second | Instant feedback; education at code time | +| Pre-commit | Semgrep (fast rules) | Changed files only | 5–30 seconds | Catch obvious issues before push | +| Pull request | Semgrep, CodeQL, Snyk Code | Diff vs base branch | 1–5 minutes | Authoritative gate; block on new high/critical | +| Nightly full scan | CodeQL, Checkmarx, Fortify | Entire codebase | 10–60 minutes | Deep taint analysis; feed central dashboard | + +## Integrating SAST in the pipeline + +```yaml +# Example GitHub Actions SAST step using CodeQL +- name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: javascript, python + queries: security-extended + +- name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:javascript" +``` + +## Writing a custom Semgrep rule + +For organization-specific patterns — internal APIs that must always be called with authentication, deprecated functions that must not be used — write custom rules: + +```yaml +# rules/no-unsafe-internal-api.yaml +rules: + - id: no-unauthenticated-internal-client + patterns: + - pattern: InternalClient($HOST, ...) + - pattern-not: InternalClient($HOST, auth=$AUTH, ...) + message: | + InternalClient must always be called with an explicit auth= parameter. + Unauthenticated calls will be rejected in production. + languages: [python] + severity: ERROR + metadata: + category: security + cwe: "CWE-306: Missing Authentication for Critical Function" +``` + +Run: `semgrep --config rules/ src/` + +Custom rules are the primary mechanism for catching organization-specific security patterns that generic rulesets cannot know about. + +## SAST for infrastructure code + +SAST is not only for application code. The same principles apply to infrastructure: + +- **Terraform / Bicep / CloudFormation** — see [IaC Scanning](../2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md) for dedicated tooling. +- **GitHub Actions / GitLab CI / CircleCI** — pipeline definitions can contain command injection, secret exposure, and unsafe permission grants. Tools like `zizmor` (GitHub Actions) and `checkov` analyze CI pipeline files statically. +- **Dockerfiles** — running as root, `ADD` instead of `COPY`, pinning base images to digests. + +Covering infrastructure-as-code alongside application code gives a complete static security picture. + +## SAST and ASPM integration + +Raw SAST output fed directly to developers produces too much noise. At scale, route SAST findings through an [ASPM](../../../3-Governance/3-3-Reporting/3-3-3-ASPM.md) or central platform (DefectDojo, Dependency-Track) that: + +- **Deduplicates** — the same vulnerability found by CodeQL, Semgrep, and Snyk Code is one finding, not three. +- **Enriches** — adds reachability context, EPSS scores, and business asset classification. +- **Assigns ownership** — maps findings to the team that owns the affected service. +- **Tracks SLAs** — monitors time-to-remediate by severity against agreed targets. + +This prevents each tool's dashboard from becoming a siloed, ignored alert queue. + +## Common pitfalls and anti-patterns + +- **Scanning everything, gating nothing** — running SAST but not blocking on results means findings are ignored. Combine scanning with actionable gates. +- **Default rules on unfamiliar languages** — out-of-the-box rules for a language or framework you do not use inflate false positives. Scope rules to your actual stack. +- **Ignoring baseline debt** — gating on total findings punishes teams for historical debt. Gate on *new* issues introduced since a known-good baseline. +- **Single pipeline stage only** — skipping IDE/pre-commit integration means developers first see findings only after a full CI run, slowing feedback loops significantly. +- **No triage ownership** — findings with no assigned owner go unresolved. Every finding needs a team responsible for the remediation or exception decision. +- **Suppressing via inline comments without tracking** — `# nosec`, `// NOSONAR`, and similar inline suppressions are invisible in most dashboards. Route suppressions through a central exception register. + +## Maturity progression + +**Starter** — Run Semgrep or Bandit in CI with a default ruleset. Report findings; do not block yet. Build developer familiarity with the tool and its output. + +**Intermediate** — Gate pull requests on new high/critical findings vs. a baselined snapshot. Integrate IDE plugins (SonarLint, Snyk Code). Tune false-positive-heavy rules. Route findings to a central tracker (DefectDojo). Write 2–3 custom rules for internal anti-patterns. + +**Advanced** — Use semantic/dataflow tools (CodeQL, Checkmarx) for deep taint analysis. Enable AI-assisted triage and autofix suggestions. Feed findings enriched with reachability and EPSS into ASPM. Track escape rate (issues reaching production) and MTTR by severity. Custom rules cover all critical internal security patterns. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| False positive rate | < 20% of findings after tuning | +| Mean time to remediate (critical) | < 7 days | +| New high/critical findings per release | Trending toward zero | +| Escape rate (issues found post-merge) | Decreasing quarter-over-quarter | +| Developer satisfaction with SAST tooling | > 70% positive in surveys | +| Rules suppressed with documented justification | 100% (zero undocumented suppressions) | --- @@ -27,23 +145,19 @@ So according to the above lines the possible actions in this step are as follows ### Open-source -- [Brakeman](https://github.com/presidentbeef/brakeman) - A static analysis security vulnerability scanner for Ruby on Rails applications -- [CodeQL](https://github.com/github/codeql) - Discover vulnerabilities across a codebase with CodeQL, our industry-leading semantic code analysis engine. -- [CodeSec by Contrast Security](https://www.contrastsecurity.com/developer) - A high-speed high-quality free SAST tool designed for use by developers and in CI/CD pipelines. -- [SonarQube](https://www.sonarqube.org) - An open-source web-based tool, extending its coverage to more than 20 languages, and also allows a number of plugins +- [Bandit](https://github.com/PyCQA/bandit) — Security-focused static analysis for Python. Best for Python-only codebases; fast, easy to extend with custom plugins. Limited to pattern matching; no dataflow. +- [Brakeman](https://github.com/presidentbeef/brakeman) — Static analysis scanner for Ruby on Rails. Deep Rails-specific knowledge makes it highly accurate for that stack; not applicable outside Rails. +- [CodeQL](https://github.com/github/codeql) — Semantic code analysis engine treating code as data for cross-codebase vulnerability queries. Strong for Java, C/C++, JavaScript, Python; integrated free in GitHub Advanced Security. Deep dataflow; slower but thorough. +- [gosec](https://github.com/securego/gosec) — Security analyzer for Go source code; maps findings to CWE and G-codes; ideal for Go microservices. +- [Semgrep](https://semgrep.dev/) — Fast, multi-language pattern-based static analysis with a large community rule registry. Low barrier to writing custom rules; best-in-class for IDE integration and speed. No native dataflow analysis (available in Semgrep Pro). +- [SonarQube Community](https://www.sonarsource.com/products/sonarqube/) — Web-based static analysis across 20+ languages with quality gate integration; broad language coverage for polyglot teams. ### Commercial -- [Checkmarx SAST](https://checkmarx.com) - A static analysis security vulnerability scanner -- [CodeSweep](https://hclsw.co/codesweepgithub) - Static Analysis tool for GitHub that's free to use and can scan code on pull request. Support over 20 languages and IaC (docker, k8s). [Download CodeSweep VS Code extension](https://hclsw.co/codesweep) -- [Enlightn](https://github.com/enlightn/enlightn) - A static analysis vulnerability scanner for Laravel PHP applications -- [Fortify](https://www.microfocus.com/en-us/cyberres/application-security/static-code-analyzer) - A static analysis security vulnerability scanner -- [HCL AppScan on Cloud](https://cloud.appscan.com ) - SAST tool built as a service. The tool can perform traditional SAST, SCA and IaC scanning. -- [Inquisition](https://github.com/rubygarage/inquisition) - A set of tools for convenient technical analysis of web applications built with Ruby and Ruby on Rails. Now you don't need to set up and configure every single gem. Use Inquisition gem instead -- [PT Application Inspector](https://www.ptsecurity.com/ww-en/products/ai/) - Is the only source code analyzer providing high-quality analysis and convenient tools to automatically confirm vulnerabilities — significantly speeding up the work with reports and simplifying teamwork between security specialists and developers -- [security code scan](https://github.com/security-code-scan/security-code-scan) - Vulnerability Patterns Detector for C# and VB.NET -- [Semgrep](https://semgrep.dev) - Lightweight static analysis for many languages. Find bug variants with patterns that look like source code. -- [Veracode](https://www.veracode.com/security/static-analysis-tool) - A static analysis tool that is built on the SaaS model. This tool is mainly used to analyze the code from a security point of view +- [Checkmarx SAST](https://checkmarx.com/) — Enterprise SAST with deep dataflow analysis and broad language support; strong for regulated industries. Full taint analysis across the full application graph. +- [Fortify Static Code Analyzer](https://www.opentext.com/products/fortify-static-code-analyzer) — Long-established enterprise SAST with binary analysis; commonly required in government and defense contexts. +- [Snyk Code](https://snyk.io/product/snyk-code/) — Developer-first SAST with real-time IDE feedback and AI-suggested fixes; fastest time-to-value for developer adoption. Strong on JavaScript/TypeScript and Python. +- [Veracode Static Analysis](https://www.veracode.com/products/binary-static-analysis-sast) — SaaS SAST with binary scanning; no source-code access required, useful for third-party assessments and vendor security reviews. --- diff --git a/current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md b/current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md new file mode 100644 index 0000000..39ebc28 --- /dev/null +++ b/current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md @@ -0,0 +1,194 @@ +# Software Composition Analysis (SCA) + +Modern applications are mostly **third-party code** — open-source libraries and their transitive dependencies often make up 80%+ of a codebase. Software Composition Analysis identifies those components and flags the ones with known vulnerabilities, risky licenses, or signs of malice. Given that supply-chain attacks now rival application bugs as a top risk, SCA is essential. + +## The Log4Shell lesson + +Log4Shell (CVE-2021-44228, CVSS 10.0) became the defining SCA failure case. The vulnerability was in Log4j — a Java logging library. What made it catastrophic was not the flaw itself, but that: + +1. Log4j appeared as a **transitive dependency** in thousands of applications — included by Elasticsearch, Apache Struts, and hundreds of other frameworks that developers chose directly. Teams had no idea they were using it. +2. Exploitation was trivially easy: a single string in any logged input field could trigger remote code execution. +3. Organizations without an accurate **software bill of materials (SBOM)** spent days manually auditing hundreds of applications to determine exposure, while those with SBOM and SCA tooling identified affected services within hours. + +Log4Shell is the clearest argument for continuous SCA with full transitive dependency resolution and SBOM-driven inventory. + +## What SCA covers + +- **Known vulnerabilities (CVEs)** — match dependencies against vulnerability databases (NVD, OSV, GitHub Advisory Database) and maintainer advisories. +- **Transitive dependencies** — the indirect dependencies you never chose explicitly but still ship. These are where most risk hides. +- **License compliance** — detect copyleft (GPL, AGPL) or otherwise incompatible licenses that create legal risk in commercial products. +- **Malicious packages** — detect typosquatting, dependency confusion, and packages exhibiting malicious behavior — increasingly important in the age of [AI-hallucinated dependencies](../../2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md). +- **Outdated components** — surface unmaintained or end-of-life dependencies before they accumulate debt or lose CVE coverage. + +## Understanding transitive dependencies + +A direct dependency is a package your team explicitly chose. A transitive dependency is everything that package depends on — and everything *those* packages depend on. The depth can be surprising: + +``` +your-app +└── web-framework@4.2.0 (direct) + └── http-client@2.1.0 (transitive, depth 1) + └── xml-parser@1.8.3 (transitive, depth 2) + └── log4j@2.14.1 (transitive, depth 3) ← vulnerable +``` + +In this example, your application never imported Log4j, but it ships inside the image and is reachable. SCA tools resolve the full graph; auditing direct dependencies only leaves the depth-2 and depth-3 layers invisible. + +## Package URL (PURL) format + +SCA tools and SBOMs use **Package URLs (PURLs)** to uniquely identify components across ecosystems: + +``` +pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1 +pkg:npm/%40angular/core@16.0.0 +pkg:pypi/requests@2.31.0 +pkg:golang/github.com/gin-gonic/gin@v1.9.1 +``` + +PURLs enable unambiguous cross-tool correlation: when an SBOM, a scanner, and a vulnerability database all use the same PURL, findings can be mapped without manual disambiguation. + +## Reachability analysis + +Most dependency CVEs are never actually exploitable in a given application. Standard SCA flags every known CVE regardless of whether the vulnerable code is called. **Reachability analysis** goes further: it builds a call graph of your application code and determines whether execution can actually reach the vulnerable function. + +How it works: +1. Identify the vulnerable function(s) named in the CVE advisory (e.g., `JndiLookup.lookup()` in Log4Shell). +2. Build a call graph from the application's entry points (API handlers, message consumers, scheduled jobs). +3. Determine if any path in the call graph reaches the vulnerable function. +4. If no path reaches it — even though the package is present — the vulnerability is **not reachable** and is deprioritized. + +Tools like Endor Labs, Snyk, and Semgrep Supply Chain can reduce actionable SCA findings by 60–85% for typical Java and JavaScript applications using reachability analysis. This dramatically reduces alert fatigue and lets teams focus on genuine risk. + +## VEX workflow + +Vulnerability Exploitability eXchange (VEX) is a machine-readable statement declaring whether a known CVE affects a specific product: + +| VEX status | Meaning | +|---|---| +| `affected` | The vulnerability affects this product version — remediation required. | +| `not_affected` | The vulnerable code is present but not exploitable (e.g., not reachable, feature disabled). | +| `fixed` | The vulnerability was present and has been remediated in this version. | +| `under_investigation` | Impact assessment is in progress. | + +**Step-by-step VEX workflow:** +1. SCA scanner flags CVE-YYYY-NNNN in a dependency. +2. Developer or security engineer investigates: is the vulnerable code path reachable? Is the affected feature enabled? +3. If not reachable: create a `not_affected` VEX statement with justification (e.g., "vulnerable HTTP server module never initialized; application uses embedded server"). +4. Attach the VEX document to the SBOM (CycloneDX supports inline VEX; OpenVEX is a standalone format). +5. Downstream consumers — customers, operators, compliance teams — consume VEX and discard irrelevant findings automatically. +6. If `under_investigation`: set a resolution deadline (e.g., 5 business days) and assign an owner. + +## SCA gate policies + +Define clear, enforceable policies at the pipeline gate level: + +```yaml +# Example Grype/Dependency-Track gate policy (pseudo-configuration) +policy: + block: + - severity: CRITICAL # CVSS >= 9.0 + - severity: HIGH # CVSS >= 7.0, with EPSS >= 0.5 + - cisa_kev: true # Any KEV-listed CVE, any severity + warn: + - severity: HIGH # CVSS >= 7.0 (without EPSS filter) + - severity: MEDIUM # CVSS >= 4.0, reachable + allow: + - severity: LOW + - not_reachable: true # Reachability analysis clears it + - vex_status: not_affected +``` + +Apply the block policy to pull requests (new findings only, vs. baseline). Apply the full scan to nightly runs and report to the central dashboard. + +## SCA in monorepos + +Monorepos introduce additional complexity: +- Multiple language ecosystems in one repository (Go services, Python scripts, Node frontends). +- Shared internal libraries with their own dependency trees. +- Different release cadences per service within the same repo. + +Best practices for monorepo SCA: +- Configure the scanner to detect package manifests recursively (`--recursive` in most tools). +- Tag findings with the service or module path so ownership is clear. +- Generate per-service SBOMs, not a single monorepo SBOM — downstream consumers need component scope, not the entire monorepo inventory. +- Use Dependency-Track projects to represent individual services, even if they share a repo. + +## Integrating SCA in the pipeline + +```yaml +# Example: Grype scan in GitHub Actions +- name: Scan dependencies with Grype + uses: anchore/scan-action@v3 + with: + path: "." + fail-build: true + severity-cutoff: high + output-format: sarif +- name: Upload SARIF results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif +``` + +- **At every dependency change** (lock file update, PR) — catch new vulnerabilities before they merge. +- **On a schedule** — new CVEs are disclosed daily against existing dependencies; nightly scans catch what wasn't vulnerable at merge time. +- **In the registry** — continuously rescan stored images and artifacts as the vulnerability database grows. +- **At admission/deploy** — policy gates reject artifacts with unresolved criticals (see [Security Gates](../2-3-5-Security-Gates.md)). + +## SCA and the supply chain + +SCA is tightly linked to the [SBOM](../2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md): the SBOM is the inventory of components, and SCA continuously checks that inventory against new vulnerability intelligence — so a newly disclosed CVE can be mapped to every affected application even after release. This is what enables rapid response to incidents like Log4Shell without manual auditing across hundreds of repositories. + +## Common pitfalls and anti-patterns + +- **Scanning only at build time** — vulnerabilities disclosed after release require continuous scanning of stored artifacts, not just point-in-time CI scans. +- **No license policy** — finding GPL code in a commercial product after it ships is expensive. Define an approved-license list and enforce it as a gate. +- **Ignoring transitive dependencies** — many exploited vulnerabilities are in transitive, not direct, dependencies. Ensure your SCA tool resolves the full graph. +- **Alert fatigue from untuned gates** — blocking on every medium CVE in a transitive dependency kills developer trust quickly. Tune to reachable, high/critical findings first. +- **Not consuming advisories from maintainers** — NVD lags; maintainer advisories (GitHub Advisory Database, npm advisories, PyPI) often arrive days earlier. Use tools that consume both. +- **No VEX program** — without VEX, every `not_affected` finding must be manually triaged each time it resurfaces. VEX turns that into a one-time documented decision. + +## Maturity progression + +**Starter** — Run OWASP Dependency-Check or Trivy in CI. Report findings to a dashboard. Establish a baseline of existing vulnerabilities. + +**Intermediate** — Gate pull requests on new high/critical findings. Enforce a license allowlist. Schedule nightly scans of existing artifacts. Feed results into a central tracker (Dependency-Track). Produce SBOMs per service. + +**Advanced** — Add reachability analysis to cut noise by 60–85%. Produce and publish VEX statements per release. Continuously monitor SBOMs in Dependency-Track with real-time CVE alerting. Track mean time to remediate by severity and measure the exploitable-to-total-findings ratio. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| Mean time to remediate (critical CVE, KEV-listed) | < 24 hours | +| Mean time to remediate (critical CVE, non-KEV) | < 7 days | +| % of critical findings with reachability context | > 80% | +| Unlicensed or unapproved-license components | 0 | +| Nightly scan freshness | < 24 hours since last scan per artifact | +| Components at end-of-life | Tracked and on remediation roadmap | +| VEX coverage (findings with a VEX status) | > 90% for critical/high | + +--- + +## Tools[^1] + +### Open-source + +- [cdxgen](https://github.com/CycloneDX/cdxgen) — Generates CycloneDX SBOMs for many ecosystems (Node, Python, Java, Go, etc.); the easiest way to produce an SBOM that feeds into SCA tooling. Broad language support makes it ideal for polyglot monorepos. +- [Grype](https://github.com/anchore/grype) — Vulnerability scanner for container images and filesystems; fast, pairs naturally with Syft for SBOM-first scanning. Best for teams wanting a lightweight, scriptable CLI scanner. +- [OWASP Dependency-Check](https://owasp.org/www-project-dependency-check/) — Long-established CVE scanner across many languages; easy to add to Maven, Gradle, or CI pipelines. Best for Java/JVM-heavy environments. +- [OWASP Dependency-Track](https://dependencytrack.org/) — Continuous SCA platform that ingests SBOMs and monitors them for new vulnerabilities; best-in-class for SBOM-centric operations and VEX management. The reference platform for SBOM-driven SCA at scale. +- [Trivy](https://github.com/aquasecurity/trivy) — All-in-one scanner for dependencies, images, and IaC; excellent breadth and ease of setup for teams wanting a single tool. Falls short on reachability analysis compared to commercial alternatives. + +### Commercial + +- [Endor Labs](https://www.endorlabs.com/) — SCA with call-graph reachability; dramatically reduces noise by confirming which vulnerable functions are actually reached. Best for large Java/JavaScript organizations with high false-positive fatigue. +- [Mend (formerly WhiteSource)](https://www.mend.io/) — Comprehensive open-source dependency and license risk management with broad language support. Strong license compliance workflow for legal teams. +- [Snyk Open Source](https://snyk.io/product/open-source-security-management/) — Developer-first dependency vulnerability and license scanning with fix PR automation; strong for developer adoption. Best-in-class developer experience; reachability available for select ecosystems. +- [Sonatype Nexus Lifecycle](https://www.sonatype.com/products/open-source-security-dependency-management) — Component intelligence integrated into the artifact repository; blocks vulnerable components before they enter the build. Best for organizations using Nexus as their artifact registry. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md b/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md index 7467cbb..f419688 100644 --- a/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md +++ b/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md @@ -1,29 +1,182 @@ -# Container Vulnerability Scanning +# Container Scanning + +Containers package an application together with its operating-system libraries and dependencies. That convenience also means a single image can carry hundreds of inherited vulnerabilities from its base layers and OS packages. **Container scanning** inspects images for known vulnerabilities, misconfigurations, and embedded secrets — across the build, the registry, and at deployment. + +## The container vulnerability lifecycle + +Understanding when and how vulnerabilities enter images is essential for an effective scanning strategy: + +``` +1. Base image published (debian:12, ubuntu:22.04, python:3.11-slim) + │ + ▼ +2. Your CI pulls the base image → vulnerability snapshot at pull time + │ + ▼ +3. Build: ADD application code, install dependencies (pip, npm, apt) + │ + ▼ +4. Image pushed to registry — clean at this point + │ + ▼ +5. New CVE disclosed against a library in the base image (days, weeks, months later) + │ + ▼ +6. Registry continuous scanning detects the new CVE in stored image + │ + ▼ +7. Alert → team must rebuild (base image bump) and redeploy +``` + +The critical insight: **a build-time scan is a point-in-time snapshot**. An image that passes today may fail tomorrow when a new CVE is disclosed against a library that was already present. This is why registry-level continuous scanning is not optional — it is the mechanism that catches post-build exposure. + +## What container scanning checks + +- **OS package vulnerabilities** — CVEs in the base image and installed system packages (glibc, openssl, zlib, etc.). +- **Application dependency vulnerabilities** — language libraries bundled into the image (overlaps with [SCA](../2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md), but scoped to what is inside the image layers). +- **Misconfigurations** — running as root, exposed ports, insecure defaults in the Dockerfile. +- **Embedded secrets** — credentials accidentally baked into image layers; note that a secret added in one layer and deleted in the next is still present in the image history and fully recoverable with `docker history`. +- **Malware / unexpected content** — files that should not be present, suspicious binaries, or unexpected network listeners. +- **License compliance** — OS packages often carry different licenses than application code. + +## Where to scan -As containers become an almost ubiquitous method of packaging and deploying applications, the instances of malware have increased. Securing containers is now a top priority for DevOps engineers. Fortunately, a number of open source programs are available that scan containers and container images. Let’s look at five such tools. +Scan at multiple points so nothing slips through: + +- **Build time** — scan the image as part of CI immediately after the build step; gate on severity before pushing to any registry. +- **Registry** — continuously rescan stored images, since *new* CVEs are disclosed against images that were clean when built. Most enterprise registries (Harbor, ECR, Artifact Registry) support built-in continuous scanning. +- **Admission / deploy time** — block non-compliant or unsigned images from reaching the cluster (see [Deploy](../../2-6-Deploy/2-6-1-Deploy.md)). This is the last line of defense. + +```yaml +# Example: Trivy scan in GitHub Actions at build time +- name: Build Docker image + run: docker build -t myapp:${{ github.sha }} . -## What can Container Security Scanning do? +- name: Scan image with Trivy + uses: aquasecurity/trivy-action@master + with: + image-ref: myapp:${{ github.sha }} + format: sarif + output: trivy-results.sarif + severity: HIGH,CRITICAL + exit-code: '1' -- Detect insecure containers - - Detect outdated libraries - - Detect incorrectly configured containers - - Detect outdated operating system -- Detect compliance validations -- Suggest best practices +- name: Upload Trivy SARIF + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: trivy-results.sarif +``` -## Issues with Container Security Scanner +## Generating SBOMs from container images -- Level of depth depends on tool being used, So the results that you'll get are very dependent on the type of tool you choose. -- Easy to go "too far" with configuration, there are tools where you can configure so much different settings, that it's easy to jump overboard. -- The scan results will lead to actionable events? +Container scanning and SBOM generation are complementary. Generate an SBOM from the built image to capture exactly what packages are present at runtime — not what the source code imports, but what the image actually contains: -## Where and When to use Container Scanner? +```bash +# Generate a CycloneDX SBOM from a container image using Syft +syft myapp:latest -o cyclonedx-json > sbom.json -![Development process diagram showing container scanning](/current-version/assets/images/Dev-process.png) +# Attach the SBOM as a signed attestation to the registry (requires cosign) +cosign attest --predicate sbom.json \ + --type cyclonedx \ + myregistry/myapp@$(crane digest myregistry/myapp:latest) -You can use it at the build phase when you're actually building for instance a Dockerfile and looking at the resulting image that you're creating. Another location to perform container scanning would be when you push a container to the registry or when you pull a container from a registry. However, a good approach is scanning before pushing into a trusted container registry then you can say we have a container registry with a scanned version of all images and for deploying in production you can pull from this trusted container registry. (Plase take look into the following image) +# Later: verify and retrieve the SBOM +cosign verify-attestation --type cyclonedx myregistry/myapp:latest | \ + jq '.payload | @base64d | fromjson | .predicate' +``` -![Container security pipeline showing scanning process](/current-version/assets/images/container-security-pipeline.png) +This SBOM can then be ingested by Dependency-Track for continuous CVE monitoring against the image's exact component inventory. See [SBOM](../2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md) for the full SBOM workflow. + +## Multi-architecture image scanning + +Multi-arch images (`linux/amd64`, `linux/arm64`) can have different vulnerabilities per platform because they pull different OS packages from the base image. Ensure scanning covers all target architectures: + +```bash +# Scan specific platform explicitly +trivy image --platform linux/arm64 myapp:latest + +# Scan all platforms in a manifest list +for platform in linux/amd64 linux/arm64; do + trivy image --platform $platform myapp:latest +done +``` + +CI pipelines that build multi-arch images must scan each variant — a vulnerability in the `arm64` image does not appear in an `amd64` scan. + +## Reducing inherited risk: distroless and minimal images + +The most effective way to cut container vulnerabilities is to start from a minimal base. The numbers are stark: + +| Base image | Approximate CVE count | Shell available | +|---|---|---| +| `ubuntu:22.04` | 30–80 CVEs (varies) | Yes | +| `debian:12-slim` | 15–40 CVEs (varies) | Yes | +| `python:3.11-slim` | 20–50 CVEs (varies) | Yes (via debian-slim) | +| `gcr.io/distroless/python3` | 0–5 CVEs | No | +| `gcr.io/distroless/static` | 0–2 CVEs | No | +| `scratch` | 0 | No | + +**Distroless images** (Google's `gcr.io/distroless/*`) ship no shell, no package manager, and no unnecessary OS tools. An attacker who achieves code execution in a distroless container has almost no utilities to work with — no `curl`, no `wget`, no `bash`, no `apt`. This dramatically reduces the blast radius of any container escape. + +**Multi-stage builds** achieve the same result for compiled languages: + +```dockerfile +# Stage 1: build (full toolchain) +FROM golang:1.22 AS builder +WORKDIR /app +COPY . . +RUN go build -o /bin/myapp ./cmd/myapp + +# Stage 2: runtime (minimal — no Go toolchain, no compilers) +FROM gcr.io/distroless/static-debian12:nonroot AS runtime +COPY --from=builder /bin/myapp /bin/myapp +USER nonroot:nonroot +ENTRYPOINT ["/bin/myapp"] +``` + +The builder stage, with its compilers and development dependencies, never ships. The runtime image is a clean, minimal artifact. + +## Pinning base images to digests + +Tags are mutable — `python:3.11-slim` today may not be the same image as `python:3.11-slim` tomorrow: + +```dockerfile +# BAD: tag is mutable +FROM python:3.11-slim + +# GOOD: pinned to immutable digest +FROM python:3.11-slim@sha256:abc123def456... +``` + +Combine digest pinning with a weekly automated rebuild (Dependabot, Renovate, or a scheduled CI job) that bumps the digest and rescans. This ensures you absorb upstream security patches without introducing unvetted changes. + +## Common pitfalls and anti-patterns + +- **Scanning only in CI, not in the registry** — a vulnerability disclosed six months after an image was built will never be caught without continuous registry scanning. +- **Scanning the wrong layer** — running SCA on source code and separately scanning the image can produce discrepancies. The image scan is authoritative for what actually ships. +- **Using `:latest` tags for base images** — always pin to digests in production Dockerfiles; mutable tags break reproducibility and scanning consistency. +- **Secrets committed in an earlier layer** — adding a secret in one layer and removing it in the next does not remove it from the image history. Use `--secret` at build time or pass secrets at runtime via the orchestrator. +- **Alert fatigue from base-image noise** — a base image upgrade can introduce dozens of new OS-level CVEs. Filter by severity and prioritize those with public exploits or runtime reachability context. +- **Not scanning multi-arch variants** — vulnerabilities in the `arm64` variant do not appear in an `amd64` scan. + +## Maturity progression + +**Starter** — Run Trivy or Grype on every image in CI. Block on critical severity. Do not push unscanned images to the registry. + +**Intermediate** — Enable continuous registry scanning (Harbor, ECR native scanning, or Trivy Operator in Kubernetes). Gate deployments with an admission controller that rejects images with unresolved criticals. Migrate base images to minimal/distroless equivalents. Pin base images to digests. + +**Advanced** — Generate SBOMs for every image with Syft; attach as signed attestations; ingest into Dependency-Track for continuous monitoring. Automate weekly base image rebuilds via Dependabot/Renovate. Use reachability analysis to differentiate exploitable from theoretical OS CVEs. Scan all multi-arch variants. Track base image age and vulnerable-image-days as KPIs. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| Images with unresolved critical CVEs in production | 0 | +| Mean age of base images before rebuild | < 30 days | +| Registry scan freshness | < 24 hours per image | +| % of images using minimal/distroless base | > 80% | +| Images pinned to digest (not tag) | 100% in production | +| Images with attached, signed SBOM in registry | 100% | --- @@ -31,22 +184,20 @@ You can use it at the build phase when you're actually building for instance a D ### Open-source -- [Clair](https://github.com/quay/clair) - Vulnerability Static Analysis for Containers -- [Anchore](https://anchore.com/opensource/) - Open-source project for deep analysis of docker images -- [Dagda](https://github.com/eliasgranderubio/dagda/) - A tool to perform static analysis of known vulnerabilities, trojans, viruses, malware & other malicious threats in docker images/containers and to monitor the docker daemon and running docker containers for detecting anomalous activities -- [Falco](https://falco.org/) - Falco, the cloud-native runtime security project, is the de facto Kubernetes threat detection engine -- [Harbor](https://goharbor.io/) - Harbor is an open source registry that secures artifacts with policies and role-based access control, ensures images are scanned and free from vulnerabilities, and signs images as trusted. -- [Trivy](https://aquasecurity.github.io/trivy/) - Trivy is a simple and comprehensive vulnerability/misconfiguration scanner for containers and other artifacts. -- [Kbescape](https://github.com/armosec/kubescape) - Kubescape is a K8s open-source tool providing a multi-cloud K8s single pane of glass, including risk analysis, security compliance, RBAC visualizer and image vulnerabilities scanning. +- [Clair](https://github.com/quay/clair) — Static analysis of vulnerabilities in container images; powers scanning in Quay and other registries; best for self-hosted registry integration rather than CI pipelines. +- [Dockle](https://github.com/goodwithtech/dockle) — Container image linter focused on Dockerfile best practices and CIS benchmark alignment; complements vulnerability scanners rather than replacing them. +- [Grype](https://github.com/anchore/grype) — Fast vulnerability scanner for container images and filesystems; pairs naturally with Syft for SBOM-driven scanning. Best for CI pipelines needing a lightweight, scriptable CLI. +- [Syft](https://github.com/anchore/syft) — SBOM generator for container images and filesystems; produces SPDX and CycloneDX; the standard pairing for Grype. +- [Trivy](https://github.com/aquasecurity/trivy) — Comprehensive scanner for images, filesystems, IaC, and SBOMs; single binary, easy CI integration, broad vulnerability database. Best all-in-one option for most teams. ### Commercial -- [Aquasec](https://www.aquasec.com/products/container-vulnerability-scanning/) - With Aqua’s advanced vulnerability scanning & management DevOps can detect vulnerabilities, embedded secrets, and other risks during the development cycle, and prioritize mitigation by risk-based insights. Available on Aqua Enterprise, Self-hosted or SaaS. +- [Docker Scout](https://www.docker.com/products/docker-scout/) — Integrated image analysis and base-image remediation guidance built into Docker Hub and Docker Desktop. Best for teams heavily in the Docker ecosystem. +- [Snyk Container](https://snyk.io/product/container-vulnerability-management/) — Container vulnerability scanning with base-image recommendations and automatic Dockerfile fix PRs. Strong developer experience. +- [Wiz](https://www.wiz.io/) — Cloud and container vulnerability management as part of a CNAPP; strong for correlating image findings with actual cloud exposure and runtime context. --- ### Links -- [Opensource.com - tools for container security](https://opensource.com/article/18/8/tools-container-security) - [^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md b/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md index fae61dc..ad2d774 100644 --- a/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md +++ b/current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md @@ -1,45 +1,129 @@ # Container Hardening -Containers have revolutionized the way applications are deployed and managed, offering flexibility and scalability. However, like any other technology, containers are not immune to security risks. To mitigate these risks, it is crucial to implement container hardening practices. This document outlines best practices and guidelines for securing containers and provides references for further information. +Scanning tells you what is *wrong* with an image; **hardening** is how you build images that are right by construction — small, minimal-privilege, and resistant to compromise. A hardened container limits both the likelihood of a vulnerability being exploitable and the blast radius if one is exploited. Defense-in-depth applies at every layer: image content, runtime configuration, and cluster policy. -## Container Hardening Best Practices +## Build a minimal image -- **Use Only Trusted Base Images** -Ensure that you use base images from trusted sources, such as official repositories or reputable vendors. Regularly update base images to include the latest security patches and fixes. +Every package, binary, and layer you include is a potential attack surface. The goal is to ship only what the application needs to run: -- **Apply Security Patches** -Keep all container software and dependencies up to date by regularly applying security patches. This includes the host system, container runtime, and any additional software or libraries. +- **Use minimal or distroless base images** — every package you omit is a vulnerability you cannot inherit. Google's [distroless images](https://github.com/GoogleContainerTools/distroless) contain only a language runtime and application code — no shell, no package manager, no debugging tools. An attacker who achieves code execution has nowhere to go. +- **Multi-stage builds** — compile in a full build stage and copy only the final artifact into a clean minimal runtime stage: -- **Implement Principle of Least Privilege** -Apply the principle of least privilege to container configurations. Limit container capabilities, such as restricting root access and minimizing privilege escalation opportunities. + ```dockerfile + # Build stage + FROM golang:1.22 AS builder + WORKDIR /app + COPY . . + RUN CGO_ENABLED=0 go build -o myapp ./cmd/server -- **Enable Resource Limitations** -Define resource limitations for containers to prevent resource exhaustion attacks. Set appropriate limits for CPU, memory, and network bandwidth to ensure fair resource sharing and protect against DoS attacks. + # Runtime stage — no build tools, no shell + FROM gcr.io/distroless/static-debian12 + COPY --from=builder /app/myapp /myapp + ENTRYPOINT ["/myapp"] + ``` -- **Use Image Vulnerability Scanning** -Employ image vulnerability scanning tools to identify and remediate known vulnerabilities in container images. These tools can provide valuable insights into security risks and suggest appropriate fixes. Check out [Container Vulnerability Scanning](3-1-3-1-Container-scanning.md) for more information. +- **Pin base images to digests** — mutable tags (`:latest`, `:22.04`) can change without warning. Pin to an immutable digest and automate periodic base image rebuilds: -- **Employ Secure Network Configuration** -Implement network security controls, such as container network segmentation and isolation. Use firewalls and network policies to restrict container communication and prevent unauthorized access. + ```dockerfile + FROM ubuntu@sha256:abc1234... AS base + ``` -- **Harden Host Systems** -Ensure that host systems running container engines are hardened and regularly updated. Follow best practices for securing the underlying infrastructure, including patch management, access control, and intrusion detection. +- **No secrets in layers** — every layer is permanently part of the image history. Use `--secret` mounts for build-time secrets and runtime environment injection for all credentials. -- **Implement Container Runtime Security Measures** -Utilize security features provided by container runtimes, such as SELinux, AppArmor, or seccomp, to enforce additional security policies and restrict container behavior. +## Run with least privilege -- **Monitor Container Activity** -Implement logging and monitoring mechanisms to detect and respond to security incidents. Monitor container behavior, access logs, and system logs to identify any suspicious activity. +A container that runs as root and has broad Linux capabilities is one kernel exploit away from a full host compromise: -- **Secure Container Registry** -Protect container images by securing the container registry. Implement authentication, access controls, and encryption to ensure that only authorized users can access and modify container images. +- **Non-root user** — always set a non-root `USER` in the Dockerfile. For distroless images, use the nonroot variant: + + ```dockerfile + USER nonroot:nonroot + ``` + +- **Read-only root filesystem** — mount the container filesystem read-only; declare explicit writable volumes only where needed: + + ```yaml + # Kubernetes pod spec + securityContext: + readOnlyRootFilesystem: true + volumeMounts: + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: {} + ``` + +- **Drop Linux capabilities** — start from zero and add back only what is required. Most application containers need no capabilities at all: + + ```yaml + securityContext: + capabilities: + drop: ["ALL"] + add: [] # add only if explicitly required, e.g. NET_BIND_SERVICE + allowPrivilegeEscalation: false + ``` + +- **No privileged containers** — avoid `--privileged` and host namespace sharing (`hostPID`, `hostNetwork`, `hostIPC`). These break container isolation entirely. +- **Resource limits** — set CPU and memory limits to contain denial-of-service conditions and runaway workloads. An unconstrained container can starve co-located services. + +## Verify against benchmarks + +Measure image and runtime configuration against established security baselines rather than relying on internal convention: + +- [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker) — covers the Docker daemon, image build practices, and container runtime configuration. +- [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes) — covers the Kubernetes control plane, worker nodes, and etcd configuration. +- [Kubernetes Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) — defines three profiles (Privileged, Baseline, Restricted); enforce the `Restricted` profile for all production workloads via namespace labels and admission controllers. +- Run **kube-bench** and **Docker Bench for Security** as part of CI for infrastructure validation. + +## Tie into the supply chain + +Hardened images should also be **signed and traceable**. Sign images with cosign/Sigstore and attach provenance (SLSA) and SBOMs as attestations so that only verified, hardened images are admitted to production — see [Artifact Signing and Provenance](../2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md) and [Container Scanning](2-3-3-1-Container-Scanning.md). + +## Common pitfalls and anti-patterns + +- **Hardening the Dockerfile but leaving a debug sidecar running in production** — sidecars with shells and tools negate the work done in the main container. +- **`USER` set to a non-root UID but without a matching group** — some applications rely on group membership; verify runtime behavior after adding the USER directive. +- **Assuming distroless means invulnerable** — distroless dramatically reduces the attack surface but the language runtime and your application code still carry their own vulnerabilities. Scanning remains necessary. +- **Resource limits set too tight** — containers that hit memory limits are OOM-killed; set limits based on real profiling, not guesses. +- **Build tools left in final image** — compilers, package managers, and test frameworks significantly increase image size and attack surface. Enforce multi-stage builds in code review. + +## Maturity progression + +**Starter** — Enforce non-root `USER` in all Dockerfiles. Add hadolint to CI to lint Dockerfiles. Remove obviously unnecessary packages from base images. + +**Intermediate** — Migrate to distroless or minimal base images. Enforce multi-stage builds. Add `readOnlyRootFilesystem: true` and drop all capabilities in Kubernetes manifests. Run kube-bench in CI for infrastructure pipelines. + +**Advanced** — Pin all base images to digests; automate weekly rebuilds. Sign images with Sigstore keyless signing and verify at admission with Kyverno or the Sigstore policy controller. Enforce `Restricted` pod security standards cluster-wide. Use Chainguard Images for critical base images; track CVE count and mean severity of base images as operational KPIs. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| % of containers running as non-root | 100% | +| % of containers with read-only root filesystem | > 90% | +| % of containers with all capabilities dropped | > 90% | +| % of images using minimal/distroless base | > 80% | +| kube-bench score (CIS benchmark pass rate) | > 95% | + +--- + +## Tools[^1] + +### Open-source + +- [Docker Bench for Security](https://github.com/docker/docker-bench-security) - Checks Docker hosts and containers against CIS benchmark recommendations; useful as a configuration audit step. +- [Dockle](https://github.com/goodwithtech/dockle) - Dockerfile and image linter for security best practices; catches common misconfigurations before the image is built. +- [hadolint](https://github.com/hadolint/hadolint) - Dockerfile linter enforcing best practices including multi-stage build patterns, pinned digests, and non-root USER; integrates with most CI systems and IDEs. +- [kube-bench](https://github.com/aquasecurity/kube-bench) - Checks Kubernetes cluster configuration against the CIS Kubernetes Benchmark; runs as a job in the cluster or in CI for infrastructure pipelines. + +### Commercial + +- [Chainguard Images](https://www.chainguard.dev/) - Continuously rebuilt, SLSA-signed minimal container base images with near-zero CVEs; eliminates base-image vulnerability debt by design. +- [Sysdig Secure](https://sysdig.com/products/secure/) - Container hardening, drift detection, and runtime security for Kubernetes; detects when a running container deviates from its hardened image. --- ### Links -- [CIS Benchmarks for Docker and Kubernetes](https://www.cisecurity.org/benchmark/docker/) -- [Docker Security](https://docs.docker.com/engine/security/) -- [Kubernetes Security](https://kubernetes.io/docs/concepts/security/) -- [NIST Special Publication 800-190: Application Container Security Guide](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-190.pdf) -- [OWASP Docker Security Project](https://owasp.org/www-project-docker-security/) +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md b/current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md new file mode 100644 index 0000000..5739aa2 --- /dev/null +++ b/current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md @@ -0,0 +1,228 @@ +# Infrastructure as Code (IaC) Scanning + +Infrastructure is now defined in code — Terraform, CloudFormation, Kubernetes manifests, Helm charts, Ansible, and more. That means infrastructure misconfigurations can be caught with the **same shift-left discipline as application code**: scanned statically, before anything is provisioned. IaC scanning finds insecure defaults and policy violations early, when they are a one-line fix rather than a production incident costing hours of remediation and potential data exposure. + +## The Capital One breach: IaC misconfiguration at scale + +In 2019, the Capital One breach exposed over 100 million customer records. The root cause was an overly permissive IAM role — a Server Side Request Forgery (SSRF) vulnerability allowed an attacker to query the EC2 metadata service, which returned temporary credentials for an IAM role with excessive S3 permissions. That IAM role configuration was defined in infrastructure code. Had IaC scanning with IAM privilege analysis been in place, the overpermissioned role would have been flagged before it was ever applied. The breach cost Capital One over $80 million in fines and settlement costs. + +This is the canonical case for why IaC security cannot be treated as optional or post-deployment. + +## What IaC scanning finds + +- **Insecure cloud configuration** — public storage buckets (S3, GCS, Azure Blob), open security groups (0.0.0.0/0 ingress), unencrypted databases, overly permissive IAM policies and roles. +- **Kubernetes misconfigurations** — privileged pods, missing resource limits and requests, host mounts, weak or missing network policies, unenforced pod security standards. +- **Missing encryption and logging** — resources lacking encryption at rest or in transit; CloudTrail, VPC flow logs, or audit logging disabled. +- **Policy violations** — drift from organizational standards and compliance baselines (CIS, SOC 2, PCI-DSS, HIPAA). +- **Secrets in IaC** — hardcoded credentials, access keys, or passwords in Terraform variable files, Helm values, or Ansible vars. +- **Overprivileged network exposure** — databases reachable from the internet, internal services with public load balancers, unrestricted egress. + +## Misconfiguration examples by IaC type + +**Terraform (AWS):** +```hcl +# BAD: S3 bucket publicly accessible +resource "aws_s3_bucket_acl" "example" { + bucket = aws_s3_bucket.example.id + acl = "public-read" # flags CKV_AWS_20 +} + +# BAD: Security group open to world +resource "aws_security_group_rule" "bad" { + type = "ingress" + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] # flags CKV_AWS_25 +} + +# GOOD: Restrict SSH to known CIDR +resource "aws_security_group_rule" "good" { + type = "ingress" + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["10.0.0.0/8"] +} +``` + +**Kubernetes / Helm (running as root):** +```yaml +# BAD: Pod running as root +spec: + containers: + - name: app + securityContext: + runAsRoot: true # flags KSV001 + +# GOOD: Non-root, read-only filesystem +spec: + containers: + - name: app + securityContext: + runAsNonRoot: true + runAsUser: 1000 + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false +``` + +**CloudFormation (unrestricted ingress):** +```yaml +# BAD +SecurityGroupIngress: + - IpProtocol: -1 + CidrIp: 0.0.0.0/0 # flags W2902 + +# GOOD +SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: 10.0.0.0/8 +``` + +## Where it fits + +- **IDE and pre-commit** — instant feedback as infrastructure code is written; the cheapest possible fix point. +- **CI / pull request** — authoritative scan; gate merges on new high-severity misconfigurations. Infrastructure PRs carry the same risk as application PRs. +- **Pre-deploy** — final check before `terraform apply` or `kubectl apply`; combined with [Policy as Code](../../../3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md) to enforce guardrails at the cluster or cloud API level. + +```yaml +# Example: Checkov scan in GitHub Actions +- name: Scan Terraform with Checkov + uses: bridgecrewio/checkov-action@master + with: + directory: ./infra/terraform + framework: terraform + output_format: sarif + output_file_path: checkov-results.sarif + soft_fail: false + check: CKV_AWS_* + +- name: Upload SARIF results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: checkov-results.sarif +``` + +## Custom Checkov policies + +Out-of-the-box rules cover common benchmarks, but organizations need custom rules for internal standards. Checkov supports Python-based custom checks: + +```python +# custom_checks/check_rds_no_public_access.py +from checkov.common.models.enums import CheckCategories, CheckResult +from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck + +class RDSNoPublicAccess(BaseResourceCheck): + def __init__(self): + name = "Ensure RDS instance is not publicly accessible" + id = "CKV_CUSTOM_RDS_1" + supported_resources = ["aws_db_instance"] + categories = [CheckCategories.NETWORKING] + super().__init__(name=name, id=id, categories=categories, + supported_resources=supported_resources) + + def scan_resource_conf(self, conf): + publicly_accessible = conf.get("publicly_accessible", [False]) + if publicly_accessible == [True] or publicly_accessible is True: + return CheckResult.FAILED + return CheckResult.PASSED + +scanner = RDSNoPublicAccess() +``` + +Run with: `checkov -d ./infra --external-checks-dir ./custom_checks` + +## Shift-left IaC: IDE integration + +IDE plugins bring IaC scanning to the point of authorship — the cheapest fix: +- **VS Code Checkov extension** — real-time inline highlighting of misconfigurations as Terraform or Kubernetes YAML is written. No CLI required. +- **Snyk IaC VS Code plugin** — live fix suggestions alongside detected issues. +- **IntelliJ + Terraform plugin** — structural validation before any CI run. + +## Policy-as-code integration with OPA + +For organization-specific policies beyond CIS benchmarks, use OPA/Conftest to evaluate IaC against custom Rego rules in CI: + +```rego +# policies/terraform/no_public_s3.rego +package main + +deny[msg] { + resource := input.resource.aws_s3_bucket_acl[_] + resource.acl == "public-read" + msg := sprintf("S3 bucket ACL must not be public-read: %v", [resource]) +} +``` + +```bash +# In CI: evaluate rendered Terraform plan against policies +terraform plan -out=plan.tfplan +terraform show -json plan.tfplan > plan.json +conftest test plan.json --policy policies/terraform/ +``` + +## The drift detection gap + +IaC scanning checks the *declared* state. Runtime configuration can drift from what was applied — a developer makes a manual change in the console, an automated process modifies a resource, or an incident response action is never codified. This gap requires runtime posture management ([CNAPP](../../2-7-Operate/2-7-1-Cloud-Native-Security.md)) to catch the *actual* state and feed drift findings back into the IaC. A finding in IaC scanning does not guarantee the issue exists in production; a clean IaC scan does not guarantee the cloud environment is clean. + +## Scan Helm charts before installation + +Helm templates are rendered to Kubernetes manifests at deploy time. Scanning the raw templates misses values-substitution — a production `values.yaml` might override safe defaults with insecure ones. Always scan the rendered output: + +```bash +helm template myapp ./chart -f prod-values.yaml | trivy config - +helm template myapp ./chart -f prod-values.yaml | checkov -f /dev/stdin --framework kubernetes +``` + +## Common pitfalls and anti-patterns + +- **Suppressing findings by rule ID without documented justification** — suppression files accumulate silently. Require justification and owner for every suppression. +- **Scanning only Terraform, not Helm or CloudFormation** — multi-tool environments require multi-language IaC scanning. +- **No link between IaC findings and runtime posture** — a bucket flagged in IaC as "not public" may have been manually made public in the console. Without runtime CSPM, the IaC scan gives false assurance. +- **Policy-as-code rules that are too broad** — rules like "no security group with any port open" that fire for legitimate HTTPS traffic cause developers to disable the scanner. +- **Treating IaC scanning as purely a security responsibility** — platform engineers who write IaC should own the findings, just as developers own SAST results. +- **No baseline management** — gating on all existing findings on day one creates an unmergeable backlog. Gate on *new* findings first; reduce existing debt on a planned schedule. + +## Maturity progression + +**Starter** — Run Checkov or KICS in CI against all Terraform and Kubernetes manifests. Report findings. Establish a baseline of existing issues. Block the pipeline on new critical findings. + +**Intermediate** — Integrate scanning into IDE (VS Code Checkov extension, Snyk IaC). Map findings to CIS benchmarks and compliance frameworks. Add Helm chart scanning (rendered output). Enforce policy-as-code rules for the top 10 organization-specific constraints. + +**Advanced** — Implement full policy-as-code enforcement (OPA/Conftest in CI + Kyverno/OPA Gatekeeper in Kubernetes admission). Track and measure drift between declared IaC state and actual runtime state via CNAPP integration. Feed CSPM findings back into IaC as automated PRs. Align all IaC policies to SOC 2 / PCI controls and generate continuous compliance evidence. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| IaC PRs merged with new high/critical misconfigurations | 0 | +| Suppressed findings without documented justification | 0 | +| % of IaC surface area covered by scanning | 100% | +| Drift findings (runtime vs declared state) | Decreasing month-over-month | +| Mean time to remediate IaC critical findings | < 5 business days | +| Custom policies covering top internal standards | Tracked; gap analysis reviewed quarterly | + +--- + +## Tools[^1] + +### Open-source + +- [Checkov](https://www.checkov.io/) — Static analysis for Terraform, CloudFormation, Kubernetes, Helm, Bicep, and ARM; 1000+ built-in policies; supports custom Python and OPA rules, SARIF output. Best breadth for multi-IaC environments. +- [KICS](https://kics.io/) — Finds security vulnerabilities and misconfigurations in IaC; supports 24 IaC platforms; built-in compliance framework mappings. Strong for teams that need framework-aligned reporting (PCI, HIPAA). +- [Kubescape](https://github.com/kubescape/kubescape) — Kubernetes security scanning against NSA/CISA hardening guidance and MITRE ATT&CK; scans live clusters and IaC before apply. Best Kubernetes-specific coverage. +- [Terrascan](https://github.com/tenable/terrascan) — Detects compliance and security violations across Terraform, Kubernetes, Helm, and Dockerfiles; integrates with Argo CD for GitOps security. +- [Trivy](https://github.com/aquasecurity/trivy) — Scans IaC and configuration alongside CVE scanning; good choice for teams already using Trivy for container scanning who want one tool. + +### Commercial + +- [Prisma Cloud (IaC Security)](https://www.paloaltonetworks.com/prisma/cloud) — IaC scanning within a full CNAPP platform; strong compliance framework coverage and cloud-runtime correlation. Best for organizations also using Prisma for cloud posture management. +- [Snyk IaC](https://snyk.io/product/infrastructure-as-code-security/) — Developer-first IaC misconfiguration scanning with IDE plugins, PR checks, and fix guidance; fastest developer adoption curve. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-3-Build/2-3-5-Security-Gates.md b/current-version/2-Process/2-3-Build/2-3-5-Security-Gates.md index 6b3e1c4..b1a0cc9 100644 --- a/current-version/2-Process/2-3-Build/2-3-5-Security-Gates.md +++ b/current-version/2-Process/2-3-Build/2-3-5-Security-Gates.md @@ -1,3 +1,104 @@ # Security Gates - +A **security gate** is a checkpoint in the pipeline that decides whether code or an artifact is allowed to proceed — to merge, to be released, or to be deployed — based on security criteria. Gates are how shift-left scanning translates into actual risk reduction: a finding that never blocks anything rarely gets fixed. + +The hard part is not adding gates; it is designing gates that reduce risk **without destroying developer flow**. Gates that are too noisy or too strict get disabled, ignored, or bypassed. + +## Principles for effective gates + +- **Gate on risk, not raw counts** — block on severity, exploitability, and reachability, not on the total number of findings. A gate that blocks on "any medium CVE in any transitive dependency" will be overridden within a week. +- **Baseline existing issues** — hold teams accountable for *new* risk they introduce, not the entire backlog of legacy debt at once. Use a known-good baseline snapshot and block only on findings that did not exist in the baseline. +- **Fail fast and clearly** — when a gate blocks, tell the developer exactly what, where, and how to fix it. A gate that says "build failed" with no guidance is friction without value. +- **Provide a path forward** — support documented, time-boxed risk acceptance / exceptions with an owner, rather than forcing developers to silently disable checks. +- **Tune relentlessly** — high false-positive rates are the fastest way to lose developer trust; treat noise as a bug in the gate, not a developer compliance problem. + +## Where to place gates + +| Stage | Typical gate | Failure mode | +| --- | --- | --- | +| Pre-commit / IDE | Secrets, linting, fast SAST (advisory) | Advisory only — educate, don't block here | +| Pull request | SAST, SCA, IaC — block new high/critical | Block merge; surface in PR comment with fix guidance | +| Build | Full scans, container scan, SBOM generation | Block artifact promotion from build stage | +| Release | Signed artifacts, provenance, no unresolved criticals | Block publishing to production registry | +| Deploy | Admission control: only signed, policy-compliant artifacts | Block workload from running in cluster | + +```yaml +# Example: GitHub Actions gate using Semgrep — blocks on new high findings +- name: Semgrep SAST gate + uses: returntocorp/semgrep-action@v1 + with: + config: > + p/owasp-top-ten + p/secrets + publishToken: ${{ secrets.SEMGREP_APP_TOKEN }} + env: + SEMGREP_BASELINE_REF: ${{ github.base_ref }} # diff-aware: new findings only +``` + +## Exception and risk-acceptance process + +No gate system survives contact with reality without an exception process. Without one, developers disable gates rather than deal with blocked pipelines. A sound process: + +1. **Raise an exception request** — the developer (or team) documents the finding, explains why immediate remediation is not feasible (e.g., no fix available, legacy library), and proposes a compensating control. +2. **Approve with a risk owner** — a security engineer or application security lead reviews and approves; the approver takes ownership of the accepted risk. +3. **Time-box every exception** — set a hard expiry (e.g., 30 or 90 days). The gate re-engages automatically when the exception expires. Indefinite exceptions are not exceptions — they are hidden vulnerabilities. +4. **Track exceptions centrally** — maintain a register (in a vulnerability management tool or ticketing system) so accepted risks are visible to leadership, not hidden in `.semgrepignore` files. +5. **Review on a cadence** — include open exceptions in sprint planning and quarterly security reviews so they get addressed, not forgotten. Report exception counts and age to leadership as a risk indicator. + +## Smarter prioritization + +Mature programs increasingly drive gates from **correlated, contextual risk** rather than isolated scanner output. Application Security Posture Management ([ASPM](../../3-Governance/3-3-Reporting/3-3-3-ASPM.md)) aggregates findings across tools, deduplicates them, and adds code-to-runtime context so gates block on what is genuinely exploitable and reachable in production — keeping signal high and friction low. + +The evolution of gate intelligence: + +| Generation | What drives the gate | +|---|---| +| 1st | Raw count of findings above a severity threshold | +| 2nd | New findings since baseline, filtered by severity | +| 3rd | CVSS + EPSS + KEV — exploitability-weighted severity | +| 4th | Reachability + runtime exposure + ASPM correlation | + +## Common pitfalls and anti-patterns + +- **Gates without feedback** — a gate that blocks with no explanation sends developers to Google. Every blocked gate must link to the finding, the affected code, and remediation guidance. +- **Gates configured but not enforced** — required CI status checks must be enabled in branch protection rules; otherwise developers merge without them. +- **Exception process that requires security team approval for every finding** — creates a bottleneck and incentivizes teams to avoid scanning. Delegate tier-2 and tier-3 exception approvals to risk owners within the product team. +- **No visibility into exception trends** — if the exception register is growing every sprint, that is a systemic problem. Track exception counts, ages, and owners as board-level metrics. +- **Suppression via comments in source code** — `# nosec`, `// NOSONAR`, and `.semgrepignore` suppressions are invisible in most dashboards. Require that suppressions be tracked in the central exception register. + +## Maturity progression + +**Starter** — Enable SAST and SCA scans in CI. Run in advisory mode (report, don't block) for two sprints to establish baseline. Then block on new criticals. + +**Intermediate** — Gate pull requests on new high/critical SAST and SCA findings. Enforce a formal exception process. Track exceptions in DefectDojo or Jira. Add container scan gates at the build stage. + +**Advanced** — Drive gates from ASPM-correlated, reachability-enriched findings. Fully automate exception expiry. Measure false positive rate per scanner and tune quarterly. Report gate compliance and exception trends to engineering leadership monthly. + +## Tools + +| Category | Examples | +|---|---| +| Vulnerability tracking & gate integration | DefectDojo (open source), Archery | +| Policy-as-code gate enforcement | OPA/Conftest, Rego policies in CI, Kyverno (Kubernetes) | +| CI/CD native gates | GitHub branch protection + required status checks, GitLab merge request approvals, Jenkins Quality Gates | +| ASPM (correlated gate decisions) | Apiiro, Arnica, Ox Security, Cycode — see [ASPM](../../3-Governance/3-3-Reporting/3-3-3-ASPM.md) | +| Exception / risk-acceptance tracking | Jira (security issue type), ServiceNow, DefectDojo risk acceptance workflow | + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| % of PRs passing security gates without exception | > 95% | +| Open exceptions older than 90 days | 0 | +| Gate false positive rate | < 15% per tool | +| Findings that escape to production | Decreasing quarter-over-quarter | +| Mean time from gate block to resolution | < 3 business days (critical) | + +--- + +## Further reading + +- [OWASP DSOMM — Test & Verification](https://dsomm.owasp.org/) +- [OWASP Top 10 CI/CD Security Risks](https://owasp.org/www-project-top-10-ci-cd-security-risks/) +- [NIST SSDF — PW & RV practices](https://csrc.nist.gov/Projects/ssdf) +- [DefectDojo documentation](https://defectdojo.github.io/django-DefectDojo/) diff --git a/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md b/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md new file mode 100644 index 0000000..a05bbf1 --- /dev/null +++ b/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md @@ -0,0 +1,117 @@ +# Software Bill of Materials (SBOM) + +A **Software Bill of Materials (SBOM)** is a formal, machine-readable inventory of every component that makes up a piece of software — its open-source and third-party dependencies, versions, and relationships. Just as a food label lists ingredients, an SBOM lets you (and your customers) know exactly what is inside an application. When a new vulnerability like Log4Shell is disclosed, an organization with SBOMs can answer "are we affected, and where?" in minutes instead of weeks. + +## Why SBOMs matter + +- **Rapid vulnerability response** — instantly map a new CVE to every affected artifact across your estate. Without SBOMs, Log4Shell-style responses require manual inventory across hundreds of repositories. +- **Supply-chain transparency** — know your transitive dependencies, not just direct ones. The 2021 Executive Order found that most organizations could not accurately enumerate their software components. +- **Regulatory drivers** — SBOMs are increasingly required (US [Executive Order 14028](https://www.cisa.gov/sbom), EU Cyber Resilience Act, FDA guidance for medical devices) for software sold to governments and regulated markets. +- **License and risk management** — feed SBOM data into [SCA](../2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md), license checks, and procurement decisions. +- **Customer assurance** — enterprise customers increasingly request SBOMs as part of vendor security questionnaires and procurement due diligence. + +## Generating SBOMs well + +- **Generate during the build**, not after the fact — only the build sees the exact resolved dependency tree, so build-time SBOMs are the most accurate. Post-build SBOMs are reconstructions, not observations. +- **Use a standard format** — the two dominant machine-readable standards are [SPDX](https://spdx.dev/) and [CycloneDX](https://cyclonedx.org/). Publish at least one; CycloneDX is generally better supported by tooling for vulnerability analysis. +- **Produce SBOMs at multiple layers** — source (lock files), container image (OS packages + application dependencies), and final artifact each tell part of the story. +- **Store and version them alongside the artifact**, ideally as a signed attestation attached to the artifact in the registry: + + ```bash + # Generate SBOM with Syft for a container image + syft myapp:v1.2.3 -o cyclonedx-json > sbom.json + + # Attach as a signed attestation with cosign + cosign attest --predicate sbom.json --type cyclonedx myapp:v1.2.3 + ``` + + ```bash + # Generate SBOM for a repository with cdxgen + cdxgen -t java -o sbom.json . + ``` + +## SBOM content requirements + +For a useful SBOM (per CISA minimum elements guidance): +- Component name, version, and supplier/origin +- Unique identifiers (CPE, PURL — Package URL is now the preferred identifier) +- Dependency relationships (not just a flat list) +- Author and timestamp of the SBOM itself +- SBOM format version and creation tool + +Package URL (PURL) is the key interoperability identifier: +``` +pkg:npm/%40angular/core@15.2.0 +pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1 +pkg:pypi/requests@2.28.0 +``` + +## From static lists to living SBOMs + +A one-time SBOM goes stale the moment a new vulnerability is disclosed. The current best practice is the **living, enriched SBOM**: + +- **Continuously re-evaluate** stored SBOMs against new vulnerability intelligence. When a new CVE is published, Dependency-Track or a similar platform automatically identifies every SBOM containing the affected component. +- **Enrich with VEX** (Vulnerability Exploitability eXchange) — publish VEX documents that declare whether a listed vulnerability actually affects your product and why (e.g., "Log4Shell: affected function not reachable from network input"). This allows consumers and automation to triage rather than blanket-alert. +- **Manage centrally** — an SBOM management platform (Dependency-Track, Anchore Enterprise) automates ingestion, monitoring, and alerting rather than leaving this as a manual spreadsheet process. + +## SBOM vs SLSA + +An SBOM describes **what** is in your software; [SLSA provenance](2-3-6-2-Artifact-Signing-and-Provenance.md) attests to **how** it was built. They are complementary: + +| | SBOM | SLSA Provenance | +|---|---|---| +| Answers | What components are in this artifact? | Who built this, how, and from where? | +| Format | SPDX, CycloneDX | SLSA provenance predicate (in-toto) | +| Primary use | Vulnerability management, license compliance | Build integrity, tampering detection | +| Starting point | Easier — generate from build or lock files | Harder — requires hosted build attestation | + +Most mature programs need both, but SBOMs are usually the higher-immediate-value starting point. + +## Common pitfalls and anti-patterns + +- **Generating SBOMs but never consuming them** — a shelf full of SBOM files that nobody queries during an incident is compliance theater. Build the query capability before the crisis. +- **Flat-list SBOMs (no relationships)** — an SBOM without dependency relationships cannot distinguish a direct dependency from a transitive one; priority cannot be set correctly. +- **SBOM format mismatch between producer and consumer** — agree on CycloneDX or SPDX across your toolchain. Mixed formats require conversion and introduce data loss risk. +- **No VEX process** — publishing SBOMs without VEX means every disclosed CVE triggers alerts for all consumers, even when the vulnerable function is not reachable. This creates noise that erodes trust in the SBOM program. +- **SBOM as a point-in-time PDF** — SBOMs that live as PDF reports in a shared drive are not machine-readable, not continuously monitored, and not useful during incident response. + +## Maturity progression + +**Starter** — Generate CycloneDX SBOMs from lock files using cdxgen or Trivy. Publish alongside release artifacts. Ingest into Dependency-Track for continuous monitoring. + +**Intermediate** — Generate SBOMs at build time (exact resolved dependency graph). Attach as signed attestations in the container registry. Produce SBOMs at multiple layers (source + image). Enable automatic CVE alerting via Dependency-Track. + +**Advanced** — Publish VEX documents for confirmed non-exploitable CVEs. Integrate SBOM queries into incident response runbooks. Track SBOM coverage (% of artifacts with SBOMs) as a KPI. Provide SBOMs to customers and partners on request as part of a documented disclosure process. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| % of release artifacts with attached SBOM | 100% | +| % of SBOMs in a machine-readable standard format | 100% | +| Mean time to identify affected artifacts after CVE disclosure | < 1 hour (with automated SBOM monitoring) | +| % of CVEs with VEX status (exploitable/not-exploitable declared) | > 80% for high/critical | +| SBOM freshness (age at release) | < 24 hours | + +--- + +## Tools[^1] + +### Open-source + +- [cdxgen](https://github.com/CycloneDX/cdxgen) - Generates CycloneDX SBOMs for many ecosystems (Node, Python, Java, Go, Ruby, Rust, etc.); best multi-language SBOM generator. +- [GUAC](https://github.com/guacsec/guac) - Aggregates SBOM, provenance, and scorecard data into a queryable graph; enables advanced supply-chain queries across your entire estate. +- [OWASP Dependency-Track](https://dependencytrack.org/) - Best-in-class continuous SBOM monitoring platform; ingests SBOMs, tracks components, and alerts on new CVEs automatically. +- [Syft](https://github.com/anchore/syft) - Generates SBOMs from container images, filesystems, and directories; natural pair with Grype for SBOM-first SCA. +- [Trivy](https://github.com/aquasecurity/trivy) - Produces and scans SBOMs in SPDX and CycloneDX formats; good for teams wanting a single tool across scanning and SBOM generation. + +### Commercial + +- [Anchore Enterprise](https://anchore.com/) - SBOM management and supply-chain security at scale; strong policy enforcement and compliance reporting on top of SBOMs. +- [FOSSA](https://fossa.com/) - SBOM generation, license compliance, and vulnerability management; particularly strong on license risk analysis for SBOMs. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md b/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md new file mode 100644 index 0000000..d0f70de --- /dev/null +++ b/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md @@ -0,0 +1,131 @@ +# Artifact Signing and Provenance + +An [SBOM](2-3-6-1-SBOM.md) tells you *what* is in an artifact; **signing and provenance** prove *who built it and how*, and that it has not been tampered with since. After incidents like SolarWinds — where attackers compromised the build system to inject malicious code into legitimately signed releases — verifiable build integrity has become a core supply-chain control. + +## The two guarantees + +- **Signing** — a cryptographic signature binds an artifact to its producer, so consumers can verify authenticity and integrity (the artifact is exactly what the publisher released, and has not been modified in transit or at rest). +- **Provenance** — tamper-evident metadata describing *how* the artifact was built: the source commit, the builder identity, the build steps, the input parameters, and the environment. Provenance establishes a verifiable "chain of custody" from source to binary. Without provenance, you know *what* is signed but not *that the build process was not compromised*. + +## SLSA: levels of build integrity + +[SLSA](https://slsa.dev/) (Supply-chain Levels for Software Artifacts) defines graded requirements for build integrity that give concrete meaning to claims about provenance: + +| Level | Requirements | Threat addressed | +|---|---|---| +| Level 1 | Provenance exists and is available | Accidental mistakes; basic auditability | +| Level 2 | Provenance is signed and generated by a hosted build service | Forgeable provenance; tampering after the build | +| Level 3 | Build platform is hardened; provenance is non-forgeable; builds are hermetic | Compromised build infrastructure; parameter injection | + +Start at Level 1 (provenance document exists) and progress toward Level 2 (signed by hosted CI) as the default target. Level 3 is appropriate for critical infrastructure and software serving high-assurance consumers. + +## Sigstore: making signing practical + +Historically, signing meant managing long-lived GPG keys — painful, error-prone, and a risk in themselves (a leaked signing key compromises all past and future releases). [Sigstore](https://www.sigstore.dev/) changed this with **keyless signing**: + +- **cosign** — signs container images and arbitrary artifacts (binaries, SBOMs, attestations). +- **Keyless / OIDC signing** — uses short-lived certificates tied to a workload identity (a CI job's OIDC token from GitHub Actions, GitLab CI, etc.), so there are no long-lived keys to store, rotate, or leak. +- **Rekor** — records signatures in a tamper-evident, append-only transparency log; any signature can be independently verified without contacting the signer. +- **in-toto attestations** — carry SBOMs, provenance, vulnerability scan results, and test outcomes as signed statements (predicates) about an artifact. + +### Signing a container image with keyless cosign in GitHub Actions + +```yaml +- name: Sign image with Sigstore + uses: sigstore/cosign-installer@v3 + +- name: Sign the container image + run: | + cosign sign --yes \ + --oidc-issuer https://token.actions.githubusercontent.com \ + myregistry/myimage@${{ steps.build.outputs.digest }} + env: + COSIGN_EXPERIMENTAL: "true" +``` + +The OIDC token identifies the signing workflow; Rekor records the certificate and signature. No key management required. + +### Generating SLSA provenance with the GitHub SLSA generator + +```yaml +- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2 + with: + image: myregistry/myimage + digest: ${{ steps.build.outputs.digest }} + registry-username: ${{ secrets.REGISTRY_USER }} + registry-password: ${{ secrets.REGISTRY_PASS }} +``` + +This produces a signed SLSA Level 3 provenance attestation attached to the image. + +## Verify before you trust + +Producing signatures and provenance only helps if you **verify** them downstream. Verification should be non-optional: + +- **At release** — verify signatures and provenance before promoting an artifact from CI to the production registry. An unverifiable artifact is rejected. +- **At admission/deploy** — only signed, policy-compliant artifacts with acceptable provenance run in the cluster. Use an admission controller to enforce this automatically. + +```bash +# Verify a container image's signature and provenance +cosign verify \ + --certificate-identity-regexp "https://github.com/myorg/myrepo/.github/workflows/release.yml" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ + myregistry/myimage:v1.2.3 + +# Verify SLSA provenance attestation +cosign verify-attestation \ + --type slsaprovenance \ + --certificate-identity-regexp "github.com/slsa-framework" \ + myregistry/myimage:v1.2.3 | jq .payload | base64 -d | jq . +``` + +- **Use policy engines** to require a minimum SLSA level for production workloads. Kyverno and the Sigstore policy-controller can enforce this at the Kubernetes admission layer. + +## Common pitfalls and anti-patterns + +- **Signing but never verifying** — many teams add signing as a CI step but never enforce verification at deploy. Signing without verification is security theater. +- **Long-lived signing keys** — a key stored in a CI secret or a vault that is valid for years is a single point of failure. Prefer keyless signing with OIDC workload identities. +- **Signing the wrong artifact reference** — sign by digest (`sha256:...`), not by tag. Tags are mutable; a signed tag can point to a different image tomorrow. +- **Provenance that covers only the final build step** — if the build process pulls unverified inputs (scripts, base images without provenance), the provenance is incomplete. Hermetic builds with declared inputs are required for SLSA Level 3. +- **No policy enforcement at admission** — without an admission controller checking signatures and provenance, a manually pushed or tampered image can bypass all signing requirements. + +## Maturity progression + +**Starter** — Sign all release container images and binaries using cosign with keyless OIDC signing in CI. Store in Rekor. Verify manually during release promotion. + +**Intermediate** — Produce SLSA Level 2 provenance using the SLSA GitHub generator or equivalent. Attach SBOMs as in-toto attestations. Automate signature verification in the release pipeline gate. Deploy Kyverno or Sigstore policy-controller to require verified signatures for production workloads. + +**Advanced** — Achieve SLSA Level 3 with hermetic, parameterless builds on hardened hosted runners. Verify provenance build parameters (source repo, commit, workflow) in admission policy — not just that a signature exists. Track SLSA level and signing coverage as KPIs. Provide provenance documents to customers on request. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| % of release artifacts with valid signatures | 100% | +| % of release artifacts with SLSA provenance | 100% | +| SLSA level achieved for production artifacts | Level 2 minimum; Level 3 for critical systems | +| Unsigned deployments blocked by admission control | Track count; target: 0 bypass | +| Time to detect a tampered artifact | < 1 hour (via Rekor / admission control) | + +--- + +## Tools[^1] + +### Open-source + +- [cosign (Sigstore)](https://github.com/sigstore/cosign) - The standard for container and artifact signing, including keyless OIDC signing and attestation management. The default choice for Kubernetes-native signing. +- [in-toto](https://in-toto.io/) - Framework for cryptographically verifiable supply-chain attestations linking every step from source to artifact; the attestation format used by SLSA. +- [Kyverno](https://kyverno.io/) - Kubernetes policy engine that verifies image signatures and attestations at admission; declarative YAML-based policies. +- [SLSA GitHub Generator](https://github.com/slsa-framework/slsa-github-generator) - Generates SLSA Level 3 provenance for GitHub Actions builds using a trusted, isolated signing workflow. +- [Sigstore policy-controller](https://github.com/sigstore/policy-controller) - Admission controller that enforces signature and attestation policies across a Kubernetes cluster. + +### Commercial + +- [Chainguard](https://www.chainguard.dev/) - Produces minimal container images that are signed and come with SLSA-backed provenance by default; eliminates the signing setup burden for base images. +- [GitHub Artifact Attestations](https://docs.github.com/actions/security-guides/using-artifact-attestations) - Built-in build provenance and signing for GitHub Actions; generates SLSA provenance attestations natively without additional workflow configuration. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md b/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md new file mode 100644 index 0000000..1e06506 --- /dev/null +++ b/current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md @@ -0,0 +1,150 @@ +# CI/CD Pipeline Security + +The pipeline that builds and ships your software is itself a high-value target. It holds powerful credentials, executes code from many sources, and has direct access to production. Attackers increasingly go after the pipeline rather than the application — a single poisoned build can compromise every downstream consumer. Securing the pipeline is therefore as important as securing the code it builds. + +## The threat model: OWASP Top 10 CI/CD Security Risks + +The [OWASP Top 10 CI/CD Security Risks](https://owasp.org/www-project-top-10-ci-cd-security-risks/) is the canonical reference. Key risks include: + +- **Insufficient flow control mechanisms (CICD-SEC-1)** — the ability to push code or artifacts to production without adequate review or gates. Anyone who can merge to main can deploy to production. +- **Poisoned Pipeline Execution / PPE (CICD-SEC-3)** — injecting malicious commands into the build by manipulating pipeline configuration or scripts. Example: a PR modifies a GitHub Actions workflow file to exfiltrate secrets to an external URL. Defense: require reviews for workflow file changes; use `pull_request_target` carefully. +- **Dependency-chain abuse (CICD-SEC-6)** — dependency confusion, typosquatting, and malicious packages pulled during the build. The pipeline's package manager runs with the same trust as CI secrets. +- **Insufficient credential hygiene (CICD-SEC-4)** — long-lived, over-privileged secrets exposed to pipeline steps; secrets printed to logs; secrets shared across environments. +- **Ungoverned usage of third-party services (CICD-SEC-8)** — unvetted GitHub Actions, Jenkins plugins, and integrations running with access to the pipeline and its credentials. +- **Insufficient PBAC / pipeline-based access controls (CICD-SEC-2)** — runners and jobs with far more access than they need; secrets available to all jobs in a repository. + +## Hardening the pipeline + +### Least-privilege tokens + +Scope permissions explicitly and narrowly. Every permission not granted is a capability an attacker cannot abuse: + +```yaml +# GitHub Actions: explicit minimal permissions +permissions: + contents: read # read source code only + packages: write # push to GitHub Packages + id-token: write # request OIDC token for keyless signing + # All other permissions are denied by default +``` + +### OIDC workload identity — replace long-lived secrets + +Exchange short-lived OIDC tokens for cloud credentials instead of storing long-lived cloud access keys as CI secrets: + +```yaml +- name: Configure AWS credentials via OIDC + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::123456789:role/ci-deploy + aws-region: us-east-1 + # No AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY needed +``` + +The OIDC token is valid for minutes and cannot be reused; a leaked token expires before it can be weaponized. + +### Pin third-party Actions to immutable commit SHAs + +Tags like `@v3` are mutable — they can be silently redirected to malicious code. Pin to the commit digest: + +```yaml +# Mutable tag — do not use this in production +- uses: actions/checkout@v4 + +# Immutable SHA pin — use this +- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 +``` + +Use tools like Dependabot or Renovate to automate SHA pin updates as new versions are released. + +### Harden runners + +- **Ephemeral, isolated runners** — use ephemeral GitHub-hosted or self-hosted runners that start clean and are destroyed after each job. Persistent runners accumulate state that attackers can abuse. +- **Network egress control** — restrict what external hosts runners can reach during a build. A build that only needs npm and GitHub should not be able to reach arbitrary cloud APIs. Use StepSecurity Harden-Runner for GitHub Actions: + + ```yaml + - uses: step-security/harden-runner@v2 + with: + egress-policy: block + allowed-endpoints: > + registry.npmjs.org:443 + api.github.com:443 + ``` + +- **Secrets scoping** — in GitHub, environment secrets are only available to workflow jobs that target that environment; use environment protection rules to gate access. + +### Protect fork/PR workflows + +Pull requests from forks are a common PPE vector. Apply these controls: + +- Require approval before running CI on first-time contributor PRs (`pull_request` trigger does not have access to secrets; `pull_request_target` does and must be used carefully). +- Never expose secrets to untrusted PRs. +- Protect workflow files with CODEOWNERS so any change to `.github/workflows/` requires security team review. + +### Pipeline configuration as a security perimeter + +The pipeline definition (`.github/workflows/`, `Jenkinsfile`, `.gitlab-ci.yml`) is executable code. Treat it accordingly: + +- Require pull request reviews for workflow file changes. +- Use `CODEOWNERS` to route changes to security-aware reviewers. +- Scan workflow files with zizmor or semgrep-rules for CI to catch common vulnerabilities (script injection, unsafe `pull_request_target` usage). + +## Measure and enforce continuously + +Use automated tooling to keep the pipeline hardened over time — egress monitoring on runners, workflow static analysis, and repository security scoring — and feed the results into your governance program. A hardened pipeline today can drift back to a vulnerable state without continuous enforcement. + +OpenSSF Scorecard provides a free, automated security score for open-source repositories that covers many pipeline hygiene dimensions (branch protection, dependency pinning, SAST, signing): + +```bash +scorecard --repo=github.com/myorg/myrepo --format json | jq .checks +``` + +## Common pitfalls and anti-patterns + +- **Secrets stored as plain-text environment variables in pipeline config** — anyone who can read the pipeline file can read the secret. Use the platform's secret store, not inline values. +- **One long-lived AWS/GCP key for all CI jobs** — a single leaked key compromises every environment. Move to OIDC with per-environment roles. +- **`pull_request_target` with unchecked-out code from the fork** — this gives fork PRs access to secrets. This is the most common PPE vulnerability in GitHub Actions. +- **Third-party Actions from unverified authors** — an Action with write access to the workspace and access to secrets can exfiltrate credentials. Audit every third-party Action used. +- **No egress control on runners** — a compromised runner with unrestricted internet access can quietly exfiltrate secrets or establish C2 connections. +- **Security scans disabled "temporarily" in CI** — "temporary" disables become permanent. Protect security step configurations in CODEOWNERS just as you protect workflow files. + +## Maturity progression + +**Starter** — Enable branch protection on main (require PR reviews, status checks). Move cloud credentials to OIDC workload identity. Set explicit `permissions:` blocks on all workflow jobs. Audit the list of third-party Actions in use. + +**Intermediate** — Pin all third-party Actions to SHA digests (use Dependabot to manage). Add CODEOWNERS for `.github/workflows/`. Deploy StepSecurity Harden-Runner with egress monitoring. Add zizmor or Semgrep CI rules to scan workflow files. Score repositories with OpenSSF Scorecard and set minimum score targets. + +**Advanced** — Enforce egress allowlists (block mode) on all runners. Use ephemeral, isolated self-hosted runners for sensitive builds. Sign all pipeline outputs (see [Artifact Signing and Provenance](2-3-6-2-Artifact-Signing-and-Provenance.md)). Automate Allstar policy enforcement across the GitHub organization. Report pipeline security score trends to engineering leadership quarterly. + +## Metrics and KPIs + +| Metric | Target | +|---|---| +| % of repositories with branch protection on main | 100% | +| % of CI jobs using OIDC (no long-lived cloud keys) | 100% | +| % of third-party Actions pinned to SHA digest | 100% | +| OpenSSF Scorecard average across organization | > 7.0 / 10 | +| Repositories with unreviewed workflow file changes | 0 | +| Egress violations detected on runners | Tracked; alerts on anomalies | + +--- + +## Tools[^1] + +### Open-source + +- [Allstar](https://github.com/ossf/allstar) - Enforces security policies across GitHub organizations (branch protection, binary artifacts, SECURITY.md, outside collaborators); alerts or opens issues on violations. +- [OpenSSF Scorecard](https://github.com/ossf/scorecard) - Scores repositories on supply-chain security best practices across 20+ checks; integrates as a GitHub Actions workflow with badge support. +- [StepSecurity Harden-Runner](https://github.com/step-security/harden-runner) - Egress filtering and runtime security for GitHub Actions runners; monitors and optionally blocks unauthorized outbound connections. +- [zizmor](https://github.com/woodruffw/zizmor) - Static analysis tool for GitHub Actions workflow security vulnerabilities (script injection, PPE patterns, dangerous triggers). + +### Commercial + +- [Cycode](https://cycode.com/) - Application security and pipeline/supply-chain protection; detects misconfigured pipelines and enforces policy across GitHub, GitLab, and Bitbucket. +- [Legit Security](https://www.legitsecurity.com/) - Security posture management for the software factory; maps every pipeline, detects risky configurations, and tracks pipeline security posture over time. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md b/current-version/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md index e9332f6..9a82622 100644 --- a/current-version/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md +++ b/current-version/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md @@ -1,42 +1,143 @@ -# Interactive Application Security Testing +# Interactive Application Security Testing (IAST) -**IAST (interactive application security testing)** is an application security testing method that tests an application, API, or function while it is being exercised by automated tests, human testers, or any other "interaction" with the code's functionality. This makes it highly compatible with just about any software development lifecycle, especially DevOps. +Interactive Application Security Testing combines the strengths of static and dynamic analysis by **instrumenting the running application** — typically with an agent inside the runtime — and observing it from the inside while it executes. As functional tests, QA, or normal usage exercise the application, the IAST agent watches data flow through the code and reports vulnerabilities with the precise line of code *and* runtime context. -IAST does not scan applications, but installs onto application and API servers and continuously analyzes applications forever. IAST works by instrumenting code with sensors that can directly observe security relevant application behavior. IAST uses the same proven technqiues as APM tools and profilers, just highly optimized for security and speed. +## How IAST differs from SAST and DAST -IAST requires zero changes to the way teams build, test, and deploy code. IAST performs security testing in real time during normal development and testing, and identifies vulnerabilities without requiring them to be exploited. This means with IAST, anyone can perform high quality security tests, even without a security background. +| Dimension | SAST | DAST | IAST | +|---|---|---|---| +| When it runs | At rest (code/build) | Against running app (black-box) | Inside running app (white-box at runtime) | +| What it sees | Full code, no runtime context | External behavior only | Code paths actually exercised | +| False positive rate | Higher (no runtime proof) | Medium | Very low (confirms real execution) | +| Fix guidance | File + line | HTTP request/response | File + line + full data-flow trace | +| CI integration effort | Low | Medium | Medium (requires test harness) | +| Source code required | Yes | No | No (agent instruments bytecode/binary) | -IAST can be deployed to development servers, CI/CD pipelines, or quality assurances servers, or even while in production. Wherever the code runs, that's where IAST is installed, including servers, containers, virtual machines, cloud, and other environments. IAST is uniquely well suited for API security testing, as it overcomes the challenges SAST and DAST have with complex API code and data. +The combination of inside-view (like SAST) and runtime-view (like DAST) is what makes IAST highly accurate: it only reports a vulnerability when it observes tainted data actually flowing to a dangerous sink in a live execution. -IAST sensors have access to: +## How it works -- Entire code -- Full HTTP request and response -- Data flow and control -- Configuration data -- Libraries and frameworks and how they are used -- Back-end connection data +An IAST agent is loaded into the application runtime — as a Java agent (`-javaagent`), a .NET profiler, a Node.js hook, or a Python middleware. From there it: -This rich context makes IAST extremely accurate compared with traditional appsec testing tools and it enables IAST to deliver very detailed findings that enable developers to understand issues and fix them correctly. It also enables IAST to cover a very broad range of appsec vulnerabilities, including: +1. **Instruments** method calls, framework hooks, and I/O operations at runtime. +2. **Tracks taint propagation** — marks data coming from user-controlled sources (HTTP params, headers, cookies) and follows it through the call stack. +3. **Alerts on sink contact** — triggers a finding when tainted data reaches a dangerous operation (SQL query, shell execution, file write, deserialization). +4. **Attaches context** — records the exact stack trace, the HTTP request that triggered it, and the source-to-sink path. -- Code issues like hardcoded secrets and weak encryption algorithms -- Data flow issues like injection and SSRF -- HTTP issues like clickjacking, parameter pollution, and missing headers -- Backend connection issues like SSRF -- Configuration issues like verb tampering and weak authentication -- and more... +Because the agent is passive, it piggybacks on whatever tests are already running — functional tests, integration tests, manual QA — without needing a dedicated attack tool. -One challenge with IAST is that only code that is exercised is tested. However, it's easy to use simple end-to-end "smoke" tests, or even a simple crawler, to generate this coverage. IAST does not require extensive functional testing, just basic end-to-end execution of routes. Some IAST tools extract the set of routes from an application and simplify the process of getting to 100% route coverage. +## Agent-based vs proxy-based IAST ---- +Some vendors offer a proxy-based variant that sits between the test client and the application (similar to a DAST proxy) while also receiving a lightweight signal from a server-side component. The distinction matters for deployment: + +| Approach | How it instruments | Best for | +|---|---|---| +| Agent-based (in-process) | JVM agent, .NET profiler, language hook | Precise taint tracking, low FP, full stack traces; requires supported runtime | +| Proxy-based (network layer) | Intercepts requests/responses; optional server hook | Language-agnostic; less deep taint analysis; easier to deploy in polyglot environments | + +Most enterprise IAST tools use the agent-based approach for precision. If your runtime is not supported by an agent, evaluate proxy-based tools or rely on DAST + SAST instead. + +## Deploying a Java IAST agent (walkthrough) + +Most IAST agents for JVM languages are attached via the standard `-javaagent` JVM flag. Example with Contrast Assess: + +```bash +# 1. Download the agent JAR (or include via Maven/Gradle) +curl -L -o contrast.jar https://your-contrast-instance/Contrast/api/ng/contrast.jar + +# 2. Set required environment variables +export CONTRAST__API__URL=https://your-contrast-instance/Contrast +export CONTRAST__API__API_KEY= +export CONTRAST__API__SERVICE_KEY= +export CONTRAST__API__USER_NAME= +export CONTRAST__APPLICATION__NAME=my-app + +# 3. Launch the application with the agent attached +java -javaagent:/path/to/contrast.jar \ + -Dcontrast.application.name=my-app \ + -jar myapp.jar + +# 4. Run your existing test suite against the instrumented app +mvn verify -Dtest.base.url=http://localhost:8080 +``` + +The agent instruments the JVM bytecode at load time — no source changes required. Findings are reported in real time to the Contrast platform as tests exercise the application. + +For CI pipelines, add the `-javaagent` flag to the application startup in your test environment's Dockerfile or Helm values, keeping the agent active for the duration of integration tests. + +## Language and framework support + +IAST coverage varies by vendor and runtime. Evaluate agents against your stack before committing: + +| Runtime | General support level | Notes | +|---|---|---| +| Java / Kotlin (JVM) | Excellent | Most mature; deep framework support (Spring, Struts, Jakarta EE) | +| .NET / .NET Core | Excellent | Good vendor support; profiler API enables deep instrumentation | +| Node.js | Good | Hook-based; coverage varies by framework (Express, Fastify) | +| Python | Moderate | Middleware-based; less deep taint tracking than JVM | +| Go | Limited | No JVM/profiler API; typically proxy-based only | +| Ruby | Limited | Available from some vendors; less mature | + +If your primary stack is Go or Ruby, IAST may not deliver the same depth as on JVM/.NET — supplement with strong SAST and DAST coverage. + +## Licensing and cost considerations -## IAST vs SAST +Most IAST agents are priced per instrumented application instance (per agent process). Costs to model: -**Static Application Security Testing** method examines source code in a non-runtime environment early in the SDLC. It looks for suspicious code patterns that indicate security risks. Even though they are easy to deploy, SASTs report large numbers of false positives because SASTs do not take into account the presence of other security countermeasures, and they lack visibility during runtime. SAST tools normally run during the build process, and can introduce delays as the scan process takes time to finish. IASTs are more flexible than SASTs, because they are applicable in production runtime environments (SASTs require direct access to the source code). +- **Per-instance licensing** — if you run IAST in a multi-replica Kubernetes deployment, each pod with the agent counts. For large-scale testing, this adds up. +- **Developer-tier / community editions** — some vendors offer free single-application tiers (e.g., Contrast Community Edition) to evaluate before scaling. +- **Test-only deployment** — containing IAST to test/staging environments (not production) limits licensing cost while still covering meaningful attack surface. -## IAST vs DAST +Before selecting a vendor, clarify: per-agent vs per-application pricing, whether replicas count separately, and whether findings from ephemeral environments (PR preview deployments) are included. -**Dynamic Application Security Testing** method works like a black-box scanner that sends malicious HTTP requests to an application and evaluate the HTTP responses to determine whether a security vulnerability was found. DASTs look at the applications from the exterior and determine the presence of risks by looking at the response (including body and headers) of the server to a battery of tests, but DASTs have no visibility of the internal workings of the app. Furthermore, DAST tests are hard to automate, because DASTs must be operated by experienced appsec teams, such as penetration testers, to be truly useful. Forrester estimates that the duration of a DAST scan can take around 5 to 7 days, while testing with IAST is a real-time (zero minutes) operation. +## How IAST findings feed vulnerability management + +IAST findings should flow into the same vulnerability management pipeline as SAST and DAST: + +1. IAST agent reports findings to the vendor platform (or a self-hosted aggregator). +2. Findings are exported via API to [DefectDojo](https://defectdojo.github.io/django-DefectDojo/) or your ASPM platform for deduplication and correlation with SAST/DAST results. +3. New high/critical IAST findings trigger pipeline gates or create tickets in Jira automatically. +4. Developers see a finding with: vulnerable line, HTTP request that triggered it, full taint flow — reducing triage time dramatically. + +```bash +# Example: Export IAST findings from Contrast via API +curl -H "API-Key: $CONTRAST_API_KEY" \ + -H "Authorization: $CONTRAST_AUTH" \ + "https://your-contrast/Contrast/api/ng/$ORG_ID/traces/$APP_ID/filter?status=Reported&severity=HIGH,CRITICAL" \ + | jq '.traces[] | {title:.ruleName, severity:.severity, file:.events[-1].stackFrames[0].file}' +``` + +## Where it fits + +Run IAST in QA/test environments alongside automated functional and integration tests, and feed its findings into [Security Gates](../2-3-Build/2-3-5-Security-Gates.md) and the central [vulnerability dashboard](../../3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md). Pair it with [DAST](2-4-2-Dynamic-Application-Security-Testing.md) for broader runtime coverage. + +A practical pipeline integration: +``` +build → deploy to test env (IAST agent active) → run functional/integration tests → IAST findings exported → gate check → promote or block +``` + +## Common pitfalls and anti-patterns + +- **Running IAST against a low-coverage test suite** — results will be sparse and give false confidence. Invest in test coverage first, or add an automated crawler/DAST alongside. +- **Treating IAST as a replacement for SAST** — IAST only covers executed paths; SAST covers the whole codebase. Use both. +- **Ignoring agent version drift** — an outdated agent may miss newly discovered vulnerability classes. Pin agent versions and update on a schedule. +- **Not integrating with the issue tracker** — findings that don't create tickets get lost. Automate the export from IAST to your vulnerability management tool. +- **Running IAST in production** — the performance overhead and potential for finding-triggered alerts in live user sessions make this inadvisable. Confine to test and staging. + +## Maturity progression + +**Starter** — Deploy one IAST agent on your most critical application in a test environment. Run it during existing integration test runs and review findings manually weekly. + +**Intermediate** — Instrument all tier-1 applications. Automate finding export to DefectDojo or Jira. Add a pipeline gate that blocks promotion if new high/critical IAST findings appear. + +**Advanced** — Extend to all applications. Correlate IAST findings with SAST and DAST results in an ASPM platform to deduplicate and prioritize. Track IAST coverage as a metric (code paths exercised vs total). Use IAST findings to identify gaps in test suites. + +## Metrics and KPIs + +- **IAST-verified high/critical findings per release** — should trend downward over time. +- **Mean time to remediate IAST findings** — compare against SAST to assess value of runtime confirmation. +- **Code-path coverage during IAST run** — low coverage indicates test-suite gaps, not application health. +- **False-positive rate** — IAST should be near zero; any FPs indicate misconfiguration of source/sink rules. --- @@ -44,24 +145,17 @@ One challenge with IAST is that only code that is exercised is tested. However, ### Open-source +- [Contrast Community Edition](https://www.contrastsecurity.com/contrast-community-edition) — Free IAST/runtime protection for a single Java or .NET application; good starting point for evaluating agent-based approaches without licensing cost. + ### Commercial -- [Checkmarx Interactive Application Security Testing(CxIAST)](https://www.checkmarx.com/products/interactive-application-security-testing/) -- [Contrast Assess](https://www.contrastsecurity.com/contrast-assess) and [Contrast Community Edition](https://www.contrastsecurity.com/contrast-community-edition) -- [HCL AppScan on Cloud](https://cloud.appscan.com) -- [Seeker Interactive Application Security Testing](https://www.synopsys.com/software-integrity/security-testing/interactive-application-security-testing.html) +- [Checkmarx](https://checkmarx.com/) — Application security platform with interactive testing capabilities; strong if you already use Checkmarx SAST for unified reporting and a single-vendor AppSec suite. +- [Contrast Assess](https://www.contrastsecurity.com/) — Instrumentation-based IAST for multiple runtimes; the most mature agent ecosystem with broad language support and runtime protection (RASP) available on the same agent. +- [HCL AppScan](https://www.hcl-software.com/appscan) — Application security suite including interactive testing; well-suited for enterprises with existing HCL tooling and compliance reporting needs. +- [Seeker (Synopsys)](https://www.synopsys.com/software-integrity/security-testing/interactive-application-security-testing.html) — Strong Java/.NET support with compliance reporting for regulated industries; integrates with Synopsys Black Duck for combined SCA+IAST coverage. --- ### Links -- [Acunetix - IAST](https://www.acunetix.com/blog/web-security-zone/what-is-iast-interactive-application-security-testing/) -- [Contrast Security - What is Interactive Application Security Testing?](https://www.contrastsecurity.com/knowledge-hub/glossary/interactive-application-security-testing) -- [Contrast Security - Why the difference sast, dast, and iast mastters](https://www.contrastsecurity.com/security-influencers/why-the-difference-between-sast-dast-and-iast-matters) -- [Esecurityplanet - Application security vendors](https://www.esecurityplanet.com/products/application-security-vendors/) -- [Hdivsecurity - IAST](https://hdivsecurity.com/bornsecure/what-is-iast-interactive-application-security-testing/) -- [OWASP - Free IAST Tools](https://owasp.org/www-community/Free_for_Open_Source_Application_Security_Tools#:~:text=open%20source%20projects.-,IAST%20Tools,-IAST%20tools%20are) -- [Synk - IAST](https://snyk.io/learn/iast-interactive-application-security-testing/) -- [Veracode - IAST](https://www.veracode.com/security/interactive-application-security-testing-iast) - [^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md b/current-version/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md index 1a7df3d..4d8ebb6 100644 --- a/current-version/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md +++ b/current-version/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md @@ -1,16 +1,209 @@ # Dynamic Application Security Testing (DAST) -DAST is a “Black-Box” testing technique that can find security vulnerabilities and weaknesses in a running application by injecting malicious payloads to identify potential flaws that allow for attacks like SQL injections or cross-site scripting (XSS), etc. DAST tools are especially helpful for detecting: +Dynamic Application Security Testing examines a **running application from the outside** — a black-box technique that sends crafted requests and observes responses, exactly as an attacker would. Because it tests the deployed, integrated application, DAST finds vulnerabilities that only appear at runtime: configuration issues, authentication and session flaws, and problems arising from how components interact. -- Input or output validation -- Authentication issues -- Server configuration mistakes +## What DAST finds -DAST tools allow for extensive scans from the client side and server side without needing the source code or the framework the application is built on. While configuration requires expertise, scans usually require minimal user interaction once configured and can be run as part of a nightly scan. As more important DAST tools we can look at the following: +- Injection flaws (SQL, command, XSS) observable in responses +- Authentication, session management, and access-control weaknesses +- Security misconfigurations and missing security headers (CSP, HSTS, X-Frame-Options, Permissions-Policy) +- Exposed sensitive data and verbose error handling that leaks stack traces or internal paths +- Server-side issues: SSRF, open redirects, path traversal, insecure deserialization indicators +- Business-logic flaws in multi-step workflows when scans are guided by test scripts -- Dynamic security scanner -- Fuzzers -- Attack Proxies +## Strengths and limitations + +**Strengths:** language-agnostic (it tests behavior, not code), finds runtime and configuration issues, low false positives for confirmed findings, and reflects the real attacker's view. No source-code access required — works against third-party and compiled applications. + +**Limitations:** runs late in the cycle (needs a deployed application), cannot pinpoint the exact vulnerable line of source code, may miss flaws in code paths not reached by the scan, and authenticated/stateful flows require explicit configuration. Scan speed vs. coverage is a constant trade-off. + +## Running DAST well + +- **Authenticated scans** — configure credentials, session cookies, or OAuth tokens so the scanner reaches protected functionality. A scan that never authenticates only tests the public surface — which may be 10% of the actual attack surface. +- **API-aware testing** — feed the scanner an OpenAPI 3.x, Swagger, or GraphQL introspection schema so it understands modern API surfaces automatically rather than relying on crawling. See [API Security](2-4-4-API-Security.md). +- **Automate in CI/CD** — run against ephemeral test/staging environments on each release candidate. Baseline findings (suppress known accepted issues) to surface only *new* issues per build. +- **Tune scope and rate** — restrict scope to application paths under test; avoid destructive tests (SQLi that drops tables) against shared environments; respect rate limits so you do not DoS your own staging. +- **Use active + passive modes** — passive mode (spider + observe) is safe in shared environments; active mode (attack payloads) should be isolated. Run both in a full pipeline. + +## CI/CD integration: OWASP ZAP in GitHub Actions + +### Baseline scan (passive — safe for shared envs) + +```yaml +# .github/workflows/dast.yml +name: DAST +on: + push: + branches: [main] + pull_request: + +jobs: + zap-baseline: + runs-on: ubuntu-latest + steps: + - name: Deploy to ephemeral test environment + run: | + # spin up the app (docker-compose, Helm, etc.) + docker compose -f docker-compose.test.yml up -d + sleep 10 # wait for health + + - name: OWASP ZAP Baseline Scan + uses: zaproxy/action-baseline@v0.10.0 + with: + target: 'http://localhost:8080' + rules_file_name: '.zap/rules.tsv' # suppress accepted findings + fail_action: true + issue_title: 'DAST Baseline Findings' + + - name: Tear down test environment + if: always() + run: docker compose -f docker-compose.test.yml down +``` + +### Full active scan (release gate) + +```yaml + - name: OWASP ZAP Full Scan (release gate) + uses: zaproxy/action-full-scan@v0.10.0 + with: + target: 'http://localhost:8080' + rules_file_name: '.zap/rules.tsv' + cmd_options: '-a -j' # -a: all active rules, -j: report as JSON + fail_action: true +``` + +### API scan with OpenAPI spec + +```yaml + - name: OWASP ZAP API Scan + uses: zaproxy/action-api-scan@v0.6.0 + with: + target: 'http://localhost:8080/openapi.json' + format: openapi + fail_action: true +``` + +## Handling authenticated flows + +For applications behind login, pass credentials or session context to the scanner: + +### Token-based auth (JWT / API key) + +```yaml +# ZAP replacer rule via environment config +- name: ZAP Authenticated Scan (token) + uses: zaproxy/action-full-scan@v0.10.0 + with: + target: 'http://localhost:8080' + cmd_options: > + -config replacer.full_list(0).description=auth + -config replacer.full_list(0).enabled=true + -config replacer.full_list(0).matchtype=REQ_HEADER + -config replacer.full_list(0).matchstr=Authorization + -config replacer.full_list(0).replacement="Bearer ${{ secrets.TEST_JWT }}" +``` + +### Form-based auth (session cookies) + +Use a ZAP authentication script (stored in `.zap/scripts/auth.js`): + +```javascript +// ZAP form-based auth script +function authenticate(helper, paramsValues, credentials) { + var loginUrl = paramsValues.get("Login URL"); + var postData = "username=" + credentials.getParam("Username") + + "&password=" + credentials.getParam("Password"); + var msg = helper.prepareMessage(); + msg.setRequestHeader(msg.getRequestHeader().getMethod() + " " + loginUrl + " HTTP/1.1\r\n"); + msg.setRequestBody(postData); + helper.sendAndReceive(msg); + return msg; +} +``` + +### Multi-step flows via HAR replay + +Record a browser session as a HAR file and replay it as the scan seed: + +```bash +# Replay HAR to seed ZAP's context with a known authenticated session +zap-cli --zap-url http://localhost:8090 spider -c mycontext --start-urls http://app:8080 +zap-cli --zap-url http://localhost:8090 import-har /path/to/authenticated-session.har +``` + +## DAST in ephemeral environments + +Modern CI practices spin up a complete application stack per PR (review apps). DAST fits naturally here: + +``` +PR opened → build image → deploy to ephemeral namespace (k8s) → run DAST → report findings as PR comment → teardown +``` + +Key considerations for ephemeral DAST: +- **Seed the database** with realistic test data so the scanner reaches meaningful application states +- **Exclude destructive operations** from active scanning in shared environments (configure ZAP's active scan policy to skip SQL mutation tests) +- **Time-box the scan** — a full active scan against a complex app can take 30–60 minutes; use a targeted policy that covers the highest-risk rules in under 10 minutes for PR feedback +- **Teardown on failure** — always destroy the ephemeral environment even if the scan fails (`if: always()` in GitHub Actions) + +## False positive management + +DAST produces false positives when it misinterprets safe behavior as a vulnerability (e.g., flagging a reflected query parameter as XSS when output is properly encoded). Management strategies: + +1. **Rules file (`.zap/rules.tsv`)** — suppress specific rule IDs for paths where the finding is a known false positive: + ``` + # .zap/rules.tsv format: alert-id action url-regex + 10038 IGNORE .* # CSP: acceptable in staging + 90033 IGNORE /health # info disclosure: health endpoint by design + ``` +2. **Baseline file** — ZAP's `--baseline` mode stores known findings; subsequent runs only fail on *new* issues. Commit the baseline file to source control. +3. **Separate confirmed from informational findings** — gate only on HIGH and MEDIUM confirmed findings; route INFORMATIONAL to a triage queue. +4. **Review the request/response** — for any flagged finding, ZAP records the exact HTTP request that triggered it. Always verify by replaying the request before escalating. + +## Integration with defect tracking + +Route DAST findings directly to your vulnerability management workflow: + +```bash +# Import ZAP JSON report into DefectDojo +curl -X POST "$DEFECTDOJO_URL/api/v2/import-scan/" \ + -H "Authorization: Token $DEFECTDOJO_TOKEN" \ + -F "scan_type=ZAP Scan" \ + -F "file=@zap-report.json" \ + -F "engagement=$ENGAGEMENT_ID" \ + -F "active=true" \ + -F "verified=false" +``` + +DefectDojo deduplicates against existing findings, maps severity, and creates Jira tickets for new issues automatically if configured. See [Vulnerability Management](../2-7-Operate/2-7-4-Vulnerability-Management.md). + +## Where it fits + +DAST belongs in the Test stage against a running build, and can also run continuously against staging or production-like environments. Combine it with [IAST](2-4-1-Interactive-Application-Security-Testing.md) (inside view) and [SAST](../2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md) (code view) for layered coverage. + +## Common pitfalls and anti-patterns + +- **Scanning only the homepage** — without authentication or a proper sitemap, DAST covers almost nothing meaningful. +- **Ignoring informational findings** — missing security headers and verbose error messages are exploited in real attacks; do not filter them out entirely. +- **Running active DAST against production** — active scanning sends attack payloads. Always run against isolated test environments; use passive-only scanning if production monitoring is desired. +- **Not baselining known findings** — without a baseline, every run floods the team with the same old issues and the new ones get buried. +- **Skipping API surfaces** — modern applications expose most of their logic through APIs; without an OpenAPI spec feed, DAST will miss the majority of the attack surface. +- **Treating a timed-out scan as a pass** — always check scan completion status, not just exit code. + +## Maturity progression + +**Starter** — Run OWASP ZAP baseline (passive) scan against a test environment. Review findings manually and create tickets for high/medium. Integrate as a non-blocking CI step. + +**Intermediate** — Switch to full active scan against an ephemeral environment per release. Feed OpenAPI spec for API coverage. Baseline known findings and block on *new* high/critical. Export to DefectDojo. + +**Advanced** — Authenticated scan covering all user roles. Nuclei templates for business-logic checks. DAST findings correlated with SAST/IAST in ASPM. Continuous passive DAST against staging. Custom scan policies per application risk tier. PR-level ephemeral DAST with findings as PR comments. + +## Metrics and KPIs + +- **New high/critical findings per release** — primary gate signal; should trend toward zero. +- **Scan coverage (pages/endpoints reached)** — low coverage means the scanner isn't authenticated or the app isn't crawlable. +- **Mean time to remediate DAST findings** — compare by severity tier. +- **False-positive rate** — track confirmed vs total findings; a high FP rate signals the need for better scan configuration. +- **Scan completion rate** — percentage of pipeline runs where DAST completes (vs times out or crashes); low rate indicates infrastructure or configuration issues. --- @@ -18,26 +211,20 @@ DAST tools allow for extensive scans from the client side and server side withou ### Open-source -- [OWASP Nettacker](https://owasp.org/www-project-nettacker/) - Automated information gathering and vulnerability scanner with API and Web UI. -- [ZED Attack Proxy](https://www.zaproxy.org) - It is an open source tool which is offered by OWASP for performing security testing +- [Nikto](https://github.com/sullo/nikto) — Web server scanner for known vulnerabilities and misconfigurations; fast and simple, best for quick server-level checks on infrastructure rather than application logic. +- [Nuclei](https://github.com/projectdiscovery/nuclei) — Fast, template-based vulnerability scanner with a massive community template library; ideal for targeted checks, custom business-logic tests, and CVE-specific validation. Highly scriptable. +- [OWASP ZAP](https://www.zaproxy.org/) — Full-featured web application scanner and intercepting proxy; the most widely used open-source DAST tool with strong CI/CD integrations (GitHub Actions, Jenkins, GitLab CI). Best general-purpose DAST starting point. +- [Wapiti](https://github.com/wapiti-scanner/wapiti) — Black-box web application vulnerability scanner; lightweight alternative to ZAP for scripted environments where a full proxy is not needed. ### Commercial -- [Acunetix](https://www.acunetix.com) - An automatic web security testing scanner that accurately scans and audits all web applications, including HTML5, JavaScript and Single Page applications (SPAs) -- [Burp Suite](http://www.portswigger.net/) is an integrated platform for performing security testing of web applications. Its various tools work seamlessly together to support the entire testing process, from initial mapping and analysis of an application’s attack surface, through to finding and exploiting security vulnerabilities. -- [Dastardly](https://portswigger.net/burp/documentation/dastardly) - Lightweight web application security scanner designed to run in CI/CD pipelines. -- [HCL AppScan on Cloud](https://cloud.appscan.com) - DAST tool built as a service. It can scan both public and privatly hosted application. Can explore and test modern web applications, leverage manually recorded steps and handle complex login scenarios. -- [InsightAppSec (AppSpider)](https://www.rapid7.com/products/insightappsec) - Application security testing for the modern web -- [Netsparker](https://www.netsparker.com) - It can identify vulnerabilities in all types of modern web applications, regardless of the underlying architecture or platform -- [Nuclei](https://github.com/projectdiscovery/nuclei) - Fast and customisable vulnerability scanner based on simple YAML based DSL. -- [Veracode Dynamic Analysis](https://www.veracode.com/products/dynamic-analysis-dast) - Veracode Dynamic Analysis helps companies scan their web applications for exploitable vulnerabilities at scale. -- [Escape DAST](https://escape.tech) - Escape DAST is purposely built for testing for business logic vulnerabilities at scale and handling complex auth scenarios in modern applications: APIs (including GraphQL) and Single Page Apps (SPAs) +- [Escape](https://escape.tech/) — DAST focused on APIs and modern web applications; strong GraphQL support and CI-native; best for API-first applications and teams prioritizing developer experience. +- [Invicti (Acunetix/Netsparker)](https://www.invicti.com/) — Automated DAST with proof-based scanning that reduces false positives by confirming exploitability; good for web apps and APIs at scale with compliance reporting. +- [Rapid7 InsightAppSec](https://www.rapid7.com/products/insightappsec/) — Cloud-based DAST with an attack replay feature and integration with the broader Rapid7 platform; best when you already use Rapid7 for vulnerability management. +- [StackHawk](https://www.stackhawk.com/) — Developer-friendly DAST built for CI/CD; runs in Docker with simple YAML configuration; best for developer-owned scanning integrated into GitHub/GitLab workflows. --- ### Links -- [OWASP - Vulnerability Scanning Tools](https://owasp.org/www-community/Vulnerability_Scanning_Tools) -- [RAPID7 - Dynamic Application Security Testing](https://www.rapid7.com/fundamentals/dast/) - [^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md b/current-version/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md index 1f03d37..e2b9ea3 100644 --- a/current-version/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md +++ b/current-version/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md @@ -1,3 +1,202 @@ -# Mobile Application Security Test +# Mobile Application Security Testing - +Mobile applications introduce a distinct threat surface: the app runs on a device the user (and potential attacker) fully controls, stores data locally, communicates over untrusted networks, and can be decompiled and inspected. Mobile Application Security Testing adapts static, dynamic, and interactive techniques to the realities of iOS and Android. + +## The OWASP MAS standard + +The [OWASP Mobile Application Security (MAS)](https://mas.owasp.org/) project is the definitive reference: + +- **MASVS (Verification Standard)** — the security requirements a mobile app should meet, organized into controls: Storage, Cryptography, Authentication, Network, Platform, Code Quality, and Resilience. +- **MASTG (Testing Guide)** — concrete techniques and test cases for verifying those requirements on both iOS and Android, with platform-specific tools and scripts. +- **MAS Checklist** — maps MASVS controls to MASTG test cases for structured assessments; use it as your test plan template. + +### MASVS level selection + +MASVS defines three security levels. Choose based on your app's risk profile: + +| Level | Target apps | Key requirements | +|---|---|---| +| L1 | All apps — baseline for consumer apps with low sensitivity | No sensitive data in logs/cleartext; TLS enforced; basic input validation | +| L2 | Apps handling sensitive or personal data (healthcare, financial, enterprise) | Secure storage (Keystore/Keychain), certificate pinning, strong auth, anti-tampering basics | +| R (Resilience) | High-value apps: banking, digital wallets, DRM, security-sensitive | Obfuscation, jailbreak/root detection, anti-debugging, certificate pinning bypass resistance | + +A mobile banking app should target L2 + R. A general consumer utility app targets L1. An enterprise MDM app likely targets L2. + +## The mobile-specific threat surface + +Mobile introduces threat vectors that do not exist in web apps: + +### Data storage +- Sensitive data in unprotected `SharedPreferences` (Android) or `NSUserDefaults` (iOS) — readable by any app with filesystem access on a rooted device +- Cleartext credentials in SQLite databases, log files, or OS-level screenshot captures +- Auto-backup to cloud (Android) and iCloud (iOS) may exfiltrate data unintentionally + +### Transport and certificate security +- **Certificate pinning bypass** — on rooted/jailbroken devices, an attacker can install a custom CA (e.g., Burp Suite CA) to MitM all TLS traffic. Apps handling sensitive data should implement certificate pinning and detect bypass attempts. +- Missing or misconfigured Network Security Config (Android) or App Transport Security (iOS) allows cleartext HTTP + +### Authentication and biometrics +- Biometric authentication (Face ID, fingerprint) can be bypassed at the OS level on compromised devices. The app must use hardware-backed biometric APIs (Android BiometricPrompt with `BIOMETRIC_STRONG`, iOS LocalAuthentication with `.deviceOwnerAuthenticationWithBiometrics`) and must not fall back to PIN trivially. +- JWT or session tokens stored in SharedPreferences or NSUserDefaults instead of Android Keystore / iOS Keychain are readable on rooted devices + +### Deep links and inter-app communication +- Unvalidated deep links accept attacker-controlled URLs that invoke privileged in-app actions +- Android Intents with exported Activities/Services/Broadcast Receivers that lack permission checks allow any app to trigger internal functionality +- iOS Universal Links require proper apple-app-site-association configuration; improper setup allows link hijacking + +### Reverse engineering +- Debug builds with `android:debuggable="true"` allow arbitrary code injection via `adb` +- Hardcoded API keys, encryption keys, or credentials in `strings.xml`, `BuildConfig`, or `Info.plist` +- Unobfuscated business logic exposes algorithms, backend endpoints, and internal decision trees to competitors or attackers + +### Jailbreak and root detection +- On jailbroken (iOS) or rooted (Android) devices, security controls enforced by the OS (sandboxing, Keychain isolation, certificate pinning) may be bypassed. L2/R apps should detect and respond to compromised device states. + +## What to test (organized by MASVS category) + +- **Storage** — check all data written after sensitive operations (login, payment, health data entry) using device filesystem inspection +- **Cryptography** — review algorithms used; look for hardcoded keys, ECB mode, deprecated hash functions +- **Authentication** — test session expiry, re-authentication for sensitive actions, biometric bypass on rooted devices +- **Network** — proxy all traffic; look for HTTP, self-signed cert acceptance, missing pinning +- **Platform** — check exported components, deep link handling, clipboard exposure, screenshot protection +- **Code Quality** — static analysis for dangerous APIs, debug flags, hardcoded secrets +- **Resilience** (L2+R) — test jailbreak/root detection bypass, debugger attachment, dynamic instrumentation hooks + +## Static analysis with MobSF (walkthrough) + +MobSF provides automated static and dynamic analysis via a web UI and REST API. For CI integration: + +```bash +# 1. Start MobSF (Docker) +docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest + +# 2. Upload and scan an APK +HASH=$(curl -s -X POST "http://localhost:8000/api/v1/upload" \ + -H "Authorization: $MOBSF_API_KEY" \ + -F "file=@./app-release.apk" | jq -r '.hash') + +# 3. Trigger scan +curl -s -X POST "http://localhost:8000/api/v1/scan" \ + -H "Authorization: $MOBSF_API_KEY" \ + -d "hash=$HASH" + +# 4. Get JSON report +curl -s -X POST "http://localhost:8000/api/v1/report_json" \ + -H "Authorization: $MOBSF_API_KEY" \ + -d "hash=$HASH" | jq '.average_cvss, .security_score' + +# 5. Gate: fail build if security score below threshold +SCORE=$(curl -s -X POST "http://localhost:8000/api/v1/report_json" \ + -H "Authorization: $MOBSF_API_KEY" \ + -d "hash=$HASH" | jq '.security_score') +[ "$SCORE" -lt 60 ] && echo "FAIL: MobSF score $SCORE below threshold" && exit 1 +``` + +Run this step in CI on every release build and on the nightly build for the main branch. + +## Dynamic analysis with Frida + +[Frida](https://frida.re/) is a dynamic instrumentation toolkit that lets you inject JavaScript into a running app process to hook methods, bypass controls (for testing), and observe behavior static analysis cannot see. + +Common testing use cases: + +```javascript +// Hook SSL pinning methods to observe bypassed traffic during testing +// (Android — OkHttp certificate pinner) +Java.perform(function () { + var CertificatePinner = Java.use('okhttp3.CertificatePinner'); + CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function (hostname, peerCertificates) { + console.log('[Frida] SSL pinning bypassed for: ' + hostname); + return; // skip the check + }; +}); + +// Hook biometric authentication result (for testing fallback behavior) +Java.perform(function () { + var BiometricPrompt = Java.use('androidx.biometric.BiometricPrompt$AuthenticationCallback'); + BiometricPrompt.onAuthenticationSucceeded.implementation = function (result) { + console.log('[Frida] Biometric auth succeeded (hooked)'); + this.onAuthenticationSucceeded(result); + }; +}); +``` + +Use Frida to validate that L2/R controls are effective: attempt a bypass and confirm detection. The [objection](https://github.com/sensepost/objection) framework wraps Frida into an interactive shell for common tasks without writing scripts. + +**Important:** Frida-based pinning bypass is a testing technique for evaluating implementation correctness. Production builds must enforce pinning and detect Frida/instrumentation frameworks as part of Resilience controls. + +## App Store and Play Store security review + +Both Apple and Google perform automated and manual security review: + +- **Google Play** — uses automated scanning for known malware patterns and policy violations. Severe security issues can trigger removal. Play App Signing gives Google control over the final signing key. +- **Apple App Store** — manual review checks for private API usage, inappropriate data access, and some security patterns. App Attest and DeviceCheck APIs provide server-side device integrity signals. + +Neither store's review is a substitute for your own security assessment — store reviews focus on policy compliance, not application security depth. Run your security program independently. + +## CI/CD integration + +A typical mobile security pipeline step: + +```yaml +# GitHub Actions — mobile security gate on release builds +- name: Mobile SAST (MobSF) + run: | + HASH=$(curl -s -X POST "$MOBSF_URL/api/v1/upload" \ + -H "Authorization: $MOBSF_API_KEY" \ + -F "file=@$APK_PATH" | jq -r '.hash') + curl -s -X POST "$MOBSF_URL/api/v1/scan" \ + -H "Authorization: $MOBSF_API_KEY" -d "hash=$HASH" + SCORE=$(curl -s -X POST "$MOBSF_URL/api/v1/report_json" \ + -H "Authorization: $MOBSF_API_KEY" -d "hash=$HASH" | jq '.security_score') + [ "$SCORE" -lt 60 ] && exit 1 || echo "Score: $SCORE" +``` + +Gate on MobSF's security score and block on critical findings. Complement with periodic manual assessment for logic flaws, reverse-engineering resistance, and platform-specific misuse. + +## Common pitfalls and anti-patterns + +- **Testing only against an emulator** — some security controls (Secure Enclave, hardware-backed Keystore) behave differently on physical devices. Test on real hardware for L2/R assessments. +- **Bypassing SSL pinning without understanding the impact** — pinning bypass is necessary for testing but never acceptable in production. Verify pinning is actually enforced in release builds. +- **Treating mobile security as a one-time pentest** — mobile threat landscape changes with OS updates. Continuous CI scanning catches regressions introduced by dependency or SDK updates. +- **Ignoring the backend** — mobile-specific app security means little if the backend API accepts unauthenticated calls or has BOLA/IDOR flaws. +- **Not testing deep-link and intent handling** — these are a common entry point for mobile-specific attacks and are often missed by automated scanners. + +## Maturity progression + +**Starter** — Run MobSF static scan on every release APK/IPA. Review MASVS L1 checklist manually for critical apps. Create tickets for high findings. + +**Intermediate** — Automate MobSF in CI pipeline with a score gate. Add dynamic testing with Burp Suite proxy during QA. Validate all MASVS L1 controls automatically; manually verify L2 controls for sensitive apps. + +**Advanced** — Full MASVS L2 automated coverage with Frida scripts for runtime checks. Continuous API testing from proxied device tests. Integrate findings into central ASPM. Resilience (R) assessment for banking or DRM apps. Track MASVS coverage as a metric per release. + +## Metrics and KPIs + +- **MASVS controls passing per level (L1/L2/R)** — expressed as a percentage; track regression per release. +- **Critical/high findings per build** — gate signal; should reach zero before release. +- **Mean time to remediate mobile findings** — compare to web app MTTR. +- **MobSF security score trend** — track over time to catch gradual degradation from dependency updates. + +--- + +## Tools[^1] + +### Open-source + +- [Frida](https://frida.re/) — Dynamic instrumentation toolkit for inspecting and manipulating apps at runtime; hooks methods, bypasses SSL pinning (for testing), dumps memory, and traces API calls. The foundation of most advanced mobile testing and L2/R validation. +- [MobSF (Mobile Security Framework)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) — Automated static and dynamic analysis for Android and iOS; supports APK, IPA, and APPX; REST API enables CI integration. Best starting point for automated mobile scanning. +- [objection](https://github.com/sensepost/objection) — Runtime mobile exploration powered by Frida; provides an interactive shell for real-time security testing without needing to write Frida scripts manually. Fastest path to SSL pinning bypass and biometric testing. +- [apktool](https://github.com/iBotPeaches/Apktool) — Reverse-engineering tool for Android APKs; decompiles to smali, inspects resources and manifest, and repackages. Used for manifest analysis and detecting debug flags. +- [jadx](https://github.com/skylot/jadx) — Dex-to-Java decompiler; reads Android app logic from compiled bytecode. Cleaner output than apktool's smali for code review. + +### Commercial + +- [Appknox](https://www.appknox.com/) — Mobile application security testing platform with automated SAST/DAST, compliance mapping, and app store integration; good for teams wanting managed mobile security without building their own toolchain. +- [NowSecure](https://www.nowsecure.com/) — Mobile app security testing and continuous monitoring with automated dynamic analysis on real devices; widely used in financial services for L2 and R assessments. +- [Oversecured](https://oversecured.com/) — Android-focused static analysis with deep interprocedural analysis; finds vulnerabilities that simpler scanners miss, particularly in complex multi-component apps. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-4-Test/2-4-4-API-Security.md b/current-version/2-Process/2-4-Test/2-4-4-API-Security.md index c89b66e..9938fba 100644 --- a/current-version/2-Process/2-4-Test/2-4-4-API-Security.md +++ b/current-version/2-Process/2-4-Test/2-4-4-API-Security.md @@ -1,3 +1,132 @@ # API Security - +APIs are the connective tissue of modern applications — and the dominant attack surface. As architectures shift to microservices, mobile backends, and third-party integrations, most business logic and data is exposed through APIs. Attackers have followed, making API security a first-class testing concern rather than a subset of web testing. The 2023 Verizon DBIR and OWASP data consistently show API-related vulnerabilities in the top causes of breaches. + +## The OWASP API Security Top 10 + +The [OWASP API Security Top 10 (2023)](https://owasp.org/API-Security/) frames the most critical API risks: + +| Risk | Description | Why it is hard to catch | +|---|---|---| +| **BOLA/IDOR** (API1) | Accessing other users' objects by manipulating IDs | Requires testing with multiple user sessions; scanners cannot infer valid IDs | +| **Broken Authentication** (API2) | Weak or missing authentication on endpoints | Often found only on non-obvious or legacy endpoints | +| **Broken Object Property Level AuthZ** (API3) | Over-exposing or allowing modification of fields (mass assignment, excessive data exposure) | Requires comparing spec vs actual response | +| **Unrestricted Resource Consumption** (API4) | Missing rate limiting enabling abuse and DoS | Requires scripted load testing, not passive scanning | +| **Broken Function Level AuthZ** (API5) | Accessing admin/privileged functions without checks | Requires role-based test cases across all permission levels | +| **Unrestricted Access to Sensitive Business Flows** (API6) | Automating flows not intended for automation (e.g., bulk purchase, account takeover) | Logic-specific; tooling alone cannot detect | +| **SSRF** (API7) | Server-side request forgery via API parameters | Requires active payload injection and out-of-band detection | +| **Security Misconfiguration** (API8) | Default credentials, unnecessary endpoints, verbose error messages | Schema drift, debug flags, CORS wildcards | +| **Improper Inventory Management** (API9) | Shadow APIs, deprecated/zombie endpoints still live | Requires ongoing discovery, not point-in-time testing | +| **Unsafe API Consumption** (API10) | Trusting third-party API responses without validation | Requires review of every external integration | + +## Testing and protecting APIs + +### API discovery and inventory + +You cannot protect what you do not know about. Maintain a live API inventory by: + +- Parsing OpenAPI/AsyncAPI specs from source control. +- Passive traffic analysis in staging/production to detect shadow APIs (endpoints that receive traffic but are not in the spec). +- Regular crawls and traffic baselining to catch zombie APIs (deprecated endpoints still responding). + +```bash +# Example: Use Akto to discover APIs from network traffic +# After mirroring traffic to Akto collector, view discovered endpoints at dashboard +``` + +### Schema and contract testing + +The spec is a security contract. Test that the implementation matches it: + +- **Positive testing** — valid requests return expected responses. +- **Negative testing** — invalid inputs, missing required fields, wrong types return proper error codes (not 500s or data leaks). +- **Boundary testing** — values at extremes (max length, integer overflow, empty strings). + +Schemathesis auto-generates test cases from your OpenAPI/GraphQL spec and can run in CI as a gate. + +### Authorization testing (BOLA/IDOR) + +This is the #1 API risk and requires explicit test cases because scanners cannot derive valid object IDs: + +1. Create two test accounts (User A, User B). +2. User A creates a resource; capture its ID. +3. Authenticate as User B and attempt to access/modify User A's resource using the same ID. +4. The API must return 403 or 404, not the resource data. + +Automate this pattern for every resource type. Tools like Escape and Akto have some BOLA detection, but manual test cases covering your data model are essential. + +### Fuzzing + +Send malformed and boundary-value inputs to surface crashes and unexpected behavior: + +- **Schema-based fuzzing** — Schemathesis generates inputs that violate schema constraints to find validation gaps. +- **Generative fuzzing** — tools like RESTler or custom Radamsa-based scripts send novel inputs to find crashes and logic flaws. +- **Parameter pollution** — duplicate parameters, arrays where scalars are expected, nested objects. + +### API-aware DAST + +Standard web DAST crawlers do not understand REST or GraphQL semantics. Feed the scanner your API spec: + +```bash +# OWASP ZAP API scan from OpenAPI spec +docker run -v $(pwd):/zap/wrk/:rw \ + ghcr.io/zaproxy/zaproxy:stable \ + zap-api-scan.py -t api-spec.yaml -f openapi \ + -r api-scan-report.html -x api-scan-report.xml +``` + +### Runtime protection and monitoring + +Testing catches issues before release; runtime protection catches exploitation in production: + +- API gateway policies: enforce authentication, rate limits, request size limits, and schema validation on every request. +- Anomaly detection: flag unusual access patterns (account enumeration, excessive data retrieval, parameter tampering). +- Continuous discovery: re-run inventory analysis against production traffic to catch new shadow APIs. + +## Common pitfalls and anti-patterns + +- **Relying only on authentication as the authorization check** — an authenticated user should not be able to access other users' resources. Auth and authz are separate. +- **Not testing with multiple user roles** — a single test account misses privilege escalation and BFLA (Broken Function Level Authorization). +- **Spec drift** — the OpenAPI spec is updated, but tests still cover the old contract. Automate spec-to-test synchronization. +- **Trusting the API gateway to do all security** — gateways enforce rate limits and authN, but BOLA and business logic flaws require application-layer validation. +- **Not monitoring for API abuse in production** — attacks on APIs are often slow and low-volume; signature-based WAFs miss them without behavioral baselines. + +## Maturity progression + +**Starter** — Maintain an OpenAPI spec for every API. Run OWASP ZAP API scan in CI against each build. Create BOLA test cases for the two most critical resources. + +**Intermediate** — Add Schemathesis schema-validation testing in CI. Automate BOLA/IDOR test cases for all resource types. Deploy API gateway with rate limiting and schema enforcement. Run passive traffic discovery in staging. + +**Advanced** — Continuous runtime traffic analysis to detect shadow/zombie APIs and anomalous access. Full OWASP API Top 10 test coverage automated per release. Correlation of API findings with application risk in ASPM. Red team exercises targeting API authorization logic. + +## Metrics and KPIs + +- **API inventory completeness** — percentage of known API endpoints that have a corresponding spec entry (higher = fewer shadow APIs). +- **BOLA/IDOR test coverage** — percentage of resource types with automated authorization test cases. +- **New high/critical API findings per release** — primary gate signal. +- **Shadow API count** — discovered endpoints not in the spec; should trend toward zero. +- **API gate pass rate** — percentage of builds where API tests pass without exceptions. + +--- + +## Tools[^1] + +### Open-source + +- [Akto](https://github.com/akto-api-security/akto) — API discovery from network traffic and security testing; good for finding shadow APIs in staging environments. +- [OWASP ZAP](https://www.zaproxy.org/) — Supports API scanning from OpenAPI/SOAP/GraphQL definitions via `zap-api-scan.py`; strong CI integration. +- [Schemathesis](https://github.com/schemathesis/schemathesis) — Property-based API testing from OpenAPI/GraphQL spec; excellent for finding schema-validation bypass and server crashes. +- [RESTler](https://github.com/microsoft/restler-fuzzer) — Stateful REST API fuzzer from Microsoft Research; generates and executes sequences of API calls to find logic and resource-management flaws. + +### Commercial + +- [Escape](https://escape.tech/) — API discovery and dynamic security testing; strong GraphQL support and CI-native with developer-friendly findings. +- [Noname Security (Akamai API Security)](https://www.akamai.com/products/api-security) — API discovery, posture management, and runtime protection; strong on detecting anomalous access patterns in production traffic. +- [Salt Security](https://salt.security/) — API security platform for discovery and runtime defense; uses ML-based behavioral analysis to detect API-targeted attacks. +- [42Crunch](https://42crunch.com/) — API security audit from OpenAPI spec and runtime protection; integrates directly into the development workflow with IDE plugins. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md b/current-version/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md index e53a816..49e0c2a 100644 --- a/current-version/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md +++ b/current-version/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md @@ -1,3 +1,117 @@ # Misconfiguration Check - +Security misconfiguration is one of the most common — and most preventable — causes of breaches. It is consistently in the [OWASP Top 10](https://owasp.org/Top10/A05_2021-Security_Misconfiguration/). Unlike code vulnerabilities, misconfigurations arise from *how systems are set up*: default credentials left in place, unnecessary features enabled, verbose errors, missing hardening, and overly permissive access. Misconfiguration checks systematically verify that applications, infrastructure, containers, and cloud resources are configured against secure baselines. + +## Why misconfigurations dominate breaches + +Misconfigurations are exploitable with little skill — no custom exploit is needed. A public S3 bucket, an exposed Kubernetes dashboard, or a management port open to the internet can be found and exploited within hours of deployment. The combination of complexity (modern infrastructure has thousands of configuration parameters), speed (infrastructure is provisioned and changed continuously), and default-insecure tooling makes misconfiguration a persistent, high-probability risk that requires automated, continuous checking rather than periodic audits. + +## Common misconfigurations by layer + +### Application and web server +- Missing security headers: `Content-Security-Policy`, `Strict-Transport-Security`, `X-Frame-Options`, `X-Content-Type-Options`, `Permissions-Policy`. +- Insecure TLS: TLS 1.0/1.1 still enabled, weak cipher suites, missing HSTS, missing certificate pinning. +- Verbose error messages leaking stack traces, internal paths, or framework versions. +- Debug endpoints (`/actuator`, `/_debug`, `/graphiql`) left enabled in production. +- Default or sample accounts not removed. + +### Infrastructure as Code +- Open-to-internet security groups (`0.0.0.0/0` on port 22 or 3389). +- Storage buckets with public read/write ACLs. +- Unencrypted EBS volumes, RDS databases, or S3 buckets. +- Missing resource-level IAM conditions (e.g., `aws:RequestedRegion`). + +These are best caught before provisioning — see [IaC Scanning](../2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md). + +### Containers and Kubernetes +- Containers running as root with no `runAsNonRoot: true` pod spec. +- Privileged containers (`privileged: true`) or excessive capabilities (`CAP_SYS_ADMIN`). +- Missing resource limits (CPU/memory) creating DoS risk. +- No network policies — all pods can communicate with all pods by default. +- No Pod Security Standards (PSS) admission control enforced at the cluster level. +- Public-facing Kubernetes dashboard with weak or no authentication. + +### Cloud (runtime posture) +- IAM users with full `*:*` permissions or stale access keys (>90 days without rotation). +- Root account MFA not enabled. +- CloudTrail/audit logging disabled for critical APIs. +- Security group rules accumulated over time, never reviewed. +- No encryption at rest for databases and object storage. + +## How to check, across layers + +- **Application and web server** — verify headers, TLS configuration, error handling, and disabled debug features; often done via [DAST](2-4-2-Dynamic-Application-Security-Testing.md) or dedicated header-check tools in CI. +- **Infrastructure as Code** — catch misconfigurations before provisioning with Trivy, Checkov, or tfsec (see [IaC Scanning](../2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md)). +- **Containers and Kubernetes** — check images and cluster configuration against [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks) and Pod Security Standards using kube-bench, Trivy, or Kubescape. +- **Cloud resources at runtime** — Cloud Security Posture Management (CSPM) and Kubernetes Security Posture Management (KSPM) detect drift and misconfigurations in live environments continuously (see [Cloud-Native Security](../2-7-Operate/2-7-1-Cloud-Native-Security.md)). + +## CI/CD integration example (Trivy misconfiguration scan) + +```yaml +# GitHub Actions — scan IaC and Kubernetes manifests +- name: Trivy misconfiguration scan + uses: aquasecurity/trivy-action@master + with: + scan-type: config + scan-ref: . + severity: HIGH,CRITICAL + exit-code: 1 + format: sarif + output: trivy-misconfig.sarif + +- name: Upload results to GitHub Security + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: trivy-misconfig.sarif +``` + +## Make it continuous + +Configuration drifts over time, so a one-time check is insufficient. A configuration that passes today can be manually changed tomorrow, overridden by a Helm upgrade, or exposed by a new feature. Define secure baselines as [Policy as Code](../../3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md), enforce them in CI and at admission control (Kyverno, OPA/Gatekeeper), and continuously monitor running environments for drift with CSPM. Map checks to recognized benchmarks (CIS, NIST) so results are auditable and comparable over time. + +## Common pitfalls and anti-patterns + +- **One-time hardening with no drift detection** — a system hardened at launch drifts back to insecure state within months. Continuous monitoring is mandatory. +- **Treating IaC scanning as a replacement for runtime CSPM** — IaC misses manually applied changes, console-provisioned resources, and drift introduced between deploys. +- **Suppressing too many findings** — teams under pressure suppress "accepted" misconfigurations and never revisit them. Time-box all suppressions. +- **Ignoring informational and low findings** — missing security headers are "low severity" but exploited in real attacks (clickjacking, MIME sniffing). Build a remediation SLA for all severity levels. +- **Not mapping to a benchmark** — ad-hoc checklists drift over time and cannot be compared across teams. Use CIS Benchmarks or similar as the authoritative baseline. + +## Maturity progression + +**Starter** — Run Trivy `--scanners misconfig` in CI on IaC/Kubernetes manifests. Run kube-bench on all Kubernetes clusters. Fix high/critical findings before release. + +**Intermediate** — Enforce IaC misconfiguration gate in CI (block on critical). Deploy CSPM tool (Prowler or cloud-native) for continuous runtime posture. Define secure configuration baselines per environment tier. + +**Advanced** — Policy-as-code admission control (Kyverno/OPA) blocks misconfigured workloads at deploy time. CSPM alerts feed into SIEM with auto-remediation for common patterns (e.g., Lambda auto-closes public S3 ACLs). Track CIS Benchmark compliance score per environment as a KPI. Configuration drift triggers automated incident. + +## Metrics and KPIs + +- **CIS Benchmark compliance score (%)** per environment (dev/staging/prod) — track trend. +- **High/critical misconfiguration count** — by layer (app, IaC, container, cloud); should trend toward zero. +- **Mean time to remediate misconfigurations** — by severity tier. +- **Configuration drift incidents** — number of times runtime config diverged from IaC definition. +- **Suppressed finding count and age** — old suppressions indicate accepted-risk debt accumulating. + +--- + +## Tools[^1] + +### Open-source + +- [kube-bench](https://github.com/aquasecurity/kube-bench) — Checks Kubernetes nodes and control plane against the CIS Benchmark; run as a Job in-cluster for comprehensive coverage. +- [Kubescape](https://github.com/kubescape/kubescape) — Kubernetes security posture tool covering NSA/CISA hardening guidance, MITRE ATT&CK, and CIS Benchmarks; developer-friendly CLI and CI integration. +- [Lynis](https://github.com/CISOfy/lynis) — Security auditing and hardening tool for Unix/Linux systems; covers system configuration, package management, authentication, and more. +- [Prowler](https://github.com/prowler-cloud/prowler) — Cloud security posture and misconfiguration assessment for AWS, Azure, and GCP; maps to CIS, SOC2, PCI-DSS, ISO 27001, and HIPAA. +- [Trivy](https://github.com/aquasecurity/trivy) — Misconfiguration scanning for IaC (Terraform, CloudFormation, Helm, Kubernetes manifests); also covers container images and dependencies in a single tool. + +### Commercial + +- [Prisma Cloud](https://www.paloaltonetworks.com/prisma/cloud) — CNAPP with cloud posture management, IaC scanning, and runtime misconfiguration detection; strong cross-cloud coverage. +- [Wiz](https://www.wiz.io/) — Agentless cloud misconfiguration and posture management; fast deployment with graph-based risk prioritization that connects misconfigurations to their blast radius. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-5-Release/2-5-1-Release.md b/current-version/2-Process/2-5-Release/2-5-1-Release.md index 623aa21..9a22ccf 100644 --- a/current-version/2-Process/2-5-Release/2-5-1-Release.md +++ b/current-version/2-Process/2-5-Release/2-5-1-Release.md @@ -1,3 +1,124 @@ # Release - +The release stage is the final checkpoint before software leaves the build pipeline and becomes a candidate for deployment. It is where all the earlier security work is consolidated into a verifiable, trustworthy package and where the final go/no-go decision is made. A disciplined release process ensures that only artifacts meeting your security bar — built from trusted source, scanned, signed, and documented — can move toward production. + +## Security activities at release + +- **Final security gate** — confirm there are no unresolved critical/high findings (or that exceptions are documented and approved). See [Security Gates](../2-3-Build/2-3-5-Security-Gates.md). +- **Attach supply-chain metadata** — bind the [SBOM](../2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md) and build [provenance](../2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md) to the release artifact. +- **Sign the artifact** — produce a cryptographic signature so downstream consumers and the deploy stage can verify integrity and origin. +- **Release approval** — capture sign-off (automated policy and/or human approval) and tie it to change management for auditability. +- **Security-relevant release notes** — document fixed vulnerabilities, CVE references, and changed security-affecting configurations so downstream consumers and operators have the information they need. + +## Immutable, traceable artifacts + +### Immutability + +Once released, an artifact must never change. Any fix produces a new versioned artifact. Without this guarantee, a "tested" artifact can be silently substituted for a malicious one, and the test results become meaningless. + +Enforce immutability technically: +- Enable **tag immutability** in your container registry (AWS ECR, GitHub Packages, Artifactory) so a published tag cannot be overwritten. +- Use **content-addressable references** (image digest `sha256:...`) in deployment manifests, not mutable tags like `latest` or `v1.2`. +- Protect release tags in source control: see [Repository Hardening](../2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md). + +### Trusted registry + +Publish artifacts to a controlled registry with: +- Access controls: only CI pipelines (via OIDC, not long-lived keys) can push; humans read-only. +- Retention policies: retain all released versions; automatically clean up pre-release candidates. +- Vulnerability scanning at rest: re-scan stored images as new CVEs are disclosed (many registries offer this natively). +- Signing: every pushed artifact is signed at publish time. + +### Traceability + +Every release should be traceable back to its exact source commit, build pipeline run, and the security scans that passed. SLSA signed provenance makes this linkage cryptographically verifiable: + +```bash +# Verify a container image's provenance with cosign (Sigstore) +cosign verify-attestation \ + --type slsaprovenance \ + --certificate-identity-regexp "https://github.com/myorg/myrepo/.github/workflows/release.yml" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ + myregistry/myimage:v1.2.3 +``` + +The attestation proves: who built it, when, from which commit, using which workflow — without any additional trust in the registry. + +## Promotion between environments + +Mature pipelines build an artifact **once** and promote the same artifact through environments (test → staging → production) rather than rebuilding per environment: + +- The artifact that passed security scans in test is *exactly* the artifact deployed to production — no re-build, no re-introduction of variance, no "it worked on staging" surprises. +- Before each promotion, re-verify the artifact's signature and provenance against the registry. An artifact that cannot be verified is not promoted. +- Use **GitOps** to make promotion declarative and auditable: a promotion is a pull request (image digest bump in the environment manifest), not a manual action or a shell script with credentials. + +Example promotion gate with cosign: +```bash +# In the production promotion workflow +IMAGE_DIGEST=$(crane digest myregistry/myimage:v1.2.3) +cosign verify \ + --certificate-identity "...release.yml@refs/tags/v1.2.3" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ + myregistry/myimage@$IMAGE_DIGEST || exit 1 +``` + +## Release approval and change management + +Different release categories warrant different approval models: + +| Release category | Approval model | +|---|---| +| Patch / bug fix (low risk) | Automated policy check (OPA/Conftest) against artifact metadata; no human gate | +| Minor feature release | Automated gate + team lead approval in PR; auto-notifies change management | +| Major release or regulated system | Formal change request, named CAB approver, rollback plan documented in ServiceNow/Jira | +| Emergency hotfix | Expedited single-approver process; post-review required within 24 hours | + +Automated policy checks via OPA or Conftest can evaluate artifact metadata (SBOM attached, signature present, no unresolved criticals, provenance verified) and produce a machine-readable attestation that human reviewers use as evidence — reducing cognitive load and audit effort. + +## Common pitfalls and anti-patterns + +- **Rebuilding per environment** — if a new build is created for production, all test results from the staging build are meaningless. Build once, promote everywhere. +- **Mutable tags in production** — using `latest` or a branch-name tag means deployments can inadvertently roll forward or back without an explicit decision. +- **Release notes with no security content** — downstream teams need to know which CVEs were fixed and which security behaviors changed to assess their own exposure. +- **Signing as a one-time event without verification at deploy** — signing is only valuable if the signature is actually verified before the artifact runs. Many teams sign but never verify. +- **Change management as a bureaucratic checkbox** — if the change management process adds weeks of delay without reducing risk, teams work around it. Automate low-risk approvals so the process has teeth where it matters. + +## Maturity progression + +**Starter** — Protect release tags in source control. Publish artifacts to a private registry. Include SBOM in release packages. Document final gate criteria. + +**Intermediate** — Enforce tag immutability. Sign all release artifacts with cosign (keyless, OIDC). Automated OPA gate checks for low-risk releases. SBOM attached as registry attestation. Release notes include CVEs fixed. + +**Advanced** — Full SLSA Level 3 provenance. Signature verification at every promotion stage. Automated policy approval for low-risk releases; human gate only for high-risk. Re-scan stored artifacts as new CVEs are published. Continuous SLA tracking for vulnerability remediation between releases. + +## Metrics and KPIs + +- **Percentage of releases with signed, attested provenance** — target 100%. +- **Mean time from critical CVE disclosure to release containing the fix** — measures responsiveness; define SLAs by severity. +- **Release rollback rate** — security-related rollbacks indicate insufficient pre-release gates. +- **Unsigned or unverified deployments** — any deployment of an unsigned artifact is an incident; should be zero. +- **Time in change management** — high average time indicates the approval process is a bottleneck; automate low-risk cases. + +--- + +## Tools + +| Category | Examples | +|---|---| +| Artifact registries | JFrog Artifactory, Sonatype Nexus, GitHub Packages, AWS ECR, Google Artifact Registry, Harbor (open source) | +| Container signing and verification | Sigstore/cosign (keyless, OIDC-based), Notary v2 (Docker Content Trust) | +| Provenance and SLSA | SLSA framework, GitHub Actions OIDC + sigstore, in-toto, Tekton Chains | +| Policy-based release approval | OPA/Conftest, Kyverno, Open Policy Agent admission webhook | +| Change management integration | ServiceNow, Jira Service Management, PagerDuty Change Events | +| GitOps promotion | Argo CD (ApplicationSets + image-updater), Flux, Spinnaker | + +--- + +## Further reading + +- [SLSA — provenance and verification](https://slsa.dev/) +- [NIST SSDF — PS (Protect the Software) practices](https://csrc.nist.gov/Projects/ssdf) +- [CNCF Software Supply Chain Best Practices](https://github.com/cncf/tag-security) +- [Sigstore — keyless signing](https://www.sigstore.dev/) +- [Harbor — open source container registry](https://goharbor.io/) +- [OpenSSF — Securing the Software Supply Chain](https://openssf.org/) diff --git a/current-version/2-Process/2-6-Deploy/2-6-1-Deploy.md b/current-version/2-Process/2-6-Deploy/2-6-1-Deploy.md index 623aa21..8759599 100644 --- a/current-version/2-Process/2-6-Deploy/2-6-1-Deploy.md +++ b/current-version/2-Process/2-6-Deploy/2-6-1-Deploy.md @@ -1,3 +1,134 @@ -# Release +# Deploy - +Deployment moves a released artifact into a running environment. It is the last gate before software is exposed to real traffic, and it is where supply-chain verification, environment configuration, and runtime access converge. Secure deployment ensures that **only verified artifacts** reach production, that they run with **least privilege**, and that the blast radius of any problem is contained. + +## Verify before you run: admission control + +The deploy stage is where signing and provenance pay off. Do not allow an artifact to run unless you can cryptographically verify where it came from and that it passed required checks. Enforce policy at admission so that: + +- Only **signed** artifacts with valid signatures are admitted (see [Artifact Signing and Provenance](../2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md)). +- Only artifacts with acceptable **provenance** (SLSA level, build workflow, source repository) run in production. +- Images that fail policy — unsigned, from untrusted registries, or containing unresolved critical CVEs — are **blocked at admission**, not merely flagged in a dashboard. + +Kubernetes admission controllers (Kyverno, OPA/Gatekeeper, Sigstore policy-controller) enforce these rules as code, consistently and automatically. + +```yaml +# Kyverno policy: require all images to be signed with cosign +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-image-signature +spec: + validationFailureAction: Enforce + rules: + - name: check-image-signature + match: + resources: + kinds: [Pod] + verifyImages: + - imageReferences: ["myregistry.io/*"] + attestors: + - entries: + - keyless: + subject: "https://github.com/myorg/*" + issuer: "https://token.actions.githubusercontent.com" +``` + +## GitOps and declarative deployment + +GitOps makes the desired state of an environment a version-controlled, auditable artifact: + +- The git repository is the single source of truth for deployment state. Changes go through reviewed pull requests — not SSH sessions, not manual Helm installs. +- A reconciler (Argo CD, Flux) continuously applies the desired state and corrects drift. If someone manually modifies a running workload, the reconciler reverts it. +- Every change has a full audit trail: who opened the PR, who approved it, when it merged, what the diff was — all in git history. +- Rollback is a `git revert` — fast, auditable, and not dependent on tribal knowledge. + +Use **image digest pinning** in deployment manifests rather than mutable tags: +```yaml +# Prefer this (immutable): +image: myregistry.io/myapp@sha256:a1b2c3d4... +# Not this (mutable): +image: myregistry.io/myapp:latest +``` + +## Limit blast radius with progressive delivery + +Roll out changes gradually so a bad release — whether a bug, a security regression, or a compromised artifact — affects as few users and systems as possible: + +- **Canary deployment** — route a small percentage of traffic (e.g., 5%) to the new version. Monitor error rates, latency, and security signals. Promote only if metrics are healthy. +- **Blue-green deployment** — run the new version alongside the old. Instantly switch traffic back if issues appear; the old version is not terminated until confidence is established. +- **Feature flags** — deploy code without activating new behavior; enable features for specific users or percentages via a feature flag service. Decouples deploy from release. +- **Automated rollback** — define health criteria and automatically revert if they breach thresholds within a deployment window. + +## Least privilege and secrets at deploy + +### Deploy identity + +The service account or role used by the deployment pipeline should have: +- Write access only to the target environment (not all environments). +- Permission to update the specific workloads it manages, not cluster-admin. +- Time-limited credentials: use OIDC workload identity (GitHub Actions → AWS IRSA, GCP Workload Identity) rather than long-lived access keys. + +### Secrets injection + +Never bake secrets into images or deployment manifests. Inject them at runtime from a trusted source: + +- **Vault agent sidecar** — a secrets management sidecar injects secrets into the pod filesystem or environment at startup and rotates them without restart. +- **Kubernetes External Secrets Operator** — syncs secrets from AWS Secrets Manager, HashiCorp Vault, or GCP Secret Manager into Kubernetes Secrets automatically. +- **Cloud-native workload identity** — services authenticate to cloud APIs using instance identity (IRSA, Workload Identity Federation) with no stored credential at all. + +See [Secrets Management](../2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md). + +## Environment parity and configuration security + +- Use the same base image and the same configuration parameters across environments — the only differences should be externally injected (vault paths, endpoint URLs, TLS certificates). +- Never disable security controls in lower environments to make testing easier. A control disabled in staging often gets forgotten and reaches production. +- Configuration drift between environments is a leading cause of "works in staging, fails in production" security incidents. IaC and GitOps eliminate drift by making configuration declarative. + +## Common pitfalls and anti-patterns + +- **Manual deployments with shared credentials** — no audit trail, broad permissions, and credentials that are never rotated. Replace with automated pipelines and workload identity. +- **`latest` tags in production** — a mutable tag means any registry push can change what runs in production. Use digest-pinned references. +- **Admission control in audit-only mode forever** — many teams set admission controllers to warn but never enforce, defeating the purpose. Set a deadline to switch to enforcement. +- **Secrets in environment variables at build time** — environment variables leak into logs, crash dumps, and `/proc` on Linux. Use mounted secret files or vault agent injection instead. +- **No rollback plan** — deployment without a tested rollback plan is high-risk. Verify rollback in staging before every major production deploy. + +## Maturity progression + +**Starter** — Deploy via reviewed PRs to a private registry. Use a scoped deploy identity. Inject secrets from a vault rather than baking them in. Document a manual rollback procedure. + +**Intermediate** — GitOps with Argo CD or Flux. Admission control enforcing signed images (Kyverno/policy-controller). Canary or blue-green delivery for tier-1 services. Automated rollback on health signals. Image digest pinning in all manifests. + +**Advanced** — Full SLSA provenance verification at admission. Zero standing credentials — all deploy identities are short-lived OIDC tokens. Progressive delivery with automated promotion gates (error rate, latency, security signals). Configuration drift detection and auto-remediation. Deployment decisions logged to an immutable audit store. + +## Metrics and KPIs + +- **Deployment frequency** — higher frequency with stable failure rates indicates a healthy deployment process. +- **Change failure rate** — percentage of deployments causing incidents or rollbacks; security-related failures tracked separately. +- **Mean time to restore (MTTR)** — time from a bad deployment detection to rollback completion. +- **Policy violation blocks at admission** — number of deployments rejected by admission control; should reach zero as teams fix upstream processes. +- **Percentage of workloads with digest-pinned images** — target 100% for production. + +--- + +## Tools[^1] + +### Open-source + +- [Argo CD](https://argo-cd.readthedocs.io/) — Declarative GitOps continuous delivery for Kubernetes; provides a UI dashboard for deployment status, drift detection, and rollback. +- [Argo Rollouts](https://argoproj.github.io/rollouts/) — Progressive delivery controller for Kubernetes: canary, blue-green, and automated analysis-based promotion. +- [Flux](https://fluxcd.io/) — GitOps toolkit for keeping clusters in sync; lightweight and composable; strong multi-tenancy and multi-cluster support. +- [Kyverno](https://kyverno.io/) — Kubernetes admission policy engine including image signature verification, resource validation, and mutation; no Rego required. +- [Sigstore policy-controller](https://github.com/sigstore/policy-controller) — Enforces cosign image signature and attestation policies at Kubernetes admission; integrates with Fulcio and Rekor. +- [External Secrets Operator](https://external-secrets.io/) — Syncs secrets from external vaults (AWS, GCP, Azure, Vault) into Kubernetes Secrets; avoids storing secrets in git. + +### Commercial + +- [Harness](https://www.harness.io/) — CI/CD and progressive delivery with built-in governance policies, approval workflows, and audit trails. +- [Octopus Deploy](https://octopus.com/) — Release management and deployment automation with environment promotion gates and change management integration; strong for non-Kubernetes workloads. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md b/current-version/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md index 0ce6742..faaeedc 100644 --- a/current-version/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md +++ b/current-version/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md @@ -1,3 +1,131 @@ -# Cloud Native Security +# Cloud-Native Security (CNAPP) - +Once software is deployed, security shifts from preventing flaws to **detecting and containing** threats in a live, dynamic environment. Cloud-native applications — containers, Kubernetes, serverless, and managed cloud services — change constantly and span many layers, which traditional perimeter tools cannot cover. The industry has converged on the **Cloud-Native Application Protection Platform (CNAPP)**: a unified approach that brings posture management and runtime protection together across code, cloud, and workloads. + +## What CNAPP brings together + +CNAPP consolidates capabilities that used to be separate products: + +| Capability | What it does | Why it matters | +|---|---|---| +| **CSPM** (Cloud Security Posture Management) | Continuously checks cloud configuration for misconfigurations and compliance drift | Catches S3 bucket ACL changes, security group drift, IAM privilege accumulation | +| **KSPM** (Kubernetes Security Posture Management) | Posture management for Kubernetes clusters, namespaces, and workloads | Detects missing Pod Security Standards, exposed dashboards, overprivileged service accounts | +| **CWPP** (Cloud Workload Protection Platform) | Protects running workloads — containers, VMs, functions — with threat detection | Detects cryptomining, reverse shells, lateral movement inside running containers | +| **CIEM** (Cloud Infrastructure Entitlement Management) | Analyzes and right-sizes cloud identities and permissions | Surfaces IAM roles with `*:*` permissions, stale credentials, cross-account privilege paths | +| **CDR** (Cloud Detection and Response) | Correlates signals into attack storylines and drives response | Connects a failed authN attempt to a subsequent privilege escalation to a data exfil | + +By correlating signals across these layers — and back to code — CNAPP prioritizes the risks that are genuinely exploitable rather than treating every finding equally. + +## Runtime protection essentials + +### Threat detection with eBPF + +Modern runtime protection uses **eBPF** (extended Berkeley Packet Filter) to attach observers to the Linux kernel without loadable kernel modules, providing: +- Full syscall visibility at near-zero overhead. +- Process lineage: which parent spawned which child, with what arguments. +- Network connection tracking: which process opened which socket to which destination. +- File access: reads/writes to sensitive paths (`/etc/shadow`, credential files, PKI directories). + +Falco uses eBPF to apply declarative rules against this stream: +```yaml +# Falco rule: detect shell spawned inside a container +- rule: Terminal Shell in Container + desc: A shell was used as the entrypoint or is run interactively in a container + condition: > + spawned_process and container + and proc.name in (shell_binaries) + and proc.tty != 0 + output: > + Shell opened in container (user=%user.name container=%container.name + image=%container.image.repository:%container.image.tag + proc=%proc.name cmdline=%proc.cmdline) + priority: WARNING +``` + +### Network policy and zero trust + +Default Kubernetes networking allows any pod to talk to any pod on any port. Apply default-deny network policies immediately: + +```yaml +# Default deny all ingress and egress — apply per namespace +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-deny-all +spec: + podSelector: {} + policyTypes: [Ingress, Egress] +``` + +Then add explicit allow rules for required communication paths only. Use a service mesh (Istio, Linkerd) for mTLS between services and fine-grained L7 policy. + +### Drift detection + +Alert when the running state diverges from the declared, reviewed GitOps state: +- A Kubernetes admission controller prevented a bad deploy — but a manual `kubectl exec` that modifies a running container is drift. +- IaC defined a security group — but an operator added an inbound rule in the console. CSPM catches this and alerts. +- Detect file integrity changes inside containers (writes to binary directories, new executables) as indicators of compromise. + +### Workload identity + +Static secrets embedded in workloads are a persistent attack surface. Use platform-native workload identity instead: +- **AWS IRSA** (IAM Roles for Service Accounts) — Kubernetes pods assume AWS IAM roles via short-lived OIDC tokens; no AWS access keys stored anywhere. +- **GCP Workload Identity Federation** — analogous for GCP services. +- **SPIFFE/SPIRE** — standards-based workload identity for cross-cloud and non-cloud workloads; issues short-lived X.509 SVIDs. + +## Closing the loop + +Runtime findings should not stay in operations — feed them back into [Vulnerability Management](2-7-4-Vulnerability-Management.md) and [ASPM](../../3-Governance/3-3-Reporting/3-3-3-ASPM.md) so production context (what is actually exposed, reachable, and under active attack) informs how earlier-stage findings are prioritized. This runtime-to-code feedback loop is the essence of "shift everywhere": + +- A CVE in a container image is critical if that image is running in a production cluster and the vulnerable component is reachable from the internet. +- The same CVE in an image never pulled is informational. +- Runtime detection of exploitation confirms that a theoretical finding is a real incident. + +## Common pitfalls and anti-patterns + +- **Alert fatigue from untuned CSPM** — a fresh CSPM deployment against a brownfield cloud environment produces thousands of findings. Start with critical and high severity; establish a remediation SLA before enabling more rules. +- **Agent deployed but findings never acted on** — runtime security is only valuable if findings trigger a response. Connect Falco or CWPP alerts to your SIEM/SOAR incident workflow from day one. +- **Network policies without testing** — a misconfigured network policy can break service communication silently. Test policies in staging with realistic traffic before enforcing in production. +- **CNAPP replacing application security** — CNAPP covers infrastructure and workload posture; it does not replace SAST, SCA, or code review. They are complementary layers. +- **Overly broad CIEM remediation** — removing cloud permissions without understanding dependencies can break production services. Use CIEM's "last used" data to identify safe removals and test in staging. + +## Maturity progression + +**Starter** — Deploy CSPM (Prowler or cloud-native Security Hub/Security Center). Enable Falco in your Kubernetes cluster with default rules. Apply default-deny network policies per namespace. Migrate from static credentials to IRSA/Workload Identity. + +**Intermediate** — Tune CSPM to remove false positives; achieve < 20 open high/critical findings. Falco alerts route to SIEM. Drift detection enabled. CIEM analysis run quarterly to right-size IAM. eBPF-based runtime agent deployed to all nodes. + +**Advanced** — Full CNAPP platform correlating CSPM + CWPP + CIEM + CDR signals. Runtime context feeds ASPM for application-level risk prioritization. Automated remediation for common CSPM findings (Lambda closes public S3 ACLs). SPIFFE/SPIRE for workload identity across multi-cloud. Active red team exercises validate detection coverage. + +## Metrics and KPIs + +- **CSPM critical/high open finding count** — track per cloud account; define remediation SLAs. +- **Mean time to detect (MTTD)** — time from anomalous runtime event to alert generation. +- **Mean time to respond (MTTR)** — time from alert to containment action. +- **Percentage of workloads using workload identity (no static credentials)** — target 100%. +- **Network policy coverage** — percentage of namespaces with explicit network policies applied. +- **IAM permissions reduction** — percentage decrease in unused permissions removed by CIEM-driven remediation. + +--- + +## Tools[^1] + +### Open-source + +- [Falco](https://falco.org/) — CNCF runtime security engine that detects anomalous behavior using eBPF/kernel events; extensive rule library and active community; integrates with SIEM, Slack, and SOAR platforms. +- [Kubescape](https://github.com/kubescape/kubescape) — Kubernetes posture management and compliance scanning against NSA/CISA, CIS, and MITRE ATT&CK frameworks; developer-friendly CLI and IDE integrations. +- [Trivy Operator](https://github.com/aquasecurity/trivy-operator) — Continuous vulnerability and misconfiguration scanning inside clusters; generates VulnerabilityReport and ConfigAuditReport CRDs that integrate with dashboards. +- [Wazuh](https://wazuh.com/) — Open-source security platform with threat detection, file integrity monitoring, and SIEM-like capabilities; useful for VM workloads alongside container-focused tools. +- [Cilium](https://cilium.io/) — eBPF-based networking and security for Kubernetes; provides network policy enforcement at L3/L4/L7, hubble observability, and transparent mTLS encryption. + +### Commercial + +- [Prisma Cloud](https://www.paloaltonetworks.com/prisma/cloud) — Full CNAPP covering CSPM, CWPP, CIEM, and code security in a single platform; strong compliance reporting for regulated industries. +- [Sysdig Secure](https://sysdig.com/products/secure/) — Runtime security and CNAPP built on Falco; adds policy management, incident response, and CSPM to open-source Falco. +- [Wiz](https://www.wiz.io/) — Agentless CNAPP for cloud posture and risk prioritization; graph-based attack path analysis that connects misconfiguration to blast radius without requiring agents. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md b/current-version/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md index 11a3b0e..d305586 100644 --- a/current-version/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md +++ b/current-version/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md @@ -1,3 +1,140 @@ -# Logging and-Monitoring +# Logging and Monitoring - +You cannot respond to what you cannot see. Security logging and monitoring provide the visibility needed to detect attacks, investigate incidents, and prove what happened. [OWASP](https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/) ranks logging and monitoring *failures* in its Top 10 precisely because so many breaches go undetected for months due to inadequate telemetry. The average time between a breach and its detection has been measured in months — logging is what shortens that window. + +## What to log + +Capture the events needed to detect and reconstruct security-relevant activity: + +- **Authentication and authorization** — logins (success and failure), MFA events, privilege escalations, access denials, token issuance and revocation. +- **Input and validation failures** — malformed requests, schema violations, and application errors that may signal probing or injection attempts. +- **Administrative and configuration changes** — who changed what system configuration, and when. +- **Access to sensitive data and functions** — reads of PII or financial records, use of admin APIs, bulk data exports. +- **Security tooling output** — WAF blocks, IDS/IPS alerts, runtime detection events from Falco, cloud trail events. +- **Session lifecycle** — session creation, expiry, and invalidation. +- **Deployment events** — who deployed what to which environment, from which pipeline run. + +Equally important is what *not* to log: never log secrets, passwords, tokens, session cookies, credit card numbers, or unnecessary personal data. Apply privacy-aware logging practices and align with [Data Protection](../../3-Governance/3-2-Data-protection.md). Log categories, not values, for sensitive fields. + +## Structured logging + +Plain-text logs are difficult to query, correlate, and parse reliably. Adopt structured logging from the start: + +```json +{ + "timestamp": "2025-06-27T14:32:11.452Z", + "level": "WARN", + "event": "auth.login_failed", + "user_id": "u-8421", + "ip": "203.0.113.42", + "user_agent": "Mozilla/5.0 ...", + "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", + "reason": "invalid_password", + "attempt_count": 4 +} +``` + +Key practices: +- Consistent event names across services (using a taxonomy like `noun.verb`). +- Correlation IDs (`trace_id`, `request_id`) that flow through the entire request chain for end-to-end reconstruction. +- UTC timestamps with millisecond precision. +- Contextual fields (user, IP, tenant, session) on every security-relevant event. + +## Make logs trustworthy + +- **Centralize** — aggregate logs from all services, infrastructure, and cloud APIs into a single platform so they can be correlated. Siloed logs cannot detect multi-stage attacks. +- **Tamper-resistant** — write logs to a separate, append-only destination that application credentials cannot modify. An attacker who compromises the app should not be able to erase evidence. +- **Retained sufficiently** — keep logs long enough to investigate slow-burning incidents and meet compliance requirements (PCI DSS requires 12 months; many regulations require at least 6). Hot retention (searchable) for 90 days; cold retention for compliance period. +- **Accurate timestamps** — synchronize clocks across all systems via NTP. A 1-second skew makes incident timelines ambiguous; a 1-minute skew makes them unreliable. +- **Ingestion monitoring** — alert on log gaps (a service that stops logging may have crashed or been tampered with). + +## From logging to detection and response + +### SIEM and detection-as-code + +A SIEM aggregates logs and runs detection rules against them to produce actionable alerts. Modern best practice is **detection-as-code**: write, test, and version-control detection rules exactly like application code. + +```yaml +# Example Sigma rule: brute-force login detection +title: Multiple Failed Logins from Same IP +status: stable +logsource: + category: application + product: custom-app +detection: + selection: + event: auth.login_failed + timeframe: 5m + condition: selection | count(user_id) by ip > 10 +falsepositives: + - Automated testing environments +level: high +tags: + - attack.credential_access + - attack.t1110 +``` + +[Sigma](https://github.com/SigmaHQ/sigma) is the vendor-neutral format; rules translate to Splunk SPL, Elastic KQL, and other query languages automatically. + +### MITRE ATT&CK mapping + +Map detection rules to [MITRE ATT&CK](https://attack.mitre.org/) technique IDs. This allows you to: +- Visualize coverage gaps on the ATT&CK Navigator. +- Prioritize new detection rules against the most likely attack techniques for your environment. +- Speak a common language with threat intelligence and incident response teams. + +### Alerting quality + +An alert that nobody can act on is worse than none — it trains the team to ignore alerts. Every alert must: +- Be actionable: the on-call person knows what to do in response. +- Be specific enough to investigate: contains sufficient context (user, IP, affected resource, event sequence). +- Be calibrated: false positive rate below 15% for critical alerts; tune aggressively. +- Link to a runbook that documents the investigation and response procedure. + +## Common pitfalls and anti-patterns + +- **Logging everything at DEBUG level in production** — creates noise, fills storage, and makes sensitive data harder to redact. Use structured severity levels; log `INFO` for normal events and `WARN`/`ERROR` for anomalies. +- **No log forwarding verification** — teams assume logs are shipping but never verify. Monitor log ingestion volume; alert on drops. +- **Uncontextualized alerts** — an alert that says "login failure detected" with no user, IP, or count is uninvestigatable. Every alert needs context. +- **Treating SIEM as a search engine** — storing logs in a SIEM but only using it to query after an incident is called "detect and do nothing." Invest in proactive detection rules. +- **Clock skew across services** — distributed systems with unsynchronized clocks produce impossible timelines. Enforce NTP for every host. + +## Maturity progression + +**Starter** — Centralize application and infrastructure logs to a single platform. Ensure authentication events are captured. Set 90-day retention. Create two or three high-value detection rules (brute force, privilege escalation, known-bad IPs). + +**Intermediate** — Structured logging with correlation IDs across all services. Detection-as-code with rules in version control. MITRE ATT&CK coverage map. Alert runbooks for every production alert. Tamper-resistant log storage. + +**Advanced** — Full observability stack (logs + metrics + traces). Sigma rule library with CI-tested rules. Automated anomaly detection (ML-based baselines). SOAR playbooks for automated first-response. Regular detection coverage reviews using BAS (see [BAS](2-7-6-Breach-and-attack-simulation.md)). Compliance-aligned retention and access control audit trails. + +## Metrics and KPIs + +- **Mean time to detect (MTTD)** — time from attack start to alert firing; target decreasing over time. +- **Alert-to-incident conversion rate** — percentage of alerts that are real incidents (higher means better tuned detection). +- **False positive rate** — per rule; rules exceeding 15% FP should be revised or suppressed. +- **MITRE ATT&CK coverage** — percentage of relevant techniques with at least one detection rule. +- **Log ingestion gap incidents** — number of times a service stopped shipping logs before it was noticed. + +--- + +## Tools[^1] + +### Open-source + +- [Grafana + Loki](https://grafana.com/oss/loki/) — Log aggregation and visualization; Loki indexes metadata (labels), not full text, making it cost-efficient at scale; best when paired with the Grafana observability stack. +- [OpenSearch](https://opensearch.org/) — Search, analytics, and log analysis suite (AWS-maintained Elasticsearch fork); strong query capabilities and Dashboards UI; good for teams already using Elasticsearch. +- [Prometheus](https://prometheus.io/) — Metrics-based monitoring and alerting; pair with Grafana for dashboards; does not handle logs (use with Loki for full observability). +- [Sigma](https://github.com/SigmaHQ/sigma) — Open standard for detection rules; write once, compile to any SIEM query language. +- [Wazuh](https://wazuh.com/) — Open-source SIEM with threat detection, file integrity monitoring, vulnerability detection, and compliance dashboards. + +### Commercial + +- [Datadog](https://www.datadoghq.com/) — Observability and security monitoring platform; unified logs, metrics, traces, and Security Monitoring in one; excellent developer experience. +- [Elastic Security](https://www.elastic.co/security) — SIEM and analytics on the Elastic Stack; large rule library; supports Sigma rule import; strong for teams already invested in the Elastic ecosystem. +- [Splunk](https://www.splunk.com/) — Log analytics and SIEM at scale; mature SPL query language; extensive integration ecosystem; higher cost but industry-standard for large enterprises and regulated industries. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-7-Operate/2-7-3-Pentest.md b/current-version/2-Process/2-7-Operate/2-7-3-Pentest.md index 3d95c6b..2d63678 100644 --- a/current-version/2-Process/2-7-Operate/2-7-3-Pentest.md +++ b/current-version/2-Process/2-7-Operate/2-7-3-Pentest.md @@ -1,98 +1,132 @@ -# Penetration Test +# Penetration Testing -A penetration test, or pen test, is a simulated attack on systems and applications to identify exploitable vulnerabilities. It involves testing web and mobile applications, APIs, network devices, workstations, servers and more, uncovering issues like SQL injection, code injection, XSS and privilege escalation. +Penetration testing is an authorized, simulated attack against a system to find and exploit vulnerabilities the way a real adversary would. Where automated scanners ([SAST](../2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md), [DAST](../2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md)) find known patterns, skilled pentesters find **business-logic flaws, chained exploits, and creative attack paths** that tools cannot. Pentesting validates that defenses work against a thinking attacker, not just against a known signature library. -While penetration testers use automated tools for scanning and information gathering, most testing is conducted manually. Manual testing is crucial for detecting vulnerabilities related to business logic and other issues that automated scans might miss. +## Types and scope -Penetration testing can be conducted during the testing phase of the software development lifecycle, ensuring vulnerabilities are addressed before the application is deployed. It can also be performed after the application is in production to identify and mitigate security risks in a live environment, ensuring ongoing protection against emerging threats. Doing it early on in the development process may depend on how mature the organization is. +| Type | Knowledge | When to use | +|---|---|---| +| Black-box | None — external attacker simulation | Assessing the external perimeter as an unauthenticated attacker would see it | +| Grey-box | Partial (credentials, architecture docs) | Most common; cost-effective balance between depth and realism | +| White-box | Full (source, infra, architecture) | Deepest technical review; maximum coverage; often used for critical systems pre-launch | -## Methodologies and Checklists +By target: +- **Web application** — OWASP Top 10, authentication/authorization, business logic, API surfaces. +- **Mobile** — OWASP MAS (MASVS/MASTG), client-side storage, traffic interception, reverse engineering. +- **API** — OWASP API Security Top 10, BOLA/IDOR, rate limiting, schema validation. +- **Cloud and infrastructure** — IAM misconfigurations, privilege escalation paths, network segmentation. +- **Social engineering** — phishing, vishing, physical (if scoped); tests the human layer. -A penetration test can be approached in three ways: black-box, gray-box, or white-box. +**Define scope, rules of engagement, and authorization clearly and in writing before any testing begins.** A "get out of jail free" letter signed by the authorizing executive protects both the testing team and the organization. -- **Black-box:** Testers have no prior information about the application, except possibly an IP address or domain. -- **Gray-box:** Testers are given additional information, such as credentials for test accounts. This approach balances cost and effectiveness, providing deeper insights without the high expense of white-box testing. It should be the preferred approach most of the time. -- **White-box:** Testers have full access to all information about the asset being tested, including the application's source code. +## Methodologies -Regardless of the approach, penetration testers will generally follow publicly-available and/or internal checklists and testing guides. The most popular ones are: +Structured methodologies make tests repeatable, defensible, and comprehensive: -- [OWASP Web Security Testing Guide (WSTG)](https://owasp.org/www-project-web-security-testing-guide/) - A comprehensive guide to testing the security of web applications and web services. -- [OWASP Mobile Application Security Testing Guide (MASTG)](https://mas.owasp.org/MASTG/) - Similar to the OWASP WSTG, it is a comprehensive guide to testing mobile applications. -- [OWASP Top 10](https://owasp.org/www-project-top-ten/) - Most common and impactful web application security vulnerabilities. -- [OWASP Top 10 API](https://owasp.org/API-Security/editions/2023/en/0x11-t10/) - Most common security risks and vulnerabilities for APIs. -- [OWASP Mobile Top 10](https://owasp.org/www-project-mobile-top-10/) - A list containing the most common and impactful mobile application security vulnerabilities. +| Methodology | Best for | +|---|---| +| [OWASP WSTG](https://owasp.org/www-project-web-security-testing-guide/) | Web application testing | +| [OWASP MASTG](https://mas.owasp.org/) | Mobile application testing | +| [OWASP API Security](https://owasp.org/API-Security/) | REST/GraphQL API testing | +| [PTES](http://www.pentest-standard.org/) | Full-scope penetration tests with pre- and post-engagement phases | +| [OSSTMM](https://www.isecom.org/OSSTMM.3.pdf) | Rigorous, metrics-based security testing across channels | +| [TIBER-EU](https://www.ecb.europa.eu/paym/cyber-resilience/tiber-eu/html/index.en.html) | Threat intelligence-led red team exercises for financial institutions | -## Process Overview +## Pentest vs red teaming vs purple teaming -### Assembling the team +| Exercise | Objective | Stealth | Blue team aware? | +|---|---|---|---| +| Penetration test | Find as many vulnerabilities as possible in scope | No — speed over stealth | Usually (announced) | +| Red team | Test detection and response against realistic adversary objectives | Yes — stealth is part of the test | No (unannounced) | +| Purple team | Improve detection and response collaboratively | No — works with the blue team | Yes (collaborative) | -The composition of the penetration testing team is very important. It can either consist of: +Red teaming goes beyond vulnerability finding — it tests whether the organization would detect and respond to a real attacker pursuing a specific objective (e.g., "exfiltrate customer data"). See [Breach and Attack Simulation](2-7-6-Breach-and-attack-simulation.md) for continuous coverage between exercises. -- **Internal:** cybersecurity professionals who understand the organization's systems and policies intimately. -- **External:** third-party hired for their specialized skills and objectivity, which can bring fresh perspectives and expertise in identifying vulnerabilities that internal teams might overlook. +## Running an effective pentest engagement -### Defining a scope +### Scoping -After assembling the penetration testing team, the organization must meticulously define the scope of the test. This step is critical to avoid deviations from the planned objectives or unintended testing of additional assets and endpoints. Scope definition entails: +- Define target systems, IP ranges, domains, and explicit exclusions. +- Specify what types of attacks are permitted (exploitation, DoS, social engineering, physical). +- Agree on data handling: what happens to credentials or data discovered during testing. +- Agree on communication protocols: how critical findings are reported immediately vs. in the final report. -- Decide between black-box, gray-box, or white-box methodologies. -- Establish clear timelines for the testing phases. -- Define which systems and endpoints will undergo testing. -- Decide whether tests will occur in production, staging, or other environments. -- Define the requirements - e.g. testing accounts, credentials, documentation, etc. +### Pre-engagement information gathering -### Requirements +Before active testing: +- Architecture diagrams, data flow diagrams, and threat models if available (white/grey-box). +- Previous pentest reports and remediation status. +- Known high-risk areas or recent changes the team wants prioritized. -Once the scope and dates are defined, the penetration testing team will communicate their requirements to the organization. These may include testing credentials, application documentation, source code access and other necessary resources. It is crucial for the organization to promptly provide all requested information and access before testing begins to ensure a smooth and effective penetration testing process. +### During the engagement -### Execution +- Regular check-ins to confirm scope and raise critical findings immediately (do not wait for the final report). +- Document all steps taken — reproduction steps are as important as the findings themselves. +- Follow rules of engagement strictly; escalate ambiguous situations before acting. -After receiving the necessary requirements, such as credentials and documentation, the penetration testing team will begin assessing the system or application. It is crucial for the penetration testing team to: +### Reporting -- Notify the organization immediately if their tests cause any disruption to a system, especially if it is in production, to mitigate potential impacts on business operations. -- Report any critical vulnerabilities discovered promptly to the organization, as these could have significant financial and/or reputational consequences, allowing for swift remediation and risk management. -- If the penetration testing team finds any indicators of compromise (IoC) that an incident may have happened, they must notify the organization immediately. +A good pentest report contains: +- **Executive summary** — risk posture, critical findings, business impact in non-technical language. +- **Technical findings** — for each issue: description, evidence/screenshot/PoC, CVSS score, business impact, remediation steps. +- **Prioritized remediation roadmap** — ordered by risk, with suggested owner and timeline. +- **Positive findings** — controls that worked; what the testers could not bypass. -### Reporting +## Continuous and modern approaches + +Annual pentests no longer match continuous delivery — a feature shipped the day after a pentest has been untested for almost a year. Complement manual pentests with: + +- **PTaaS (Penetration Testing as a Service)** — platforms like Cobalt, Synack, and HackerOne connect organizations with vetted pentesters on demand, with continuous engagement models and integrated finding management. +- **Automated continuous testing** — tools like Pentera or Horizon3 run automated exploitation tests continuously between manual engagements to catch regression. +- A tight **remediation loop** — findings flow into [Vulnerability Management](2-7-4-Vulnerability-Management.md) with named owners and SLAs; retesting by the original pentesters (or an independent reviewer) confirms fixes. A finding closed without retest is a finding with unknown status. + +## Common pitfalls and anti-patterns + +- **Pentesting without remediating** — a pentest that produces a report that sits unactioned is a compliance exercise, not a security improvement. Commit to remediation SLAs before the engagement. +- **Scope too narrow** — testing only the front-end while skipping APIs, admin panels, and cloud infrastructure misses the majority of modern attack surface. +- **No retesting** — remediations are often incomplete or introduce new bugs. Always include a retest phase in the engagement scope. +- **Annual only** — a once-a-year pentest against a system that ships 50 releases per year is not sufficient coverage. Supplement with PTaaS and automated testing. +- **Findings not prioritized by exploitability** — a list of 40 findings sorted by CVSS score alone does not help defenders decide what to fix first. Add business impact, exploitability, and reachability context. + +## Maturity progression + +**Starter** — Annual grey-box web application pentest by a qualified firm. Findings tracked in the vulnerability management system. Remediation of critical/high findings within 30 days. -Upon completing all tests, the penetration testing team will begin compiling a comprehensive report. This report should be structured as follows: - -- Cover -- Table of Contents -- Executive Summary -- General Information - - Penetration Testing Team - - Methodology - - Scope -- Vulnerabilities - - Title - - Severity - - Description - - Proof of Concept (with screenshots) - - Impact - - Mitigation - - References -- Conclusion - -### Retesting - -Lastly, after delivering the report and initiating the vulnerability management process, the penetration testing team will retest all vulnerabilities that developers consider fixed. This retesting ensures that each vulnerability has been successfully addressed and that no bypasses to the newly implemented security controls exist. +**Intermediate** — Annual pentest for all tier-1 applications. PTaaS for continuous coverage of critical apps. Remediation loop with retesting included in scope. Pentest findings feed the SAST/DAST rule tuning process. + +**Advanced** — Annual red team exercise testing detection and response. PTaaS with a rotating researcher pool for fresh perspective. Automated continuous exploitation testing (Pentera/Horizon3). Purple team collaboration to improve SIEM detection rules based on pentest findings. Pentest coverage metrics by application tier. + +## Metrics and KPIs + +- **Critical/high findings per pentest** — track trend; declining findings indicate improving security posture. +- **Mean time to remediate pentest findings** — by severity tier; compare against SLA. +- **Retest pass rate** — percentage of fixed findings confirmed closed by the tester; low rate indicates incomplete fixes. +- **Coverage rate** — percentage of tier-1 applications that have been pentested in the last 12 months. +- **Findings that were missed by automated tools** — quantifies the value of manual testing vs. scanner-only approach. --- ## Tools[^1] -- [BurpSuite](https://portswigger.net/burp) - A comprehensive software tool used for web application security testing. Key features include a proxy for intercepting and modifying web traffic, a scanner for automated vulnerability detection and tools for performing manual testing, such as repeater, intruder and so forth. -- [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF) - Automated, open-source tool for security testing and analyzing mobile applications, supporting both Android and iOS platforms. -- [Postman](https://www.postman.com/) - API testing tool that allows sending various HTTP requests, manipulating headers and automating tests. It helps identify vulnerabilities like authentication issues and data exposure, integrating with other security tools for comprehensive analysis. -- [Zed Attack Proxy (ZAP)](https://www.zaproxy.org) - An open-source web proxy similar that has features similar to BurpSuite's. +### Open-source + +- [BloodHound](https://github.com/SpecterOps/BloodHound) — Maps attack paths in Active Directory and cloud identity (Azure/AWS); essential for assessing privilege escalation and lateral movement paths. +- [Burp Suite Community](https://portswigger.net/burp) — Web security testing proxy and toolkit; intercepts, modifies, and replays HTTP/S traffic; industry standard for web application testing. +- [Metasploit Framework](https://github.com/rapid7/metasploit-framework) — Exploitation framework with a large module library; used for post-exploitation, lateral movement, and payload generation. +- [Nmap](https://nmap.org/) — Network discovery, port scanning, and service enumeration; the starting point for almost every infrastructure engagement. +- [OWASP ZAP](https://www.zaproxy.org/) — Web application scanning and manual testing proxy; open-source alternative to Burp for intercepting and scanning web traffic. +- [SQLmap](https://github.com/sqlmapproject/sqlmap) — Automated SQL injection detection and exploitation; used to confirm and exploit injection findings. +- [ffuf](https://github.com/ffuf/ffuf) — Fast web fuzzer for directory/file discovery, virtual host enumeration, and parameter fuzzing. + +### Commercial + +- [Burp Suite Professional](https://portswigger.net/burp/pro) — Advanced web application penetration testing; adds active scanner, Collaborator (out-of-band detection), and advanced automation to the Community edition. +- [Cobalt](https://www.cobalt.io/) — Pentest-as-a-Service platform with a curated researcher network, integrated finding management, and API-driven workflow. +- [Synack](https://www.synack.com/) — PTaaS with a vetted, full-time researcher community; strong on financial services and government compliance requirements. +- [Pentera](https://www.pentera.io/) — Automated, continuous penetration testing for network and cloud environments; runs continuously rather than on engagement cycles. --- ### Links -- [Awesome Penetration Testing](https://github.com/enaqx/awesome-pentest) -- [OWASP Penetration Testing Methodologies](https://owasp.org/www-project-web-security-testing-guide/latest/3-The_OWASP_Testing_Framework/1-Penetration_Testing_Methodologies) -- [The Penetration Testing Execution Standard (PTES)](http://www.pentest-standard.org/index.php/Main_Page) - [^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md b/current-version/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md index 61b4345..27d440b 100644 --- a/current-version/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md +++ b/current-version/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md @@ -1,3 +1,113 @@ # Vulnerability Management - +Every stage of the pipeline produces findings — SAST, SCA, container, IaC, DAST, pentest, runtime, and bug-bounty reports. Without a process to collect, prioritize, and drive them to closure, these findings pile up faster than they can be fixed. **Vulnerability management** is the continuous lifecycle that turns a flood of raw findings into a manageable, risk-prioritized workflow. + +## The lifecycle + +1. **Aggregate** — collect findings from all scanners and sources into one central platform. Every tool that generates findings must have an integration that prevents findings from staying siloed in tool-specific dashboards. +2. **Deduplicate and normalize** — the same CVE reported by Trivy, Grype, and Snyk is one issue, not three. Normalize severity, description, and CWE mappings across tools. +3. **Prioritize by risk** — rank by genuine risk, not just CVSS score (see below). The goal is to fix the right things first, not the most. +4. **Assign ownership** — route each issue to the team that can fix it, with a named owner, a due date, and a link to the ticket. Findings without owners do not get fixed. +5. **Remediate or accept** — fix, mitigate with a compensating control, or formally accept residual risk with justification and a time-boxed expiry. +6. **Verify** — retest or re-scan to confirm the fix. A closed finding without verification is an assumption. +7. **Report and learn** — track trends over time and feed insight back into the program: which tool finds the most exploited vulnerabilities? Which team has the highest remediation rate? + +## Risk-based prioritization + +CVSS severity alone causes teams to chase thousands of "critical" issues that are not actually exploitable in their environment. A CVSS 9.8 RCE vulnerability in a library that is never invoked is less urgent than a CVSS 6.5 SQL injection in a production-facing endpoint. Modern prioritization combines multiple signals: + +| Signal | What it adds | Source | +|---|---|---| +| **CVSS** | Base technical severity | NVD, vendor advisories | +| **EPSS** | Probability the CVE will be exploited in the wild (0–100%) | FIRST.org, updated daily | +| **CISA KEV** | Confirmed exploited in real attacks — fix these first | CISA Known Exploited Vulnerabilities | +| **Reachability** | Is the vulnerable code path actually called in your app? | SCA tools with call-graph analysis | +| **Runtime exposure** | Is the affected component loaded in a running production workload? | CNAPP/CSPM runtime context | +| **Asset criticality** | Is the affected service internet-facing, handling PII, or in the blast radius of a critical function? | Asset inventory / CMDB | + +The practical prioritization formula: **KEV > (EPSS > 0.5) > reachable critical > reachable high > unreachable critical > ...** + +This is the heart of [ASPM](../../3-Governance/3-3-Reporting/3-3-3-ASPM.md): correlating code-to-runtime context so teams fix what truly matters. + +## Remediation SLAs + +Define and enforce remediation timelines by risk tier: + +| Risk tier | Criteria | SLA | +|---|---|---| +| Critical | CVSS ≥ 9.0 OR KEV listed | 24 hours for mitigation, 7 days for full fix | +| High | CVSS 7.0–8.9 OR EPSS > 0.5 | 14 days | +| Medium | CVSS 4.0–6.9, reachable | 60 days | +| Low / informational | CVSS < 4.0 or unreachable | 90 days or next sprint | + +Track SLA adherence as a metric and escalate breaches to engineering management. SLAs without enforcement are aspirations, not commitments. + +## VEX: Vulnerability Exploitability eXchange + +Not every reported CVE is exploitable in your application. VEX allows you to formally document and communicate the exploitability status of each CVE in each of your products: + +- **Affected** — the vulnerable component is present and the vulnerable code path is reachable. +- **Not affected** — the CVE is present but not exploitable (e.g., the vulnerable function is not called, or a mitigating configuration is in place). +- **Fixed** — the fix has been applied. +- **Under investigation** — status not yet determined. + +VEX documents (in CycloneDX or OpenVEX format) can be attached to your SBOM and shared with customers, reducing downstream alert noise for vulnerabilities that do not affect them. + +## Automation and AI-assisted remediation + +- **Auto-ticket creation** — when a new high/critical finding is ingested, automatically create a Jira/GitHub issue, assign it to the owning team based on code ownership, and set the due date from SLA policy. +- **Dependency update PRs** — tools like Dependabot, Renovate, and Snyk Fix automatically open pull requests to update vulnerable dependencies to a patched version. +- **AI-assisted fix suggestions** — emerging AI agents can analyze a vulnerability, locate the affected code, draft a fix, and open a PR for human review. This significantly reduces the human effort required for known vulnerability patterns. +- **Auto-close on fix verification** — when a scanner no longer detects a finding in a new scan, automatically transition the ticket to "resolved pending verification" and route to a reviewer. + +## Make it operational + +- **Central dashboard** — give leadership and teams a single view of open vulnerabilities by severity, age, and team (see [Central Vulnerability Management Dashboard](../../3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md)). +- **Trending, not just snapshots** — track open finding counts over time. A program that is finding and fixing vulnerabilities will show a stable or declining trend even as new findings are discovered. +- **Exception register** — accepted risks are visible, time-boxed, and reviewed regularly. See [Security Gates](../2-3-Build/2-3-5-Security-Gates.md) for the exception process. + +## Common pitfalls and anti-patterns + +- **Prioritizing by CVSS alone** — without exploitability and reachability context, teams exhaust themselves on theoretical risks while genuine exposures go unpatched. +- **No ownership model** — findings that belong to "the security team" do not get fixed; they belong to the security team forever. Findings must be owned by the development team that can resolve them. +- **Alert fatigue from too many tools without deduplication** — five security tools reporting the same CVE five times creates the illusion of five separate problems and inflates finding counts. Deduplicate before routing. +- **SLAs without tracking** — defining SLAs and then never measuring adherence provides no accountability. Build SLA breach reports into weekly engineering reviews. +- **Re-opening without root-cause analysis** — when the same vulnerability recurs after being marked fixed, it indicates the remediation was superficial. Track recurrence as a metric and invest in root-cause fixes. + +## Maturity progression + +**Starter** — Centralize findings from SAST and SCA into DefectDojo. Apply CVSS-based SLAs. Assign findings to development teams. Track open critical/high counts weekly. + +**Intermediate** — Enrich findings with EPSS and KEV data for prioritization. Automated ticket creation and assignment by code ownership. VEX for the top 10 most-flagged false-positive CVEs. SLA adherence tracked and reported to leadership. + +**Advanced** — Full ASPM platform with code-to-runtime context. AI-assisted remediation PRs for known vulnerability patterns. Automated VEX generation from call-graph reachability analysis. Real-time SLA breach escalation. Vulnerability aging and recurrence analytics in the engineering KPI dashboard. + +## Metrics and KPIs + +- **Open critical/high finding count** — track over time; a declining trend indicates program health. +- **SLA adherence rate** — percentage of findings remediated within SLA by tier; target > 90% for critical. +- **Mean time to remediate (MTTR)** — by severity and by source (SAST vs SCA vs pentest vs runtime). +- **Escape rate** — findings discovered in production that were not caught earlier in the pipeline; indicates where earlier detection is needed. +- **Recurrence rate** — percentage of findings that reappear after being marked fixed; indicates superficial or incomplete remediation. + +--- + +## Tools[^1] + +### Open-source + +- [Faraday](https://github.com/infobyte/faraday) — Collaborative vulnerability management platform; aggregates findings from a wide range of security tools; suited for pentest-focused teams. +- [OWASP DefectDojo](https://www.defectdojo.org/) — Vulnerability aggregation, deduplication, and management; supports importers for 150+ scanner formats; widely used for DevSecOps pipeline integration. +- [OWASP Dependency-Track](https://dependencytrack.org/) — Continuous component vulnerability tracking from SBOMs in CycloneDX/SPDX format; evaluates every component against NVD, OSV, and GitHub Advisory databases. + +### Commercial + +- [Kenna / Cisco Vulnerability Management](https://www.cisco.com/site/us/en/products/security/vulnerability-management/index.html) — Risk-based vulnerability prioritization using EPSS and threat intelligence; strong for infrastructure vulnerability data from Tenable/Qualys. +- [Tenable](https://www.tenable.com/) — Vulnerability management and exposure platform; broad coverage from on-prem to cloud; Tenable One adds ASPM-like exposure management. +- [Vulcan Cyber](https://vulcan.io/) — Risk-based vulnerability orchestration and remediation; integrates fix intelligence from vendors and community sources to accelerate remediation. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-7-Operate/2-7-5-VDP-and-Bug-bounty.md b/current-version/2-Process/2-7-Operate/2-7-5-VDP-and-Bug-bounty.md new file mode 100644 index 0000000..4b7471a --- /dev/null +++ b/current-version/2-Process/2-7-Operate/2-7-5-VDP-and-Bug-bounty.md @@ -0,0 +1,131 @@ +# Vulnerability Disclosure and Bug Bounty + +No matter how strong your pipeline, external researchers and users will find issues you missed. The question is whether they have a **safe, clear way to tell you** — or whether they post it publicly, sell it, or stay silent. A Vulnerability Disclosure Program (VDP) and, optionally, a bug bounty program turn the outside security community into an extension of your defenses. + +## Vulnerability Disclosure Program (VDP) + +A VDP is the baseline: a published policy that invites anyone to report vulnerabilities and tells them how. It does not require financial incentives — it requires clarity and commitment. + +### Core components of a VDP + +**`security.txt`** — publish a standardized [security.txt](https://securitytxt.org/) file at `/.well-known/security.txt` so automated tools and researchers can find your contact and policy: + +``` +Contact: mailto:security@yourcompany.com +Expires: 2026-12-31T00:00:00.000Z +Acknowledgments: https://yourcompany.com/security/hall-of-fame +Policy: https://yourcompany.com/security/vulnerability-disclosure-policy +Preferred-Languages: en +``` + +**Clear policy** — a published disclosure policy must address: +- Scope: which systems, domains, and products are in scope and explicitly out of scope. +- How to report: encrypted email (PGP key), web form, or platform (HackerOne, Bugcrowd). +- What to expect: acknowledgment SLA, validation SLA, disclosure timeline. +- What is prohibited: destructive testing, social engineering, accessing others' data, DoS. + +**Safe harbor** — commit explicitly not to pursue legal action against researchers who discover and report vulnerabilities in good faith within the policy scope. Without safe harbor, researchers avoid reporting for fear of prosecution. Safe harbor is non-negotiable for a functional VDP. + +**Coordinated disclosure** — work with the reporter on a fix timeline before public disclosure. Industry standard is 90 days (Google Project Zero model). Communicate progress throughout. If you need more time, request it explicitly and explain why. + +**Triage SLAs** — define and meet response commitments: + +| Stage | Target SLA | +|---|---| +| Initial acknowledgment | 24–48 hours | +| Validation (is it real?) | 5 business days | +| Severity assessment | 5 business days | +| Status update cadence | Every 14 days until resolved | +| Resolution notification | Within 7 days of fix deployment | + +Nothing discourages researchers faster than silence. A VDP with poor triage is worse than no VDP — it creates expectations and then breaks them. + +### Legal and regulatory considerations + +VDPs are increasingly expected or required: +- [CISA](https://www.cisa.gov/resources-tools/resources/guidance-coordinated-vulnerability-disclosure-processes) recommends all US federal agencies maintain a VDP; many civilian agencies are required to. +- [ISO/IEC 29147](https://www.iso.org/standard/72311.html) covers vulnerability disclosure processes; [ISO/IEC 30111](https://www.iso.org/standard/69725.html) covers vulnerability handling. +- The EU Cyber Resilience Act will require coordinated vulnerability disclosure for products with digital elements. +- Many enterprise procurement processes now require suppliers to have a published VDP. + +## Bug bounty programs + +A bug bounty program adds **financial incentives** on top of a VDP, attracting more researchers and motivating them to pursue harder-to-find vulnerabilities. It is a significant step up in maturity — only run one once you can triage and remediate reliably at volume. + +### Readiness prerequisites + +Before launching a bug bounty: +- A working VDP with demonstrated SLA adherence. +- A vulnerability management system capable of handling a sustained inflow of reports. +- Dedicated triage capacity (internal security team or managed triage from the platform). +- Clear scope definitions and reproducible test environments for researchers. +- Legal review of the safe harbor language. + +### Program design + +**Private vs public** — start with a private program (invited, vetted researchers; controlled volume) before going public. A private program lets you calibrate triage capacity and scope before being exposed to the full researcher community. + +**Scope and reward table** — match rewards to severity and business impact: + +| Severity | Example | Reward range | +|---|---|---| +| Critical | Authentication bypass, RCE, data exfiltration | $5,000–$30,000+ | +| High | BOLA/IDOR affecting multiple accounts, stored XSS | $1,000–$5,000 | +| Medium | CSRF, reflected XSS, rate-limit bypass | $200–$1,000 | +| Low / informational | Missing headers, clickjacking, self-XSS | $0–$200 or recognition only | + +Reward levels vary significantly by industry and organization. Financial services and infrastructure companies typically pay more than consumer applications for equivalent severity. + +**Acknowledgment program** — a public hall of fame for researchers who report valid vulnerabilities, even without monetary rewards, is a meaningful incentive for many researchers. + +### Managing researcher relationships + +- Respond respectfully and promptly. Researcher communities are small and word travels fast. +- When you dispute a finding, explain clearly and provide technical detail. +- Pay promptly once a finding is validated and fixed. +- Consider giving bonus rewards for particularly creative or impactful findings. + +## Maturity progression + +**Starter** — Publish a `security.txt` and a simple VDP page with an email contact. Commit to 48-hour acknowledgment and 90-day disclosure. Designate an internal owner to handle reports. + +**Intermediate** — Migrate to a managed VDP platform for structured intake, triage tracking, and researcher communication. Formal scope definition. Documented triage SLAs. Acknowledgments page for researchers. + +**Advanced** — Private bug bounty with invited researchers. Dedicated triage (internal or managed). Reward table tied to severity and impact. VDP/bounty findings feed the vulnerability management pipeline and ASPM. Regular scope reviews to add new assets. Public bug bounty once private program is stable. + +## Common pitfalls and anti-patterns + +- **VDP with no safe harbor** — researchers will not report without legal protection. A policy that says "don't hack us" but offers no explicit safe harbor is not a VDP. +- **Slow or silent triage** — researchers who submit reports and receive no response for weeks will escalate publicly. SLA adherence is reputation management. +- **Scope too broad too soon** — a first VDP or bounty that covers everything creates unmanageable volume. Start narrow (e.g., one public-facing product) and expand as capacity allows. +- **Bug bounty as a replacement for internal security** — a bounty finds bugs; it does not fix the root causes. Without a strong internal security program, you will remediate the same classes of vulnerability repeatedly. +- **Not fixing bounty findings** — a bounty program that pays researchers but leaves findings unpatched for months destroys credibility with researchers and fails to improve security. + +## Metrics and KPIs + +- **Triage SLA adherence rate** — percentage of reports acknowledged and validated within SLA; target > 95%. +- **Valid report rate** — percentage of submitted reports that are confirmed valid vulnerabilities; low rate may indicate unclear scope or poor researcher targeting. +- **Mean time to remediate bounty findings** — by severity; compare to internal finding MTTR. +- **Total valid reports per quarter** — indicates researcher engagement and program health. +- **Critical/high findings from external researchers** — vulnerabilities found externally that were missed internally; a high number indicates gaps in the internal security program. + +--- + +## Tools[^1] + +### Open-source + +- [security.txt](https://securitytxt.org/) — RFC 9116 standard for a machine-readable security contact and disclosure policy file; minimal investment, immediate benefit. + +### Commercial + +- [Bugcrowd](https://www.bugcrowd.com/) — Crowdsourced bug bounty and VDP platform; managed triage services available; strong researcher community across web, mobile, and IoT. +- [HackerOne](https://www.hackerone.com/) — Vulnerability disclosure and bug bounty platform; largest researcher community; strong tooling for program management, SLA tracking, and integrations with Jira and Slack. +- [Intigriti](https://www.intigriti.com/) — European-based bug bounty and VDP platform; GDPR-aligned; strong European researcher community; growing global presence. +- [Synack](https://www.synack.com/) — Managed crowdsourced security with a vetted, full-time researcher pool; higher cost, higher signal-to-noise ratio; popular with financial services and government. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md b/current-version/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md index d5a01bf..296afd9 100644 --- a/current-version/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md +++ b/current-version/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md @@ -1,3 +1,110 @@ # Breach and Attack Simulation - +Having security controls is not the same as knowing they work. **Breach and Attack Simulation (BAS)** continuously and safely emulates real adversary techniques against your environment to validate whether your defenses actually detect and prevent them. Where a pentest is a point-in-time snapshot, BAS provides ongoing, automated assurance that controls have not silently drifted or broken. + +Security controls fail silently all the time: a SIEM rule that fired correctly six months ago may have stopped working after a logging format change; an EDR exclusion added to reduce false positives may have opened a detection gap; a new workload may have been deployed without the runtime agent. BAS surfaces these failures before adversaries do. + +## What BAS does + +- **Emulates adversary TTPs** — runs the tactics, techniques, and procedures (TTPs) real attackers use: from initial access and lateral movement to credential theft and data exfiltration. Techniques are executed safely — they demonstrate exploitation capability without causing actual damage. +- **Validates the detection and prevention stack** — does the EDR fire? Does the SIEM generate an alert? Does the WAF block the payload? Does the alert route to the right analyst? BAS answers these questions empirically and continuously. +- **Continuous coverage** — runs on a schedule (daily, weekly) or triggered by changes, catching regressions as environments, configurations, and detection rules change. +- **Maps to MITRE ATT&CK** — frames all results against the [MITRE ATT&CK](https://attack.mitre.org/) matrix so coverage gaps are visible by tactic, technique, and sub-technique. + +## BAS, pentest, and purple teaming + +| Method | Objective | Frequency | Driven by | +|---|---|---|---| +| Penetration testing | Find vulnerabilities | Annual / quarterly | Human testers | +| BAS | Validate controls detect/prevent known TTPs | Continuous | Automated platform | +| Purple teaming | Improve detection collaboratively | Quarterly / bi-annual | Red + blue together | +| Red teaming | Test detection and response to realistic goal-oriented attack | Annual | Human team | + +These are complementary: pentests find new weaknesses, BAS ensures the defenses you rely on keep working between pentests, and purple teaming accelerates detection improvement by having red and blue collaborate rather than operate in opposition. + +## The ATT&CK matrix as a coverage map + +The MITRE ATT&CK framework organizes adversary behavior into 14 tactics (from Reconnaissance to Impact) and hundreds of techniques. Use it as a coverage map: + +1. **Identify priority techniques** — based on threat intelligence relevant to your industry (e.g., financial services organizations face different TTPs than healthcare organizations). Threat reports from CISA, ENISA, and vendor intelligence teams identify which techniques are actively used against your sector. +2. **Run BAS tests** against priority techniques and record: detected, prevented, or neither. +3. **Visualize coverage** using ATT&CK Navigator (a free, web-based tool that color-codes the matrix by coverage status). +4. **Prioritize detection engineering** for undetected but in-use techniques. +5. **Repeat** — rerun after adding new detection rules to verify improvement. + +## Closing the loop + +BAS value is fully realized only when findings drive action: + +- **Undetected technique** → detection engineering task: write or tune a Sigma rule, add a Falco policy, or improve logging to capture the telemetry needed. +- **Detected but unalerted** → SIEM tuning: the event is in the log but no rule fires. Adjust thresholds or add the rule. +- **Alerted but not routed** → response workflow: the alert fires but no one picks it up within SLA. Fix the escalation path. +- **Blocked but not logged** → logging improvement: the control blocked the action but left no audit trail. Add the telemetry. + +Without this feedback loop, BAS becomes a metric-reporting exercise rather than a program-improvement engine. + +## Purple teaming with BAS tooling + +Purple teaming has red and blue operate together, with the red team executing techniques while the blue team watches their SIEM and endpoint consoles in real time. BAS platforms enable this at scale: + +1. Red executes an Atomic Red Team test or a BAS platform scenario. +2. Blue confirms detection in the SIEM and assesses alert quality (context, severity, suggested action). +3. Together they tune the detection rule if needed. +4. Test is re-executed to confirm the tuning works. + +This collaborative model produces dramatically faster detection improvement than annual red team exercises with a weeks-long reporting gap. + +## Running BAS safely + +- **Production environments** — run only safe, read-only, or reversible techniques. Simulate the intent (e.g., credential access) without actual credential dumping or data exfiltration. +- **Isolated environments** — run full exploitation chains in a staging environment that mirrors production to test deeper techniques. +- **Change management** — treat BAS runs as scheduled maintenance; notify the blue team so genuine alerts are not confused with simulated ones during non-purple team exercises. +- **Exclude production databases and PII systems** from any write or exfiltration simulations. + +## Common pitfalls and anti-patterns + +- **BAS as a reporting tool, not a detection-improvement engine** — generating ATT&CK coverage reports that never drive changes to detection rules is theater. Every undetected technique must create a ticket. +- **Running BAS without informing the blue team** — if the SOC investigates a BAS simulation as a real incident, it wastes response capacity. Coordinate schedules. +- **Only testing the EDR** — a comprehensive detection stack includes SIEM, cloud audit logs, network detection, and application logs. BAS coverage should span all telemetry sources. +- **Coverage = detected, not coverage = blocked** — a blocked technique with no detection telemetry is still a gap. You need both prevention and detection. +- **Ignoring persistence and lateral movement techniques** — many BAS programs focus on initial access techniques because they are easy to test. Lateral movement and persistence are where breaches do most of their damage. + +## Maturity progression + +**Starter** — Deploy Atomic Red Team and run 10–15 high-priority ATT&CK techniques against your endpoint environment. Check SIEM for alerts. Identify gaps. Create detection engineering tickets for undetected techniques. + +**Intermediate** — Schedule weekly automated BAS runs across priority techniques. ATT&CK Navigator coverage map reviewed monthly. Purple team session quarterly using BAS findings as the exercise agenda. Detection engineering backlog managed as a first-class project. + +**Advanced** — Continuous BAS across all environments (endpoint, cloud, network, application). Full ATT&CK technique coverage tracked as a quarterly KPI. Automated detection-engineering pipeline (BAS finding → Sigma rule proposal → peer review → deployment). BAS results inform threat intelligence prioritization. Annual threat-intelligence-led red team exercises validate detection coverage at the scenario level. + +## Metrics and KPIs + +- **ATT&CK technique detection rate** — percentage of tested techniques that generated an alert in the SIEM; track by tactic (e.g., lateral movement = 72%, exfiltration = 55%). +- **ATT&CK technique prevention rate** — percentage blocked by preventive controls (EDR, WAF, network policy). +- **Mean time to detect in BAS exercises** — time from technique execution to alert generation; a MTTD proxy using known events. +- **Detection engineering backlog size** — number of open "undetected technique" tasks; should be decreasing or stable. +- **Detection regression rate** — percentage of previously-detected techniques that are no longer detected (control degradation); should be zero between purple team sessions. + +--- + +## Tools[^1] + +### Open-source + +- [Atomic Red Team](https://github.com/redcanaryco/atomic-red-team) — Library of small, portable, peer-reviewed tests mapped to MITRE ATT&CK; easy to execute individually or automate at scale; the starting point for most BAS programs. +- [Caldera](https://github.com/mitre/caldera) — MITRE's automated adversary emulation platform; supports chained, goal-oriented attack scenarios; C2-like agent for more realistic lateral movement simulation. +- [Infection Monkey](https://github.com/guardicore/monkey) — Open-source breach and attack simulation tool focused on network traversal and lateral movement; good for testing network segmentation controls. +- [Stratus Red Team](https://github.com/DataDog/stratus-red-team) — Cloud-specific BAS: atomic attack techniques for AWS, Azure, GCP, and Kubernetes; fills the gap left by endpoint-focused tools. + +### Commercial + +- [AttackIQ](https://www.attackiq.com/) — Mature BAS platform with scenario library, ATT&CK coverage analytics, and integrations with major SIEM and EDR platforms; strong enterprise reporting. +- [Cymulate](https://cymulate.com/) — Continuous security validation and BAS across multiple attack surfaces: email, web, endpoint, cloud, lateral movement; good for broad coverage programs. +- [SafeBreach](https://www.safebreach.com/) — BAS across the full kill chain; scenario-based simulations aligned to threat intelligence feeds; strong for financial services and critical infrastructure. +- [Picus Security](https://www.picussecurity.com/) — BAS with a focus on actionable detection and prevention gap analysis; provides ready-made Sigma rules and SIEM queries for detected gaps. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md b/current-version/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md index b8bac01..2d769ef 100644 --- a/current-version/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md +++ b/current-version/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md @@ -1 +1,129 @@ # Compliance Auditing + +Compliance auditing demonstrates — to regulators, customers, and leadership — that your security controls exist, work, and are followed. In a DevSecOps context the goal is to make compliance a **byproduct of good engineering** rather than a separate, manual scramble before each audit. When controls are automated and evidence is generated continuously, audits become a query against existing data instead of a fire drill. + +## Common frameworks and regulations + +Most organizations map their controls to one or more of: + +- **SOC 2** — trust services criteria, common for SaaS. Requires evidence of access control, availability, and monitoring over a defined audit period (typically 12 months for Type II). +- **ISO/IEC 27001** — information security management system standard. Requires a risk-based approach and documented controls with ongoing review. +- **PCI DSS v4** — for handling payment card data. Highly prescriptive; now emphasizes continuous monitoring and customized implementation paths. +- **NIST SSDF (SP 800-218)** — secure software development practices; increasingly required for vendors selling to US federal agencies (per OMB M-23-16). +- **NIST 800-53** — comprehensive control catalog for federal and high-assurance environments. +- **HIPAA** — healthcare data; focuses on PHI safeguards, breach notification, and business associate agreements. +- **GDPR / PIPEDA / LGPD** — privacy-first regulations governing personal data of EU, Canadian, and Brazilian residents (see [Data Protection](../3-2-Data-protection.md)). +- **EU Cyber Resilience Act (CRA)** — security requirements for products with digital elements, including SBOMs and vulnerability disclosure obligations by 2027. +- **FedRAMP** — US federal cloud authorization, based on NIST 800-53 with strict continuous monitoring requirements. + +## Continuous compliance vs. point-in-time audit + +The traditional audit model is point-in-time: an auditor arrives, requests evidence for the past 12 months, and assesses controls as of the audit date. Controls can pass an annual audit while being violated for months between cycles. + +Continuous compliance inverts this: controls are verified automatically on every change, evidence is collected and timestamped by the pipeline, and compliance state is always known. The audit becomes a reporting exercise, not an investigation. + +| Dimension | Point-in-time audit | Continuous compliance | +|---|---|---| +| When | Annually or on-demand | Every commit, deploy, or config change | +| Evidence collection | Manual, retrospective scramble | Automated, real-time pipeline output | +| Drift detection | Found only at audit time | Immediate alert on deviation | +| Audit prep cost | High (weeks of effort) | Low (report export) | +| Ongoing assurance | Low (gaps possible between cycles) | High (continuous verification) | + +## Compliance as code and continuous compliance + +The modern approach automates the audit lifecycle end-to-end: + +- **Map controls to checks** — express each control as an automated test wherever possible: a scan policy, a configuration assertion, a CI gate, or an admission rule. Document the mapping explicitly (control ID → automated check) so auditors can trace evidence to requirements. +- **Continuous Control Monitoring (CCM)** — verify controls on every commit, deploy, or configuration change rather than at quarterly audit time. Drift is caught and reported immediately. +- **Automated evidence collection** — pipelines emit logs, scan results, approvals, signed provenance, and attestations automatically. Store them in a tamper-resistant evidence vault for the audit period. +- **Policy as code** — encode compliance rules in machine-readable form and enforce them in CI and at admission (see [Policy as Code](3-1-2-Policy-as-code.md)). +- **Cross-framework mapping** — a single automated check often satisfies multiple frameworks simultaneously. Platforms like Drata and Vanta maintain pre-built control mappings so a passing SAST gate can satisfy both SOC 2 CC7.1 and NIST 800-53 SA-11 at once. + +## What auditors actually look for + +Understanding what evidence auditors request makes it easier to generate that evidence continuously: + +| Evidence type | What it demonstrates | How to generate it automatically | +|---|---|---| +| Change management records | Every change was reviewed and approved | PR merge history with required reviewers; GitOps PR approvals | +| Vulnerability scan reports | Controls are active and findings are actioned | CI/CD scan outputs retained per pipeline run; DefectDojo audit trail | +| Access control review | Least-privilege principle is enforced | IAM access reviews via cloud-native tools; quarterly role review records | +| Security training completion | All staff received required training | LMS completion export (KnowBe4, Proofpoint) | +| Incident response records | Incidents are detected, tracked, and closed | SIEM alert-to-ticket lifecycle in Jira/ServiceNow | +| SBOM / dependency inventory | Software components are known and managed | Syft/CycloneDX SBOM attached to every release artifact | +| Penetration test report | External validation of controls | Annual pentest report with remediation status | +| Signed commits / provenance | Changes are attributable; artifacts are tamper-evident | Signed commits in git; cosign/SLSA attestations in registry | + +## SOC 2 control mappings — examples + +SOC 2 Trust Services Criteria (CC) map naturally to DevSecOps practices: + +| SOC 2 criterion | DevSecOps practice | Evidence | +|---|---|---| +| CC6.1 — logical access controls | Branch protection, RBAC in CI/CD, MFA enforced | IAM config, branch protection settings | +| CC6.6 — restrict access to change management | Required reviewer rules; protected branches | GitHub/GitLab audit log of merges | +| CC7.1 — detect and monitor security events | SIEM with defined detection rules | SIEM alert log, detection-as-code policy files | +| CC7.2 — monitor system components | Continuous vulnerability scanning | Scan results per pipeline run, registry re-scan cadence | +| CC8.1 — manage changes | GitOps pull-request workflow with approvals | PR merge history, change management ticket links | +| A1.2 — availability risk mitigations | Capacity monitoring, health checks, progressive delivery | Monitoring dashboards, runbooks, deployment config | + +## Audit trails + +Auditability depends on tamper-resistant records of who did what and when: + +- **GitOps as a change-management trail** — every infrastructure and configuration change is a reviewed, merged pull request with a complete history. This is inherently auditable and maps directly to SOC 2 CC8.1 and NIST 800-53 CM-3. +- **Signed commits and provenance** — signed commits prove who authored changes; signed build provenance proves what source produced which artifact (see [Artifact Signing](../../2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md)). +- **Centralized, retained logs** — SIEM logs with defined retention periods (typically 1 year for SOC 2, 7 years for some regulated industries) support both investigation and evidence requests (see [Logging and Monitoring](../../2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md)). +- **Release approvals and ticket links** — tie each release to an approved change ticket, capturing the human sign-off that automated processes cannot replace. + +## Maturity progression + +**Starter** — manual control documentation and periodic (annual) evidence collection per audit cycle. Controls exist but are not automated. + +**Intermediate** — controls mapped to automated checks in CI. Evidence collection is partially automated (scan outputs saved, logs retained). Compliance is tracked against a known framework with quarterly reviews. + +**Advanced** — continuous control monitoring with real-time drift detection. All audit evidence is auto-collected, indexed, and retrievable on demand. A single set of automated checks satisfies multiple frameworks simultaneously. Audit prep is a report export, not a project. + +## Common pitfalls + +- **Evidence collected only at audit time** — auditors can and do ask for historical evidence; collecting it retrospectively is stressful and unreliable. Type II auditors specifically look for evidence *over the period*, not just at a point in time. +- **Controls that exist on paper but not in practice** — an automated check will surface this; a policy document will not. Automate to keep documentation honest. +- **Framework sprawl without rationalization** — chasing every framework independently creates massive duplication. Map controls to a primary framework and cross-reference others. One passing CI gate can satisfy SOC 2, NIST, and ISO requirements simultaneously. +- **Treating compliance as the goal** — compliance is a floor, not a ceiling. Passing an audit does not mean you are secure; it means your controls met the criteria at the time of review. Design for real-world adversaries, not just auditor checklists. + +## Metrics + +| Metric | What it tells you | +|---|---| +| % of controls with automated checks | How much of your compliance posture is continuously verified vs. manually attested | +| Days to gather audit evidence | A proxy for automation maturity; target should be hours, not weeks | +| Control drift rate | How often automated checks detect a configuration falling out of compliance | +| Open compliance findings by severity | Current gap between actual and required posture | +| Time since last framework review | Controls age; frameworks update and so should your mapping | + +## Make it sustainable + +Treat compliance as continuous, not annual. Tooling can map a single control to multiple frameworks (test once, satisfy many), reducing duplicated effort. The aim is that passing an audit and running a secure pipeline are the same activity. + +--- + +## Tools[^1] + +### Open-source + +- [Cloud Custodian](https://cloudcustodian.io/) — rules engine for cloud governance; write YAML policies to detect and auto-remediate non-compliant cloud resources. Best for teams already living in cloud config. +- [OpenSCAP](https://www.open-scap.org/) — compliance scanning against SCAP/XCCDF baselines including CIS and DISA STIGs. Strong for OS-level compliance in regulated environments. +- [Open Policy Agent](https://www.openpolicyagent.org/) — general-purpose policy engine for codifying compliance rules in Rego. Use to gate CI, Kubernetes admission, and API authorization. + +### Commercial + +- [Drata](https://drata.com/) — continuous compliance automation for SOC 2, ISO 27001, HIPAA, PCI DSS, and more. Integrates with cloud providers, code platforms, and HR systems to auto-collect evidence. +- [Vanta](https://www.vanta.com/) — automated compliance and trust management; strong on cross-framework coverage and vendor risk management. +- [Secureframe](https://secureframe.com/) — compliance automation with built-in security training, risk management, and vendor questionnaire management. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md b/current-version/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md index 92dd46f..7b26461 100644 --- a/current-version/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md +++ b/current-version/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md @@ -1,22 +1,190 @@ # Policy as Code -## What is Policy +Policy as Code (PaC) expresses security, compliance, and operational rules as **machine-readable, version-controlled code** that is automatically evaluated and enforced — rather than as documents humans are expected to remember and follow. This makes policy consistent, testable, auditable, and impossible to silently skip, which is exactly what a high-velocity DevSecOps pipeline needs. + +## Why policy as code + +- **Consistency** — the same rule is enforced identically everywhere, every time, without relying on individual judgment or memory. +- **Automation** — policies run in CI and at admission without manual gatekeeping or review bottlenecks. +- **Version control and review** — policy changes go through pull requests with history, diff, and accountability. Rolling back a bad policy is a revert. +- **Testability** — policies can be unit-tested against example inputs before rollout, preventing both false positives and missed cases. +- **Auditability** — every decision is logged with the input, the policy version, and the outcome — producing structured evidence for [Compliance Auditing](3-1-1-Compliance-Auditing.md). +- **Scalability** — one centrally maintained policy library can be distributed to thousands of pipelines, services, and clusters simultaneously. + +## Where policy as code is applied + +- **CI/CD gates** — block merges or builds that violate policy (e.g., "no critical vulnerabilities", "SBOM required", "image must be signed"). Conftest tests structured config files (Kubernetes manifests, Terraform plans, Helm values) against Rego policies before they are applied. +- **Admission control** — Kubernetes admission controllers (OPA Gatekeeper, Kyverno) reject non-compliant or unsigned workloads at the point of deploy (see [Deploy](../../2-Process/2-6-Deploy/2-6-1-Deploy.md)). +- **Infrastructure as Code** — enforce guardrails on Terraform/Kubernetes before provisioning (see [IaC Scanning](../../2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md)). +- **Cloud guardrails** — preventive controls (Service Control Policies in AWS, Azure Policy, GCP Organization Policy) prevent forbidden actions from being performed at all. +- **API authorization** — OPA is commonly used as an external authorization engine to evaluate fine-grained access-control policies separately from application code. + +## Policy examples + +### Block `:latest` image tags + +```rego +# deny_latest_tag.rego +package main + +deny[msg] { + input.kind == "Deployment" + container := input.spec.template.spec.containers[_] + endswith(container.image, ":latest") + msg := sprintf("Container '%v' must not use the :latest tag — pin to a digest or versioned tag", [container.name]) +} +``` + +### Require `runAsNonRoot` + +```rego +# require_non_root.rego +package main + +deny[msg] { + input.kind == "Deployment" + container := input.spec.template.spec.containers[_] + not container.securityContext.runAsNonRoot + msg := sprintf("Container '%v' must set securityContext.runAsNonRoot: true", [container.name]) +} +``` + +### Require required labels + +```rego +# require_labels.rego +package main + +required_labels := {"app", "team", "env"} + +deny[msg] { + input.kind == "Deployment" + label := required_labels[_] + not input.metadata.labels[label] + msg := sprintf("Deployment is missing required label: '%v'", [label]) +} +``` + +### Block no-root enforcement missing from securityContext (Kyverno YAML alternative) + +```yaml +# kyverno-require-non-root.yaml +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-run-as-non-root +spec: + validationFailureAction: enforce + rules: + - name: check-runAsNonRoot + match: + resources: + kinds: ["Pod"] + validate: + message: "Containers must not run as root. Set runAsNonRoot: true in securityContext." + pattern: + spec: + containers: + - securityContext: + runAsNonRoot: true +``` + +## OPA integration in CI — step by step + +1. **Install Conftest** in your CI image or as a binary download step: + ```bash + wget https://github.com/open-policy-agent/conftest/releases/download/v0.50.0/conftest_0.50.0_Linux_x86_64.tar.gz + tar xzf conftest_*.tar.gz && mv conftest /usr/local/bin/ + ``` + +2. **Store policies** in a `policy/` directory in your repo (or reference a shared OCI bundle): + ``` + policy/ + deny_latest_tag.rego + require_non_root.rego + require_labels.rego + ``` + +3. **Run in CI** against generated Kubernetes manifests before applying: + ```bash + helm template my-app ./chart > rendered.yaml + conftest test rendered.yaml --policy ./policy/ + ``` + +4. **Interpret results** — conftest exits non-zero if any `deny` rule fires. CI blocks the job and surfaces the message to the developer. + +5. **Promote to enforcement** — once the policy has been running in warn mode for two sprints without significant false positives, remove the `--no-fail` flag so violations block the pipeline. + +## Testing policies + +A policy that is not tested is a policy that may silently fail. Use OPA's built-in test framework: + +```rego +# deny_latest_tag_test.rego +package main + +test_deny_latest { + deny["Container 'app' must not use the :latest tag — pin to a digest or versioned tag"] with input as { + "kind": "Deployment", + "spec": {"template": {"spec": {"containers": [{"name": "app", "image": "myrepo/myimage:latest"}]}}} + } +} + +test_allow_pinned { + count(deny) == 0 with input as { + "kind": "Deployment", + "spec": {"template": {"spec": {"containers": [{"name": "app", "image": "myrepo/myimage:sha256-abc123"}]}}} + } +} +``` + +Run with: `opa test ./policy/` + +Require 100% test coverage for all `deny` rules before promoting to enforcement mode. + +## Policy library management + +At scale, individual teams should consume policies — not author them. A platform team model: + +- **Central policy repository** — all organizational policies live in a single, reviewed repo. Changes require at least two approvals. +- **OCI distribution** — package and publish policies as OCI artifacts to your container registry. Conftest can pull directly: `conftest pull oci://myregistry/policies:v1.2`. +- **Versioned releases** — tag policy releases. Pipelines pin to a specific version. Breaking policy changes are pre-announced and coordinated. +- **Policy changelog** — maintain a changelog. Teams need to understand what changed between policy versions and why, so they can prepare before upgrading. +- **Exemption process** — define how teams can request a policy exemption for a specific resource, with a named owner and expiry date. Exemptions are stored as OPA annotations or Kyverno exceptions, not as silently disabled checks. + +## Good practice + +- **Start with guardrails, not handcuffs** — begin in warn/audit mode, then move high-confidence rules to enforce after validating false-positive rates. This builds developer trust rather than creating immediate friction. +- **Codify organization-specific rules** — encode the policies unique to your risk appetite and regulatory context, not just generic benchmarks. +- **Provide clear, actionable messages** — when a policy blocks something, tell the developer exactly what to change and why. A cryptic OPA error kills adoption. +- **Unit-test every policy** — use OPA's built-in test framework or Kyverno's `test` command to validate that policies correctly allow and deny the right inputs before deploying them. +- **Gate policy changes like code changes** — a policy change that silently widens permissions is as dangerous as a code change that introduces a vulnerability. + +## Maturity progression + +**Starter** — a few ad-hoc Conftest or OPA checks run in CI for the most critical rules (e.g., no hardcoded secrets, no public buckets). Policies live in individual repos with no central coordination. + +**Intermediate** — a centrally maintained policy library distributed to all pipelines. Kubernetes admission control enforced via Gatekeeper or Kyverno. Policies are version-controlled, reviewed, and unit-tested. Warn vs. enforce distinction managed deliberately. + +**Advanced** — full policy lifecycle management via a platform like Styra DAS or a custom OPA bundle server. Every compliance control from [Compliance Auditing](3-1-1-Compliance-Auditing.md) has a corresponding policy check. Policy decisions are logged to SIEM for audit evidence. SLO on policy coverage: 100% of production workloads governed by at least one admission policy. + +## Common pitfalls + +- **Policies that are always in warn mode** — a policy that never enforces is theater. Build a path from warn to enforce for every rule with a defined timeline. +- **No tests for the policy itself** — untested policies silently fail to catch what they were meant to catch, discovered only after an incident. +- **Overly broad deny rules** — a policy that blocks too much gets disabled by teams under pressure. Tune aggressively on false positive rate before enforcing. +- **Policy debt** — policies accumulate without pruning. Stale rules that no longer apply create confusion and noise. Review the policy library quarterly. +- **No exemption process** — teams under deadline that cannot get an exemption will delete the policy check. A defined exemption path keeps the policy in place. -In each company there are lots of rules, requirements, or procedures that must consider before deploying any application or product to be in production level, and other of them for other type of level like staging or developing. These rules, requirements, or procedures must check and pass and if there is any misconfiguration, process has to be suspend until it fix. +## Metrics -Some must comply with industry-recognized frameworks such as SOC 2, CIS, PCI DSS, or ISO 27001. These policies are either part of the business logic code or enforced manually.These are not easily trackable because every team implements it as it sees fit due to a lack of framework definition in organization level. - -## What is Policy as Code - -Having multiple security checklist in your organization will come to be time consuming and makes lots of differents meaning and behaviour in each team. despite of having a checklist or excel, you can manage all policies as code and make all of them proactive and apply them in each enviroment you need them. by this approach policeis are not only a checklist that one team can ignore some part of it or miss any part of it. - -## Benefits of Policy as Code - -**Policy Management**: Centralizing your policies into a single location, as opposed to dispersing them across multiple locations maintained by different IT teams, enables a more agile and adaptable approach to policy management. - -**Version Control**: Centralizing policies in a version control system like GitHub or GitLab offers organizations enhanced control and visibility. Stakeholders benefit from easy access to operational changes, while automated version control facilitates seamless updates and rollback options, ensuring smooth transitions and mitigating potential issues with new versions. - -**Faster and Efficient**: Efficiency is heightened as manual policy enforcement is eliminated, enabling dynamic updates and sharing of policies, thereby streamlining the process. Additionally, the combination of centralization and versioning fosters repeatability and idempotence in code execution. Repeatability ensures consistent code execution, while idempotence guarantees that repeated executions yield the same output. This reliability is crucial for instilling confidence among operators, empowering them to execute deployments without hesitation or fear. +| Metric | What it tells you | +|---|---| +| % of pipelines with at least one enforcement-mode policy | Governance coverage across the estate | +| Policy violation rate by rule | Which policies are blocking most; candidates for tuning or developer education | +| Warn-to-enforce migration rate | Maturity of the policy program; stagnation in warn mode is a risk signal | +| Policy test coverage | How thoroughly policies are validated before rollout | +| Open policy exemptions by age | Exemptions that have not been closed indicate growing residual risk | --- @@ -24,13 +192,15 @@ Having multiple security checklist in your organization will come to be time con ### Open-source -- [Kyverno](https://kyverno.io/) - Kyverno (Greek for “govern”) is a policy engine designed specifically for Kubernetes. -- [OPA](https://www.openpolicyagent.org/) - Open Policy Agent (OPA) is an open source, general-purpose policy engine that enables unified, context-aware policy enforcement across the entire stack. +- [Checkov](https://www.checkov.io/) — policy-as-code scanning for IaC (Terraform, CloudFormation, Kubernetes, Helm) with hundreds of built-in rules and support for custom Rego or Python policies. Integrates natively with most CI systems. +- [Conftest](https://www.conftest.dev/) — tests any structured configuration (YAML, JSON, HCL, Dockerfile, etc.) against Rego policies. Ideal for pre-deploy validation in CI without a running cluster. +- [Gatekeeper](https://github.com/open-policy-agent/gatekeeper) — OPA-based Kubernetes admission controller. Enforces policies at the Kubernetes API level, preventing non-compliant resources from ever being admitted. Supports audit mode for existing resources. +- [Kyverno](https://kyverno.io/) — Kubernetes-native policy engine using YAML-based policies (no Rego). Easier adoption for teams unfamiliar with Rego; supports mutating policies (auto-remediation) as well as validation. +- [Open Policy Agent (OPA)](https://www.openpolicyagent.org/) — general-purpose policy engine using the Rego language. The foundation for Conftest, Gatekeeper, and many other tools. Use directly for API authorization and custom enforcement contexts. ### Commercial -- [HashiCorp Sentinel](https://developer.hashicorp.com/sentinel) - A language and framework for policy built to be embedded in existing software to enable fine-grained, logic-based policy decisions. -- [Styra DAS](https://www.styra.com/pricing/) - Commercial tools for managing OPA at scale and created by the founders and maintainers of Open Policy Agent (OPA) +- [Styra DAS](https://www.styra.com/) — management plane for OPA policies at scale. Provides centralized authoring, testing, distribution, and decision logging for OPA across hundreds of services and clusters. --- diff --git a/current-version/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md b/current-version/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md index 128ed42..09a8e10 100644 --- a/current-version/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md +++ b/current-version/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md @@ -1 +1,136 @@ -# Security benchmarking +# Security Benchmarking + +Security benchmarking measures your security posture against an objective standard — either an external best-practice baseline or your own past performance. Benchmarks answer two questions every program eventually faces: "How do we compare to recognized good practice?" and "Are we getting better over time?" Without them, security investment is guided by intuition rather than evidence. + +## Types of benchmarks + +- **Configuration benchmarks** — [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks) provide prescriptive, consensus hardening baselines for operating systems, cloud, containers, and Kubernetes. Each check is categorized as Level 1 (essential, low-impact) or Level 2 (defense-in-depth, may affect usability). Measuring against them produces a concrete compliance percentage you can track over time. +- **Supply-chain posture** — [OpenSSF Scorecard](https://github.com/ossf/scorecard) scores open-source and internal repositories on supply-chain security practices: branch protection, pinned dependencies, signed releases, fuzzing, and more. Run it in CI on every pull request and on a regular schedule across all repos. +- **Maturity models** — [OWASP SAMM](https://owaspsamm.org/), [OWASP DSOMM](https://dsomm.owasp.org/), and [BSIMM](https://www.bsimm.com/) assess how mature your overall program is across many practices, and allow comparison to industry peers. +- **Cloud security posture** — tools like Prowler and cloud-native services (AWS Security Hub, Azure Defender, GCP Security Command Center) continuously benchmark your cloud configuration against CIS, PCI DSS, ISO 27001, and other standards. + +## Choosing the right benchmark for the job + +| What you're measuring | Best benchmark | +|---|---| +| OS and server hardening | CIS Benchmarks (Linux, Windows, macOS) | +| Kubernetes cluster security | CIS Kubernetes Benchmark, kube-bench | +| Cloud account configuration | CIS AWS/Azure/GCP Foundations, Prowler | +| Source code repository health | OpenSSF Scorecard | +| DevSecOps pipeline maturity | OWASP DSOMM | +| Overall AppSec program maturity | OWASP SAMM, BSIMM | +| Container image hardening | CIS Docker Benchmark, Trivy (misconfig) | + +## CIS Benchmark scoring — a worked example + +CIS Benchmarks produce a pass/fail result for each check. Consider the CIS Kubernetes Benchmark for a cluster control plane: + +``` +[PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive +[FAIL] 1.2.6 Ensure that the --authorization-mode argument is not set to AlwaysAllow +[PASS] 1.2.9 Ensure that the admission control plugin EventRateLimit is set +[FAIL] 4.2.1 Ensure that the kubelet service file permissions are set to 644 or more restrictive +``` + +A typical run might yield 60/80 checks passing = 75%. The actionable output is not the percentage — it is the list of failing checks, each with a remediation step. Prioritize failing checks by Level (Level 1 first) and by risk impact (auth/authz failures before filesystem permissions). + +Over quarters, track the delta: 75% → 82% → 91%. This is the story that justifies the hardening investment. + +## Using OpenSSF Scorecard — step by step + +Scorecard evaluates 20+ checks across a repository. Running it is straightforward: + +```bash +# Run against your repo (requires GitHub token with read scope) +GITHUB_AUTH_TOKEN= scorecard --repo github.com/myorg/myrepo + +# Or run as a GitHub Actions workflow (auto-triggered on push) +# Add the scorecard-action workflow from github.com/ossf/scorecard-action +``` + +A sample output with scores per check: + +``` +Maintained: 10 / 10 +Code-Review: 8 / 10 (some PRs merged without review) +Dangerous-Workflow: 10 / 10 +Dependency-Update-Tool: 10 / 10 (Dependabot enabled) +Binary-Artifacts: 10 / 10 +Branch-Protection: 7 / 10 (no require-signed-commits) +Pinned-Dependencies: 3 / 10 (Actions not pinned to SHA) +SAST: 5 / 10 (SAST runs but no blocking gate) +Signed-Releases: 0 / 10 (no signed releases) + +Aggregate score: 7.0 / 10 +``` + +From this output, actionable priorities are clear: pin Actions to SHA digests (Pinned-Dependencies: 3/10), add signed releases (Signed-Releases: 0/10), and require signed commits in branch protection (Branch-Protection: 7/10). These three fixes would move the aggregate score above 9.0. + +## DSOMM assessment process + +OWASP DSOMM provides a web-based tool and YAML-based data model for tracking pipeline practices. A practical assessment process: + +1. **Install the DSOMM application** — run it locally or self-host with Docker. +2. **Select your dimensions** — DSOMM covers Static Depth, Dynamic Depth, Intensity, Consolidation, and more. Start with Static Depth (SAST, SCA) and Infrastructure (IaC, cloud config). +3. **Rate each practice** — for each activity (e.g., "Use of multiple SAST tools", "SAST integrated into developer IDE"), select your current level (0–4) based on evidence. +4. **Export the gap report** — DSOMM generates a heatmap of current state vs. target level, and a list of gap activities with references to tools and implementation steps. +5. **Create backlog items** — for each gap, create a ticket. DSOMM links each practice to implementation guidance. +6. **Re-assess quarterly** — re-run the assessment and compare to the previous export. The delta is the evidence of progress. + +## From benchmark to roadmap + +Benchmarks are most valuable when they feed planning: + +1. Run the benchmark and record scores per domain/check. +2. Identify the lowest-scoring areas with the highest risk impact. +3. Create prioritized backlog items with owners and remediation timelines. +4. Re-run on a defined cadence and track delta. +5. Report trend to leadership quarterly. + +Link each benchmark gap back to the framework it addresses — a failing Scorecard "Pinned-Dependencies" check maps to SLSA Supply Chain Threats and OWASP Top 10 CI/CD Risk #8. This cross-referencing is what turns a benchmark score into a compliance argument (see [Compliance Auditing](3-1-1-Compliance-Auditing.md)). + +## Maturity progression + +**Starter** — CIS Benchmarks run manually on a sample of systems before a major audit. Scorecard run once on critical repos. No automated tracking. + +**Intermediate** — kube-bench running as a scheduled CronJob; Prowler scanning cloud accounts weekly. Scorecard in CI for all repositories. Gaps tracked as backlog items. SAMM or DSOMM assessment conducted annually. + +**Advanced** — all benchmark checks automated and continuous. Scores feed a centralized dashboard alongside scan findings. Drift from baseline triggers an alert. Maturity assessments are quarterly, with a formal roadmap reviewed by security leadership. CIS scores part of deployment gates for new environment provisioning. + +## Common pitfalls + +- **Checkbox compliance** — reaching a benchmark score by disabling checks or documenting exceptions without fixing the underlying issue. Track the exclusion list as carefully as the score; unexplained gaps attract auditor scrutiny. +- **Benchmarking only at audit time** — a configuration that passes a benchmark on Monday can drift by Friday. Continuous checks are the only reliable approach. +- **Ignoring model intent** — SAMM and DSOMM describe practices to *do*, not just policies to *have*. An organization that documents a threat modeling process but runs no threat models scores artificially high. +- **Comparing incomparable scores** — Scorecard v3 and v4 scores are not directly comparable. BSIMM data changes as the participating firms evolve. Always version your benchmark runs and note the benchmark version in reporting. + +## Metrics + +| Metric | What it tells you | +|---|---| +| CIS Benchmark score (% passing) | Configuration hardening level by system/environment | +| OpenSSF Scorecard score (by repo) | Supply-chain security health of repositories | +| SAMM/DSOMM maturity level by practice | Where the program is strong and where it lags | +| Number of benchmark checks with accepted exclusions | Residual risk from environment-specific gaps | +| Score delta quarter-over-quarter | Whether the program is improving | + +--- + +## Tools[^1] + +### Open-source + +- [kube-bench](https://github.com/aquasecurity/kube-bench) — checks Kubernetes nodes and control plane against the CIS Kubernetes Benchmark. Can run as a Job in-cluster or as a standalone binary. The de facto standard for Kubernetes CIS compliance. +- [OpenSCAP](https://www.open-scap.org/) — scans Linux systems against SCAP/XCCDF baselines including CIS Benchmarks and DISA STIGs. Produces XML and HTML reports; integrates with Satellite and Ansible for remediation. +- [OpenSSF Scorecard](https://github.com/ossf/scorecard) — scores repositories on 20+ supply-chain security checks. Run via GitHub Actions or as a CLI; results can be published to the OpenSSF dashboard. +- [Prowler](https://github.com/prowler-cloud/prowler) — cloud security posture assessment for AWS, Azure, and GCP. Covers CIS Foundations Benchmarks, PCI DSS, HIPAA, GDPR, and more. Strong CLI and CI integration. + +### Commercial + +- [CIS-CAT Pro](https://www.cisecurity.org/cybersecurity-tools/cis-cat-pro) — automated assessment against CIS Benchmarks with multi-system scanning, remediation guidance, and report generation. The official CIS tool; useful for large-scale OS and server compliance programs. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/3-Governance/3-2-Data-protection.md b/current-version/3-Governance/3-2-Data-protection.md index f969969..bc34a1f 100644 --- a/current-version/3-Governance/3-2-Data-protection.md +++ b/current-version/3-Governance/3-2-Data-protection.md @@ -1,37 +1,112 @@ # Data Protection -Privacy has become an important aspect of application security. GDPR, LGPD, CCPA and other laws and regulations have impose several controls over processing PII (Personally Identifiable Information). To comply with those regulations, DevSecOps have to be sure to use PII accordingly and protect data agains leaking. +Ultimately, most security exists to protect **data** — customer information, credentials, intellectual property, and regulated records. Data protection spans the controls and practices that keep data confidential, intact, and available throughout its lifecycle, and the privacy obligations that govern personal data. In a DevSecOps program, data protection cuts across every stage, from design through operation. -To start, it is important to have a good understanding of what is considered PII: +## Know your data: classification -- First and last name; -- Identifiable email (); -- Identity card numbers; -- Location data (mobile); -- IP Address. -- This is not a complete list. +You cannot protect data appropriately without knowing what you have and how sensitive it is. Classification is the foundation of proportionate protection: -Some PII are considered sensitive, and require even more protection, such as: +- **Public** — no harm if disclosed (marketing content, documentation). Minimal controls. +- **Internal** — intended for employees and partners. Basic access control and logging. +- **Confidential** — business-sensitive data (financials, strategy, IP). Encryption, restricted access, audit trails. +- **Regulated / PII / PHI** — personal or legally-protected data (GDPR, HIPAA, PCI DSS). Strictest controls, data residency obligations, retention limits, and deletion rights. -- Racial or ethnic origin; -- Political opinions; -- Religious or philosophical beliefs; -- Trade union membership; -- Genetic data; and -- Biometric data (where processed to uniquely identify someone). +Steps to operationalize classification: -Most privacy regulations promote Privacy by Design, the aproach where the development process addresses privacy concerns thru the whole cycle. Even before coding starts. +1. **Inventory** — catalog all data stores (databases, object storage, data lakes, SaaS) and label them by classification. Automated data discovery tools accelerate this at scale. +2. **Tag at the source** — embed classification metadata in data catalog entries, resource tags, and infrastructure-as-code so controls can be applied programmatically. +3. **Apply controls proportionate to classification** — the most sensitive data gets the strongest encryption, most restricted access, and most complete audit trail. -You have to create a PII data flow to make sure you apply the required protection to the data thru its lifecycle. You also have to follow all the requirements related to the quality and volume of processed data. +## Core protective controls -All PII data processing requirements have to be specified. you have to create an inventory of all PII and evaluate the processing activity to make sure it follows all requirementes, such as: +### Encryption -- Lawfulness, fairness and transparency -- Purpose limitation -- Data minimization -- Accuracy -- Storage limitation -- Integrity and confidentiality (security) -- Accountability +- **Encryption in transit** — enforce TLS 1.2+ everywhere, including service-to-service traffic inside the cluster. Use mutual TLS (mTLS) for service mesh environments (Istio, Linkerd). Reject or redirect plaintext connections. +- **Encryption at rest** — encrypt databases, object storage (S3/GCS/Azure Blob), backups, and persistent volumes. Use platform-managed encryption as a baseline; for highest-sensitivity data, add application-layer or client-side encryption so the cloud provider cannot decrypt data at rest. +- **End-to-end encryption** — for data that must remain private even from your own infrastructure (e.g. health or financial records), consider E2E encryption where keys remain entirely with the data owner. -After you make sure that the PII and the PII processing activity are mapped and comply to the privacy regulation you have to follow, it is important to apply the security measures to protect the data, accordingly with its criticity. +### Key management + +- Manage keys in a dedicated KMS/HSM (AWS KMS, Azure Key Vault, GCP Cloud KMS, HashiCorp Vault) with automatic rotation, access control, and audit logging. +- Never hardcode keys or secrets in source code (see [Secrets Management](../2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md)). +- Separate keys by environment (dev/staging/prod); a compromised dev key must not decrypt production data. +- Enforce key expiry and rotation policies. For regulated data, document the key lifecycle. + +### Access control + +- Apply least-privilege access to all data stores: users and services receive the minimum permissions required for their function. +- Use strong authentication (MFA for human access to sensitive data; short-lived, scoped credentials for service access via OIDC/Workload Identity). +- Log all access to sensitive data — who accessed what, when, from where — and retain logs for the period required by your compliance obligations. +- Review data access permissions regularly; access rights granted for a project often outlast the project. + +### Data Loss Prevention (DLP) + +- Deploy DLP controls at egress points (email, cloud storage, SaaS integrations, developer endpoints) to detect and block unauthorized exfiltration. +- Define sensitive-data patterns for your context: PCI card numbers, SIN/SSN, GDPR-regulated identifiers, internal credential formats. +- For developer workflows, DLP at the IDE and git level (pre-commit hooks, secret scanners) prevents sensitive data from ever reaching source control. + +## Privacy by design + +Privacy should be designed in, not bolted on — integrating data protection principles at the architecture and feature design stage rather than as a compliance retrofit: + +- **Data minimization** — collect and retain only what you need, for only as long as you need it. Every additional data field collected is a liability. +- **Purpose limitation** — use data only for the purposes disclosed at collection. Building a secondary analytics use case on data collected for operations requires a separate legal basis. +- **Privacy threat modeling** — apply [LINDDUN](https://www.linddun.org/) during design to systematically identify privacy threats (Linkability, Identifiability, Non-repudiation, Detectability, Disclosure, Unawareness, Non-compliance) across data flows and trust boundaries. See [Threat Modeling](../2-Process/2-1-Design/2-1-1-Threat-modeling.md). +- **Privacy regulations** — meet obligations such as GDPR (EU), PIPEDA (Canada), LGPD (Brazil), CCPA (California), and HIPAA (US healthcare), including data-subject rights (access, erasure, portability), lawful basis documentation, and **data residency/sovereignty** requirements — some jurisdictions prohibit transferring personal data outside their borders. + +## Protect data across environments + +- **Test-data management** — never use real production data in test, dev, or staging environments. Use data masking (obfuscation of real data), anonymization (irreversible de-identification), or synthetic data generation that preserves realistic characteristics without exposing real individuals. +- **Privacy-aware logging** — keep sensitive data out of logs: no passwords, tokens, PII, or full card numbers in application logs, error messages, or distributed traces. See [Logging and Monitoring](../2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md). +- **Secure deletion** — verifiably delete data when retention ends. For cloud storage, use crypto-shredding (delete the encryption key) to render data permanently unreadable without re-encrypting the entire dataset. +- **Backup protection** — apply the same encryption and access controls to backups as to primary data. A plaintext backup of an encrypted database is not an encrypted database. +- **AI data handling** — control what data is shared with AI assistants and used for model training. Enterprise data must not flow to third-party AI models without a data processing agreement and privacy review. See [AI Governance and Risk](3-4-AI-Governance-and-Risk.md). + +## Maturity progression + +**Starter** — data classified manually with basic labels. TLS in transit and at-rest encryption enabled for known sensitive stores. Secrets in a vault. No test-data management policy. + +**Intermediate** — automated data discovery and inventory. DLP deployed at key egress points. Privacy threat modeling performed for new features. Formal test-data masking or synthetic data pipeline. Data retention policy defined and partially automated. Privacy reviews gate new data collection. + +**Advanced** — real-time data security posture management (DSPM) across all cloud data stores. Crypto-shredding on deletion. E2E encryption for highest-sensitivity data. AI-BOM and data flow mapping for all AI features. All data access audited and anomalies alerted in SIEM. Data minimization enforced by platform defaults. + +## Common pitfalls + +- **Encrypting everything but managing keys poorly** — encryption is only as strong as key access control. If every service has the decryption key, encryption adds little. +- **Using production data in dev** — one breach of a dev environment that contains real PII is a reportable incident under GDPR and HIPAA. +- **Logging sensitive data "just in case"** — logs are often less protected than primary data stores and retained for long periods. Sensitive data in logs is a recurring breach vector. +- **Forgetting backup data** — backups frequently have weaker access controls, older encryption standards, and longer retention than primary data. They are a high-value, low-visibility target. +- **No data residency enforcement** — data residency requirements are easy to violate when using global cloud services without explicit region constraints. + +## Metrics + +| Metric | What it tells you | +|---|---| +| % of data stores with at-rest encryption enabled | Baseline encryption coverage | +| % of services enforcing TLS in transit | Network-level confidentiality | +| Key rotation compliance rate | KMS hygiene and operational maturity | +| Data classification coverage (% of stores classified) | Visibility into data landscape | +| Number of DLP policy violations per month (by type) | Volume and nature of exfiltration attempts | +| Time to purge data past retention deadline | Effectiveness of data lifecycle automation | + +--- + +## Tools[^1] + +### Open-source + +- [Amundsen](https://www.amundsen.io/) — data discovery and metadata catalog to locate and classify sensitive data across a data lake or warehouse. Useful for building an inventory of where sensitive data lives. +- [Presidio](https://github.com/microsoft/presidio) — detects and anonymizes PII (names, credit cards, passport numbers, SSNs, etc.) in text, images, and structured data. Use in data pipelines to scrub PII before loading into non-production environments. +- [Vault](https://www.vaultproject.io/) — secrets management, encryption-as-a-service, and dynamic credentials. Provides a central key management layer across cloud and on-premises infrastructure. + +### Commercial + +- [BigID](https://bigid.com/) — data discovery, classification, and privacy management across structured and unstructured data. Strong regulatory coverage (GDPR, CCPA, HIPAA) and automated risk scoring. +- [Cyera](https://www.cyera.com/) — data security posture management (DSPM) for cloud environments. Continuously discovers and classifies data, identifies misconfigurations, and prioritizes data exposure risk. +- [Macie (AWS)](https://aws.amazon.com/macie/) — managed ML-based service for discovering and classifying sensitive data in S3. Native integration with AWS security services for alerting and remediation. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md b/current-version/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md index b1f20dd..e0a9746 100644 --- a/current-version/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md +++ b/current-version/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md @@ -1 +1,117 @@ # Tracking Maturities + +A DevSecOps program is never "done" — it matures. Tracking maturity gives leadership and teams an honest, repeatable picture of where the program stands, where it is improving, and where to invest next. Without it, security spending is hard to justify and progress is invisible. Maturity tracking converts a vague sense of "we're doing security" into an evidence-based conversation about risk and investment. + +## Maturity models + +Use an established model so assessments are structured, repeatable, and comparable to industry: + +- **[OWASP SAMM](https://owaspsamm.org/)** — assesses maturity across five business functions (Governance, Design, Implementation, Verification, Operations) at three levels each. Each level is clearly defined with concrete activities and expected outputs, not vague descriptions. Strong for overall program strategy and executive reporting. SAMM assessments map to business risk, making them effective for communicating with leadership about where to invest. +- **[OWASP DSOMM](https://dsomm.owasp.org/)** — focuses on concrete DevSecOps activities in the pipeline and maps them to maturity levels across dimensions like Static Depth, Dynamic Depth, and Infrastructure. Strong for engineering adoption: every practice is mapped to specific tools and implementation steps. Use DSOMM to track the pipeline and engineering-level maturity. +- **[BSIMM](https://www.bsimm.com/)** — a descriptive model based on what real organizations (finance, healthcare, tech, ISV) actually do, derived from annual data from participating firms. Useful for benchmarking against industry peers: "we are at the median for our sector in code review but below average in attack models." + +**How to choose:** SAMM sets strategic direction; DSOMM drives day-to-day engineering adoption. Many programs use both: SAMM for the annual executive report, DSOMM for the engineering team's quarterly review. Add BSIMM when peer-benchmarking is a priority. + +## Conducting an assessment + +A maturity assessment is only useful if it is honest and consistent. Here is a practical facilitation guide: + +### Preparation (1–2 weeks before) + +- Select the model and scope (whole organization, one business unit, or one product team). +- Identify participants: security engineers, security champions, senior developers, and product/engineering managers — at least one per business function being assessed. +- Share the model and evidence requirements in advance so participants arrive prepared, not surprised. +- Define what counts as evidence: a policy document alone does not earn credit; a policy plus a passing scan result plus a remediation ticket does. + +### Running the session + +- Timebox each practice to 10–15 minutes. A full SAMM assessment across five functions typically takes two half-day sessions with the right participants. +- Work through each practice with the group. Present the model's description, ask "do we do this?", then ask "show me the evidence." Score only what can be evidenced. +- Where participants disagree on a score, err toward the lower score and treat the gap as an improvement opportunity. Optimism without evidence hurts the assessment's usefulness. +- Capture the rationale and evidence references for each score, not just the number — this is what makes the next assessment meaningful. + +### SAMM scoring — a worked example + +SAMM scores each practice on a 0–3 scale. Consider the practice **Secure Build** under Implementation: + +- **Score 0** — no defined build process for security; builds run ad-hoc. +- **Score 1** — a defined build process exists; dependency list is known. *Evidence: a `package-lock.json` or `requirements.txt` committed to source control.* +- **Score 2** — build process enforces removal of unneeded dependencies; known vulnerabilities in dependencies are identified. *Evidence: SCA tool configured in CI with passing gate reports.* +- **Score 3** — build process produces an SBOM; all dependencies are vetted and pinned; build provenance is generated and signed. *Evidence: Syft/CycloneDX SBOM attached to each release, cosign provenance attestation in registry.* + +Score 1.5 means evidence supports level 1 behaviors and partial evidence for level 2. Do not round up unless the evidence is unambiguous. + +## Building a roadmap from the assessment + +An assessment without a roadmap is a status report. A roadmap without a roadmap owner is a wish list. After each assessment: + +1. **Export all gaps** — every practice scoring below your target level produces a gap. +2. **Prioritize by risk impact** — not all gaps are equal. A missing secrets-scanning practice at score 0 in an active cloud environment is higher priority than a missing fuzzing practice. +3. **Write backlog items** — for each priority gap, create a ticket with: the target score, the evidence needed to reach it, the owner, and the target quarter. +4. **Assign roadmap ownership** — the roadmap needs a named owner (typically the AppSec lead or CISO) who reports on it quarterly. +5. **Gate the next assessment on roadmap progress** — if an item was due last quarter and is not done, that is the first conversation in the next assessment session. + +## Metrics that matter + +Complement maturity assessments with operational metrics that show whether the program is *working*, not just what practices are *present*: + +- **Mean Time to Remediate (MTTR)** — how fast vulnerabilities get fixed, by severity. Critical should be measured in hours to days; high in days to weeks. MTTR that does not improve year-over-year despite scanning investment indicates a workflow or prioritization problem, not a scanning problem. +- **Escape rate** — issues reaching production vs caught earlier in the pipeline. The primary shift-left indicator. A falling escape rate means the program is working; a rising one means risk is accumulating in production. +- **Scan coverage** — percentage of repositories and pipelines with each control type enabled (SAST, SCA, secrets, container, IaC). A security control that runs on 60% of repos has 40% blind spots. +- **Findings backlog age** — age distribution of open findings, by severity. A growing tail of old high-severity findings indicates SLA non-compliance and accumulating risk. +- **False positive rate** — the percentage of flagged issues that are not real vulnerabilities. High rates drive developer fatigue and tool disabling. Track this per scanner and tune aggressively. +- **Developer adoption** — training completion, security champions per team, threat models completed per new feature. Adoption metrics reveal culture, not just tooling. +- **ATT&CK coverage** — detection coverage validated by [Breach and Attack Simulation](../../2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md). Shows what percentage of adversary techniques your detection layer would catch. + +## Reporting cadence + +Match reporting frequency to audience and decision-making cycle: + +| Audience | Cadence | Content | +|---|---|---| +| Engineering teams | Weekly / per-sprint | Scan coverage gaps, MTTR by team, open backlog by age | +| Engineering leadership | Monthly | Trend metrics (escape rate, MTTR), roadmap progress, upcoming SLA breaches | +| CISO / security leadership | Quarterly | SAMM/DSOMM score trend, risk exposure summary, investment asks | +| Board / executive | Annual | Program maturity vs. industry (BSIMM), compliance posture, major incidents and lessons learned | + +## Make tracking useful + +- **Measure trends, not snapshots** — a SAMM score of 1.8 means little in isolation; a score rising from 1.2 to 1.8 over 18 months means the program is progressing at a healthy pace. +- **Build a roadmap from every gap** — translate gaps into a prioritized, owned improvement plan with target dates. An assessment without a roadmap is a status report, not a management tool. +- **Report to the audience** — leadership wants risk exposure, trend, and investment ROI; engineering teams want actionable, specific detail about what to fix and how. Produce both views from the same underlying data. +- **Avoid vanity and punitive metrics** — total vulnerability count is a vanity metric in a large estate. Ranking individual teams on scanner output incentivizes gaming (suppressing findings, tuning thresholds) rather than fixing. See [Security Culture and Awareness](../../1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md). +- **Close the loop** — every remediated backlog item from an assessment should feed back into the next assessment score. The maturity model is most powerful when it is a living, continuous process. + +## Maturity progression + +**Starter** — ad-hoc security reviews before major releases. No formal maturity model. Metrics tracked manually in spreadsheets if at all. + +**Intermediate** — annual SAMM assessment with a formal report and improvement roadmap. DSOMM used to track pipeline-level controls by squad. Core operational metrics (MTTR, coverage, escape rate) tracked in a dashboard. Metrics reviewed quarterly with engineering leads. + +**Advanced** — continuous DSOMM tracking integrated with pipeline data (scan results, gate outcomes, ticket resolution). SAMM assessments semi-annual with board-level reporting. Maturity scores feed OKRs and budget planning. BSIMM comparison used to justify investment against industry peers. All metrics automated, no manual data collection. + +## Common pitfalls + +- **Optimistic self-assessment** — teams credit themselves for policies they have not implemented. Require artifact evidence for every practice claimed. +- **Assessing but not acting** — an assessment that produces no roadmap, no backlog items, and no follow-up creates cynicism. Assessment without action is worse than no assessment. +- **Chasing the score** — optimizing for a higher maturity number by implementing the easiest practices rather than the most impactful ones. +- **Annual-only tracking** — once-a-year assessments miss drift between cycles. Supplement with continuous operational metrics that update in real time. + +--- + +## Tools[^1] + +### Open-source + +- [OWASP DSOMM application](https://github.com/devsecopsmaturitymodel/DevSecOps-MaturityModel) — interactive web application for assessing DevSecOps maturity against the DSOMM framework. Supports team-level assessments, progress tracking over time, and export of gap reports. Self-hostable. +- [OWASP SAMM Toolbox](https://owaspsamm.org/assessment/) — official spreadsheet and online tooling for conducting SAMM assessments. Version-controlled assessment templates allow consistent scoring across cycles. + +### Commercial + +- [Codific SAMMY](https://sammy.codific.com/) — platform for managing SAMM-based maturity assessments at scale, with collaborative scoring, gap analysis, roadmap generation, and trend reporting across multiple teams or business units. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md b/current-version/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md index da86d24..61fa3f7 100644 --- a/current-version/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md +++ b/current-version/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md @@ -1,35 +1,106 @@ # Central Vulnerability Management Dashboard -## What Is Vulnerability Management? +A typical pipeline runs many security tools — SAST, SCA, container, IaC, DAST, secrets, runtime — each with its own console, format, and severity scheme. Left separate, this fragments visibility: no one can answer "what is our total risk?" or "is this issue already reported elsewhere?" A **central vulnerability management dashboard** aggregates findings from every source into one normalized, prioritized view — making the whole security program manageable and reportable. -Vulnerability Management is a continuous process that helps organizations detect, report, prioritize, and remediate vulnerabilities in their software and platforms. It is an important part of DevSecOps Lifecycle because it allows the ability to organize the security flaws in a manageable, actionable, and traceable way. Also, VM helps to achieve visibility of an organization's security posture. When VM is executed alongside other processes, it helps minimize the attack surface and bridge the gap between isolated findings across distributed tools and processes. +## Why centralize -## Process Definition +Without centralization, each tool creates its own silo: -Taking the OWASP VMG Project as a reference, we can describe the overall VM process in three stages: +- The same CVE in a base image reported by Trivy, Snyk, and AWS ECR scanning appears as three separate findings with different severities and descriptions. +- A developer cannot see whether their SAST finding overlaps with something already tracked in the SCA scanner. +- Leadership cannot answer "what is our critical finding count?" without manually stitching together four dashboards. +- SLA tracking is impossible when findings live across disconnected tools. -- **Detection:** During the detection cycle, we conduct the tasks that support vulnerability tests in essential ways by defining the: who, what, where, why, and how. The principal activities are focused on defining and refining scope after each round of the process, getting tools ready and verifying their integrity, conducting tests, and verifying results. -- **Reporting:** The reporting cycle targets activities that help the organization understand vulnerability in a measurable way. The principal activities are focused on [quickly and concisely capturing](https://www.linkedin.com/pulse/how-vulnerability-jeff-williams/) all the system, vulnerability, threat, technical risk, and operational risk details associated with a vulnerability. Reporting can also involve creating organizational, meaningful metrics such as Mean Time to Remediate (MTTR) and Vulnerability Escape Rate (VER) to help the organization improve over time. -- **Prioritization:** The prioritization process selects vulnerabilities and working with development teams to get them fixed. Some vulnerabilities may represent minimal risk or may not be exploitable. Risk is one key factor in the prioritization process, but the effort and expertise required are also key factors. Organizations might also consider the retirement date of the system and details of the development process. -- **Remediation:** The Remediation cycle targets activities that reduce or eliminate vulnerabilities. Key activities are focused on defining priorities and terms of remediation work, discussing and documenting false positives, and dealing with exceptions. +A central dashboard eliminates this by being the single source of truth that all tools feed into: -## How VM tools can help DevSecOps +- **Single source of truth** — one place to see all findings across all tools, stages, and services. +- **Deduplication** — the same vulnerability reported by multiple tools becomes one item, with all evidence attached. This cuts the apparent finding count by 30–60% in typical environments, dramatically reducing noise. +- **Normalization** — different severity scales (CVSS 3.x, CVSS 4.0, vendor-proprietary) and formats (SARIF, CycloneDX, custom JSON) are reconciled into a consistent model with a single severity, priority, and description. +- **Prioritization** — risk scoring is applied uniformly across sources using CVSS, EPSS, CISA KEV membership, reachability, and asset context (see [Vulnerability Management](../../2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md)). +- **Reporting** — trends, SLAs, backlog health, and posture become reportable to teams and leadership from a single source. -The tools we use to create a DevSecOps pipeline will generate plenty of vulnerabilities, and each tool will have its own separate format. Managing this data can be challening to track. Vulnerability Management tools consolidate reports generated by different tools and activities in one or a few dashboards, providing an overview of the security posture. Team members can track the progress of remediation efforts by metrics, triage and prioritize findings across the entire pipeline, and manage the vulnerabilities lifecycle across the process. Also, engineers can benefit from the de-duplication features, which help them deal with the noise generated by continuous scanning and duplication of findings. Finally, VM Tools provide integrations with other components to enable bi-directional communication, notifications, data export, and report generation. +## What a good dashboard provides -The following image can give you a better view of what the Vulnerability Management means and why we must consider it. +### Data ingestion -![VM Inside Pipeline](/current-version/assets/images/Pipeline-view.png) +The foundation is broad scanner coverage. A mature setup ingests from: +- SAST (Semgrep, CodeQL, Checkmarx) +- SCA (Snyk, Dependabot, OWASP Dependency-Check) +- Container scanning (Trivy, Grype, Clair) +- IaC scanning (Checkov, Trivy misconfig) +- Secrets detection (Gitleaks, TruffleHog) +- DAST (OWASP ZAP, Burp Suite) +- Runtime (Falco, cloud-native alerts) +- Penetration test findings (manual import) -## Cautions +Most platforms accept SARIF and CycloneDX as interchange formats; ensure your scanners emit these. -Be wary of generating a large security backlog in your VM tool that captures vulnerabilities but isn't contributing to getting them fixed. As Michal Zalewski describes in "The Tangled Web," underfunded security efforts plus risk management are no substitute for real security work. +### Deduplication and correlation -Also be careful that your VM process isn't extremely fast. DevSecOps pipelines should be designed to create fast feedback loops that feed vulnerabilities to developers quickly as a part of the normal development process. Adding delays makes fixing vulnerabilities much more complex and expensive. +Deduplication logic must be tuned: matching by CVE ID alone misses the same flaw found by different tools under different identifiers. A good platform uses combination matching: CVE/CWE + file path + line number + component version. -## Where, When and How +Correlation goes further — linking the same vulnerable component across different stages: "this CVE appears in a dependency (SCA), in the container that packages it (container scan), and is reachable from an internet-facing endpoint (DAST)." This escalates priority meaningfully. -You should implement and integrate VM tools at the central part of your DevSecOps program to provide governance capabilities at earlier stages of development. Tools like OWASP DefectDojo support automatic CI/CD integration and manual reports, it also includes a checklist to track your application against OWASP ASVS V4, which is an excellent way to complement the risk analysis process. +### Risk-based prioritization + +Raw CVSS scores over-weight theoretical severity and under-weight real-world exploitability. A mature prioritization model combines: + +- **CVSS** — base severity and attack characteristics. +- **EPSS** — probability of exploitation in the next 30 days (empirically derived). +- **CISA KEV** — has this CVE been exploited in the wild? KEV membership warrants immediate action regardless of CVSS score. +- **Reachability** — is the vulnerable code path actually reachable from an external entry point? Non-reachable findings can be deprioritized. +- **Asset criticality** — a critical vulnerability in a tier-1 production service outranks the same finding in a dev tool. + +### Ownership and workflow + +- Assign every finding to a team, service, and owner. +- Integrate with Jira, ServiceNow, or GitHub Issues so findings flow into engineering workflows automatically — the developer sees a ticket in their backlog, not a security console they don't use. +- Define and track SLAs by severity (e.g., critical: 7 days; high: 30 days; medium: 90 days). +- Support **risk acceptance** — allow documented, time-boxed exceptions with an owner who accepts the residual risk. + +### Trend and SLA reporting + +A vulnerability management dashboard is most powerful as a trending tool: + +- New findings per week (by scanner, service, severity) — rising trend signals a problem. +- Resolved findings per week — flat line means the backlog is growing. +- MTTR by severity — is the team meeting SLAs? +- Backlog age distribution — are old high-severity findings accumulating? +- SLA breach rate — what percentage of findings missed their target remediation date? + +### Audit evidence + +Every finding, assignment, status change, and risk acceptance is a timestamped, exportable record. This makes the dashboard an evidence vault for compliance audits (see [Compliance Auditing](../3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md)). + +## Relationship to ASPM + +A central dashboard is the foundation; **Application Security Posture Management ([ASPM](3-3-3-ASPM.md))** is the evolution of it. Where a dashboard aggregates and deduplicates findings, ASPM adds deep code-to-runtime context, business-layer risk classification, and active orchestration. Think of the central dashboard as the consolidation and workflow layer that ASPM builds on top of with additional intelligence and automation. + +## Maturity progression + +**Starter** — findings exported manually from each scanner to a shared spreadsheet. Tracked per-team with no deduplication. SLAs informal. + +**Intermediate** — DefectDojo or equivalent ingesting findings from 5+ scanners automatically. Deduplication configured. Jira integration for ticket creation. SLAs defined and tracked per severity. Monthly trend reports to security team. + +**Advanced** — all scanner output flowing automatically to a central platform. Risk-based prioritization using CVSS + EPSS + KEV + reachability. Real-time dashboards for leadership and engineering teams. SLA breach alerts. Risk acceptance workflow with audit trail. Platform feeding security gates and ASPM. + +## Common pitfalls + +- **Aggregation without deduplication** — importing all scanners without deduplication triples the apparent finding count, creating more noise than the individual tools. +- **Severity normalization ignored** — treating a "critical" from one scanner identically to a "critical" from another without normalizing to a common scale produces inconsistent prioritization. +- **No ownership model** — a dashboard full of unassigned findings has no accountability and does not drive remediation. +- **Findings as read-only** — a dashboard that developers cannot act from (no ticket integration, no context, no fix guidance) is a reporting tool, not a remediation driver. + +## Metrics + +| Metric | What it tells you | +|---|---| +| Total open findings by severity | Current risk backlog | +| New findings per week | Velocity of risk introduction | +| MTTR by severity | Remediation efficiency; compare against SLA targets | +| SLA breach rate | What % of findings miss their target closure date | +| Deduplication ratio | How much noise the platform is eliminating | +| Findings per scanner (over time) | Which tool is contributing most; tuning signal | --- @@ -37,19 +108,17 @@ You should implement and integrate VM tools at the central part of your DevSecOp ### Open-source -- [Archery Sec](https://www.archerysec.com) - Open Source Orchestration and Correlation Tool -- [OWASP DefectDojo](https://github.com/quay/clair) - OpenSource Application Security Management +- [Faraday](https://github.com/infobyte/faraday) — vulnerability management and aggregation platform with a collaborative interface. Supports import from 70+ tools and provides a web UI for tracking, assignment, and reporting. Good for teams running varied pentest and scanner toolchains. +- [OWASP DefectDojo](https://www.defectdojo.org/) — the most widely deployed open-source vulnerability management platform. Aggregates, deduplicates, and manages findings from over 100 scanner formats (SARIF, CycloneDX, and tool-specific outputs). Provides SLA tracking, Jira integration, RBAC, and rich API. The default choice for teams with a diverse scanner mix. +- [OWASP Dependency-Track](https://dependencytrack.org/) — centralized component vulnerability tracking from SBOMs (CycloneDX and SPDX). Continuously monitors components against the NVD, OSV, and VEX feeds. Best used alongside DefectDojo: Dependency-Track for SCA/SBOM; DefectDojo for all other finding types. ### Commercial -- [kondukto](https://kondukto.io) - Instantly get all security testing tool results in a single view, automate vulnerability remediation workflows and manage risks with key security performance indicators (KPIs). +- [ArmorCode](https://www.armorcode.com/) — ASPM and vulnerability management aggregation platform. Aggregates from 100+ sources with risk-based prioritization and workflow automation. +- [Brinqa](https://www.brinqa.com/) — risk-based vulnerability management and correlation platform. Strong on contextual risk scoring and connecting findings to business assets and owners. --- ### Links -- [DefectDojo Supported Tools & Reports](https://defectdojo.github.io/django-DefectDojo/integrations/parsers/) -- [DefectDojo Model](https://defectdojo.github.io/django-DefectDojo/usage/models/) -- [Vulnerability Management Principles](https://www.tenable.com/principles/vulnerability-management-principles) - [^1]: Listed in alphabetical order. diff --git a/current-version/3-Governance/3-3-Reporting/3-3-3-ASPM.md b/current-version/3-Governance/3-3-Reporting/3-3-3-ASPM.md new file mode 100644 index 0000000..233cb7e --- /dev/null +++ b/current-version/3-Governance/3-3-Reporting/3-3-3-ASPM.md @@ -0,0 +1,193 @@ +# Application Security Posture Management (ASPM) + +As organizations adopted dozens of security scanners, they discovered a new problem: a flood of disconnected findings with no shared context, no deduplication, and no way to tell which issues actually matter. **Application Security Posture Management (ASPM)** answers this by continuously collecting, correlating, and contextualizing security data from across the entire software lifecycle — from source control to build to runtime — to maintain a single, live picture of application risk. + +## ASPM data model + +An ASPM platform ingests and normalizes data from many sources: + +| Data source | What it contributes | +|---|---| +| SAST scanners | Code-level vulnerability findings with file, line, and CWE | +| SCA scanners | Dependency CVEs with PURL, CVSS, and ecosystem | +| DAST scanners | Runtime-discovered vulnerabilities with URL, method, and evidence | +| Container scanners | Image CVEs with package name and layer | +| IaC scanners | Misconfiguration findings with resource type and policy ID | +| Secrets scanners | Secret types, locations, and exposure risk | +| SBOM feeds | Component inventory per artifact/service | +| Runtime telemetry | Which code paths are executed in production | +| Source control metadata | Repository, team, branch protection, last commit | +| Asset inventory | Service criticality, data classification, internet exposure, compliance scope | +| CISA KEV / EPSS | Real-world exploitability signals for prioritization | + +Each finding is normalized to a common schema: vulnerability identifier, affected asset, severity, source tool, discovery time, assigned owner, SLA status, and remediation state. This normalization is what makes cross-tool deduplication and comparison possible. + +## How ASPM deduplicates findings + +The same underlying vulnerability is routinely flagged by multiple tools. Without deduplication, a team sees three separate tickets with three separate fix requests: + +**Example: SQL injection in `UserRepository.java`, line 42** + +| Tool | Finding ID | Title | Severity | +|---|---|---|---| +| Semgrep (SAST) | SG-1041 | SQL injection via string concat | HIGH | +| Snyk Code (SAST) | SC-8822 | Unsanitized input in JDBC query | HIGH | +| Burp Suite (DAST) | BS-331 | SQL injection confirmed in `/api/users` | CRITICAL | + +Without ASPM: three separate tickets, three separate remediation requests, possible triple-counting in metrics. + +With ASPM deduplication: +1. Normalize all three to CWE-89 (SQL Injection). +2. Match by asset (`UserRepository.java`) and finding type (CWE-89). +3. Merge into one finding with three source references. +4. Elevate severity to CRITICAL (Burp confirmed it at runtime). +5. Assign to the owning team once; track one remediation workflow. + +The result: one actionable finding, higher-confidence severity (runtime confirmation), and accurate metrics that do not triple-count the same issue. + +## ASPM vs SIEM vs vulnerability management platform + +These three categories are often confused: + +| Platform | Primary purpose | Data it processes | Who uses it | +|---|---|---|---| +| **SIEM** | Security operations, threat detection, incident response | Logs, events, alerts, network flows | SOC analysts, IR teams | +| **Vulnerability Management** | Track and remediate infrastructure CVEs | Network scan results, agent-based CVEs, OS patches | IT security, sysadmins | +| **ASPM** | Application risk across the SDLC | SAST, SCA, DAST, container, IaC, SBOM, runtime | AppSec, development teams, security engineers | + +SIEM detects threats in real time using events. Vulnerability management tracks known exposures in infrastructure. ASPM manages risk in *applications* — the code, its dependencies, its containers, and its pipelines — with the developer team as the primary consumer. + +ASPM and SIEM are complementary: ASPM feeds enriched application risk context to the SIEM (which service has a known unpatched critical CVE currently exposed to the internet?), while the SIEM feeds runtime threat signals back to ASPM (this service is actively being probed — elevate its risk priority). + +## Risk score normalization across tools + +Different tools use different severity scales: +- CVSS (0–10 numeric) +- SAST tool-specific: Critical / High / Medium / Low +- DAST tools: P1 / P2 / P3 / P4 +- Cloud scanners: Critical / High / Medium / Low / Informational + +ASPM normalizes these to a common scale using: +1. **Base severity** — mapped to a common 4-level scale (Critical / High / Medium / Low). +2. **EPSS enrichment** — the probability this specific CVE is exploited in the wild within 30 days (0–100%). High EPSS elevates priority. +3. **CISA KEV** — if the CVE is on the Known Exploited Vulnerabilities catalog, it is treated as Critical regardless of CVSS. +4. **Reachability** — if the vulnerable code path is confirmed unreachable, the finding is deprioritized even if CVSS is high. +5. **Asset context** — internet-facing, PII-handling, or in-scope for PCI/HIPAA services carry a risk multiplier. + +The final risk score drives gate decisions, SLA assignment, and dashboard ranking — giving teams a single defensible prioritization that is consistent across all tools. + +## What ASPM does + +- **Aggregates and deduplicates** findings from SAST, SCA, secrets, IaC, DAST, container, and runtime tools into a single normalized inventory. +- **Correlates across the lifecycle** — links a finding in code to the build it shipped in and the workload running it in production. +- **Adds code-to-runtime context** — knows whether vulnerable code is reachable from an external entry point, whether the asset is internet-facing, what data classification it touches, and which team owns it. +- **Prioritizes by real risk** — combines CVSS, EPSS, CISA KEV, reachability, business criticality, and runtime exposure. +- **Maps ownership** — connects each risk to the team, service, and individual responsible, enabling direct assignment and accountability. + +## Why it matters + +Traditional scanning produces *findings*; ASPM produces *prioritized, owned, contextual risk*. This directly addresses the biggest failure mode of AppSec programs — **alert fatigue** — by cutting thousands of raw findings down to the few that are exploitable and reachable. + +A concrete example: a CVE with CVSS 9.8 in a logging library used only in a dev tool, with no network exposure, may rank below a CVSS 7.2 CVE in an auth service that is internet-facing and holds PII — because ASPM applies reachability and asset context that raw CVSS cannot. + +## ASPM for executive reporting + +ASPM is the primary data source for AppSec program reporting to leadership: + +**Executive dashboard (monthly):** +- Risk trend: total critical/high findings, open vs closed, week-over-week delta. +- Mean time to remediate (MTTR) by severity, by team, vs SLA target. +- Escape rate: findings discovered post-merge vs pre-merge (measures shift-left effectiveness). +- Risk by business unit or product line: which services carry the most unresolved risk. +- Compliance posture: percentage of in-scope services meeting security gate requirements. + +This is reportable in a single dashboard because ASPM aggregates from all sources. Without ASPM, this data must be manually compiled from 5–10 tool consoles, introducing inconsistency and lag. + +## Active vs passive ASPM + +- **Passive ASPM** aggregates and correlates findings into a unified view, provides prioritization, assigns ownership, and tracks remediation. This is the evolution of the [central vulnerability dashboard](3-3-2-Central-vulnerability-management-dashboard.md) — the same data, with much richer context. +- **Active ASPM** goes further: it continuously monitors posture, orchestrates scanners (triggering targeted scans when code changes), enforces policy (feeding [Security Gates](../../2-Process/2-3-Build/2-3-5-Security-Gates.md)), and drives remediation — increasingly with AI agents that triage, prioritize, propose fixes, or open pull requests with minimal human intervention. + +## Buy vs build + +**Build considerations:** +- Connecting 10+ scanner outputs with normalization, deduplication, and custom enrichment requires significant engineering — typically a 2–4 person-year initial investment. +- Open-source tools (DefectDojo) can get 60% of the way there; the remaining 40% (reachability, EPSS integration, runtime correlation) requires custom development. +- Best suited for organizations with a large AppSec engineering team and strong data engineering capability. + +**Buy considerations:** +- Commercial ASPM platforms (Apiiro, ArmorCode, Cycode, Legit Security) offer pre-built integrations for 100+ scanners, reachability analysis, and executive dashboards out of the box. +- Time-to-value is typically 4–8 weeks vs 6–18 months to build equivalent capability. +- Best suited for organizations that want to focus engineering capacity on remediation, not tooling. + +**Recommendation:** Start with DefectDojo for passive aggregation (free, immediate value). Evaluate commercial ASPM when you have 5+ scanner sources, more than 2 AppSec engineers, and are measuring false positive rates systematically. + +## How ASPM processes findings + +``` +Scanner A (SAST) ──┐ +Scanner B (SCA) ──┤ +Scanner C (DAST) ──┤──> Normalization ──> Deduplication ──> Enrichment ──> Prioritized Risk +Scanner D (runtime)─┤ (reachability, ──> Ownership +SBOM feeds ──┘ EPSS, KEV, ──> Workflow + asset context) +``` + +## Where ASPM fits in this guideline + +ASPM is the connective tissue across the pillars: it consumes the output of every Process-stage control and applies Governance-level prioritization and policy: + +- **People** — maps findings to owning teams; feeds developer-facing dashboards with actionable, high-signal work. +- **Process** — drives [Security Gates](../../2-Process/2-3-Build/2-3-5-Security-Gates.md) with correlated risk; feeds [Vulnerability Management](../../2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md) with prioritized queues. +- **Governance** — provides the structured evidence for [Compliance Auditing](../3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md) and the posture trends for [Tracking Maturities](3-3-1-Tracking-maturities.md). + +ASPM is how mature programs move from "running scanners" to "managing risk." + +## Maturity progression + +**Starter** — Individual scanner consoles, manual aggregation in a spreadsheet. Risk assessment is tool-specific and inconsistent. + +**Intermediate** — Central vulnerability management platform (DefectDojo, Dependency-Track) aggregating 5+ scanners. Deduplication configured. Ownership assigned. SLAs tracked. Executive dashboard published monthly. + +**Advanced** — Dedicated ASPM platform with full code-to-runtime correlation, reachability analysis, and EPSS/KEV enrichment. Security gates driven by ASPM output. AI-assisted triage and fix suggestions. Real-time posture dashboard for leadership. All compliance evidence auto-collected from ASPM data. + +## Common pitfalls + +- **Treating ASPM as a scanner** — ASPM needs data from many scanners to be effective. An ASPM with inputs from only two tools cannot produce meaningful correlation. +- **Skipping normalization** — feeding raw scanner severity levels without normalizing produces skewed prioritization. +- **No code-to-runtime linkage** — an ASPM that only aggregates static findings without runtime context is a better spreadsheet, not posture management. +- **ASPM owned by security only** — if development teams cannot see and act on ASPM output directly, it becomes another security reporting tool rather than a shared risk management layer. +- **Not tracking false positive rate** — if ASPM is not reducing noise vs. raw scanner output, the enrichment and deduplication are not working. Measure and improve. + +## Metrics + +| Metric | What it tells you | +|---|---| +| Mean time from finding to contextual prioritization | How quickly the platform enriches and ranks incoming findings | +| % of critical findings with reachability data | Depth of ASPM enrichment coverage | +| Risk reduction rate (findings closed / findings opened, per week) | Net direction of the overall risk posture | +| Findings with no assigned owner | Governance gaps; unowned findings rarely get fixed | +| False positive rate post-ASPM enrichment vs. raw scanner output | Value the platform adds in noise reduction | +| Coverage: % of services with ASPM data | Blind spots in the posture picture | +| Executive dashboard published on schedule | Governance discipline indicator | + +--- + +## Tools[^1] + +### Open-source + +- [OWASP DefectDojo](https://www.defectdojo.org/) — Findings aggregation and management with ASPM-adjacent capabilities: deduplication, SLA tracking, ownership, workflow integration, and rich API. The most accessible entry point for passive ASPM. Does not natively provide reachability analysis but integrates well with tools that do. Best first step for any team moving beyond per-tool consoles. + +### Commercial + +- [Apiiro](https://apiiro.com/) — Code-to-runtime application risk and ASPM. Builds a risk graph from code structure, secrets, PII handling, and logic changes through to runtime exposure. Strong risk-based code review prioritization. +- [ArmorCode](https://www.armorcode.com/) — ASPM platform aggregating and prioritizing findings across 100+ security tools. AI-assisted triage, SLA tracking, and bi-directional Jira integration. Strong for large enterprises managing many product teams. +- [Cycode](https://cycode.com/) — Complete ASPM across the software supply chain: source control, CI/CD, registries, and runtime. SBOM-anchored risk graph and code-to-production traceability. +- [Legit Security](https://www.legitsecurity.com/) — ASPM and software factory security posture. Focuses on pipeline and developer security risk alongside application findings. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/3-Governance/3-4-AI-Governance-and-Risk.md b/current-version/3-Governance/3-4-AI-Governance-and-Risk.md new file mode 100644 index 0000000..10c2fea --- /dev/null +++ b/current-version/3-Governance/3-4-AI-Governance-and-Risk.md @@ -0,0 +1,131 @@ +# AI Governance and Risk + +AI has become embedded across the software lifecycle — assistants generate code, models power product features, and agents act autonomously in pipelines. This creates new risks that traditional AppSec does not fully cover, and new governance obligations. AI governance establishes the policies, controls, and accountability for using AI **safely and responsibly** in both how you build software and what you ship. + +## Two faces of AI risk + +### 1. AI in the SDLC + +The use of AI coding assistants (GitHub Copilot, Cursor, Amazon Q, Claude) and AI agents in pipelines introduces risks at the development layer: + +- **Insecure generated code** — LLMs produce code with OWASP Top 10 flaws (injection, broken auth, insecure deserialization) at measurable rates. Studies show AI-generated code fails security review more often than human-written code on average when developers accept suggestions without scrutiny. +- **Hallucinated dependencies (slopsquatting)** — LLMs invent package names that do not exist, creating supply-chain risk if a malicious actor registers those names. +- **Data leakage to third-party models** — developers submitting proprietary code, PII, or credentials to external AI services may violate data protection obligations. +- **Prompt injection via code context** — malicious content in a codebase (e.g., a file deliberately crafted to manipulate an AI agent's actions) can redirect AI behavior in unexpected ways. + +See [IDE and AI-Assisted Development Security](../2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md) for controls. + +### 2. AI in the product + +Securing LLM- and ML-powered features you build and operate: + +- **Prompt injection** — malicious user input or content retrieved from external sources manipulates the model's behavior, causing it to bypass safety guardrails or take unauthorized actions. +- **Insecure output handling** — LLM output fed into downstream systems (code execution, SQL, shell commands) without sanitization becomes an injection vector. +- **Training-data poisoning** — adversarially crafted data introduced into training sets can cause models to behave incorrectly in specific, hard-to-detect ways. +- **Sensitive-information disclosure** — models can memorize and regurgitate training data, including PII or proprietary content. +- **Excessive agency** — AI agents granted broad permissions can cause significant harm when manipulated or malfunctioning. An agent with access to production databases and email should raise the same alarm as a human with the same access. +- **Model theft / inversion** — adversaries can extract model behavior or training data through repeated querying. + +## Key risk frameworks + +- **[OWASP Top 10 for LLM Applications](https://genai.owasp.org/)** — the canonical risks for LLM-based systems: prompt injection, insecure output handling, training-data poisoning, model denial of service, sensitive-information disclosure, excessive agency, and more. Map every LLM-powered feature against this list at design time. +- **[OWASP Machine Learning Security Top 10](https://owasp.org/www-project-machine-learning-security-top-10/)** — risks specific to ML systems: input manipulation (evasion), data poisoning, model inversion, membership inference, and model theft. +- **[NIST AI Risk Management Framework (AI RMF)](https://www.nist.gov/itl/ai-risk-management-framework)** — a structured approach to governing AI risk across four functions: Govern, Map, Measure, Manage. Aligns AI risk management with organizational risk appetite. +- **[ISO/IEC 42001](https://www.iso.org/standard/81230.html)** — AI management system standard, analogous to ISO 27001 for information security. Provides a framework for responsible AI development and deployment. +- **[EU AI Act](https://artificialintelligenceact.eu/)** — risk-based regulation classifying AI systems from minimal to unacceptable risk, with mandatory requirements (transparency, conformity assessment, human oversight) for high-risk systems. + +## Securing the ML pipeline (MLSecOps) + +Extend DevSecOps discipline to the model lifecycle — models and datasets are supply-chain artifacts and must be treated with the same rigor as code: + +- **Data and model provenance** — track where training data and pre-trained models come from. Record the source, version, and license. Use a model registry with immutable versioned artifacts, analogous to a container registry. +- **AI-BOM** — extend the [SBOM](../2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md) concept to inventory models, datasets, fine-tuning data, and their dependencies. CycloneDX supports AI/ML bill of materials extensions. +- **Scan model artifacts** — serialized model files (pickle, safetensors, ONNX) can carry malicious code that executes on deserialization. Scan all externally sourced model files before loading. Prefer safetensors format over pickle; avoid `torch.load` with untrusted sources. +- **Protect the inference path** — validate and sanitize all inputs before they reach the model. Rate-limit model endpoints. Log inputs and outputs for abuse monitoring and forensics. +- **Guardrails** — apply prompt-injection defenses (input filtering, output validation, instruction hierarchy), output filtering (content policy enforcement, PII redaction), and least-privilege for any agent that can take actions. +- **Adversarial testing** — red-team LLM-powered features specifically for prompt injection, jailbreaks, and misuse before launch and after model updates. Use tools like Garak for automated probing. + +## Governing AI use + +### AI usage policy + +Every organization using AI tools in the SDLC needs a policy that covers: + +- **Which tools are approved** — maintain an approved list and a process for evaluating new tools. Unapproved tools used for work data are shadow IT. +- **What data may be shared** — define clearly which data classifications may be sent to external AI models. Assume that data sent to a SaaS AI model may be retained and used for training unless explicitly contractually excluded. +- **Where enterprise or self-hosted options are required** — for source code, PII, and confidential business data, require enterprise-tier agreements with data isolation guarantees, or self-hosted/on-premises models. +- **How AI-generated code must be reviewed** — require that AI-generated code receives the same security review as human-written code. Establish that acceptance of AI suggestions is the accepting developer's responsibility. + +### Human accountability + +AI assists, but humans remain accountable for what is merged and shipped: + +- No AI-generated code is exempt from code review, security scanning, or testing. +- Require explicit sign-off for AI-generated security-critical code (authentication, authorization, cryptography). +- Document where AI is used in products and decisions — for transparency, for regulatory compliance, and to support post-incident investigation. + +### Limiting agency + +Constrain autonomous agents to the minimum permissions and actions required: + +| Control | Implementation | +|---|---| +| Least privilege | Scoped API keys; read-only where possible | +| Action allowlisting | Agent may only call defined tool functions | +| Human-in-the-loop | Require approval for irreversible actions | +| Audit trail | Log all agent decisions and tool calls | +| Kill switch | Ability to pause or revoke agent credentials immediately | + +### Transparency and oversight + +- Disclose to users when they are interacting with an AI system where legally required (EU AI Act, FTC guidance). +- Monitor model behavior in production for drift, misuse, and unexpected outputs. Anomalies in output patterns are early warning signs of prompt injection attacks or model degradation. +- Review AI-generated content policies and guardrails regularly as adversarial techniques evolve. + +## Maturity progression + +**Starter** — an AI usage policy that defines approved tools and data-sharing rules. SAST and SCA run on AI-generated code as on any other. Developers informed about AI-specific risks. + +**Intermediate** — enterprise AI tool agreements in place with data isolation. AI-BOM adopted for all internally-built AI features. LLM-powered features assessed against OWASP LLM Top 10 at design. Guardrails implemented. Adversarial testing before launch. + +**Advanced** — ML pipeline secured end-to-end with model provenance, artifact signing, and scanning. AI-BOM integrated into software supply chain and ASPM. Continuous monitoring of model behavior in production. Automated prompt-injection testing in CI for LLM features. Compliance with EU AI Act requirements for applicable risk categories. + +## Common pitfalls + +- **Trusting AI-generated code without review** — AI tools produce plausible-looking code that contains real vulnerabilities. The developer's responsibility for security does not diminish because a tool wrote the code. +- **No approved tool list** — without one, developers use whatever is convenient, often sending proprietary data to services with no data protection agreement. +- **Excessive agent permissions** — granting an AI agent admin credentials "because it's easier" creates a high-blast-radius target. Any agent that can delete data or send email is a significant risk if manipulated. +- **Treating LLM output as trusted** — LLM outputs that flow into downstream systems (databases, shell commands, APIs) without sanitization are injection vulnerabilities. +- **No data residency consideration for AI** — sending EU customer data to a US-based AI API may violate GDPR data transfer requirements. + +## Metrics + +| Metric | What it tells you | +|---|---| +| % of AI-generated code that passes security review on first submission | Developer ability to produce secure AI-assisted code | +| Number of unapproved AI tools in use (shadow AI) | Governance gap; indicates policy is not being followed | +| LLM-powered features assessed against OWASP LLM Top 10 (%) | Security coverage of AI product surface | +| Prompt injection findings in adversarial testing | Robustness of AI feature defenses | +| AI-BOM coverage (% of AI features with documented model/data inventory) | Supply-chain visibility for AI components | + +--- + +## Tools[^1] + +### Open-source + +- [Garak](https://github.com/NVIDIA/garak) — LLM vulnerability scanner. Probes LLM-powered applications for prompt injection, jailbreaks, data leakage, and more using hundreds of built-in attack probes. Use in CI for LLM-powered features. +- [ModelScan](https://github.com/protectai/modelscan) — scans ML model files (pickle, HDF5, Keras, PyTorch, TensorFlow SavedModel) for unsafe code that executes on deserialization. Run on all externally sourced model artifacts. +- [NeMo Guardrails](https://github.com/NVIDIA/NeMo-Guardrails) — toolkit for adding programmable guardrails to LLM applications: topic restrictions, output filtering, and dialog flow control. Supports multiple LLM backends. +- [PyRIT](https://github.com/Azure/PyRIT) — Python Risk Identification Toolkit for generative AI (by Microsoft). Automates red-teaming of LLM applications at scale. + +### Commercial + +- [HiddenLayer](https://hiddenlayer.com/) — security platform for AI/ML models: model scanning, adversarial attack detection at inference time, and model behavior monitoring. +- [Protect AI](https://protectai.com/) — security and governance for the AI/ML lifecycle. Covers model scanning (via ModelScan), supply chain security, and LLM guardrails. + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/README.md b/current-version/README.md index 279a01d..1013999 100644 --- a/current-version/README.md +++ b/current-version/README.md @@ -1,73 +1,86 @@ # OWASP DevSecOps Guideline -This is the updated version of the DevSecOps Guideline. In this version, we have revised our documentation approach to provide a more structured format. The primary focus of this restructuring was on the core pillars of DevSecOps, which include: +This is the current version of the OWASP DevSecOps Guideline. It explains how to build and operate a secure software delivery pipeline, promotes a **shift-left** (shift-everywhere) security culture, and curates vendor-neutral practices and tools for organizations of any size. -- People -- Process -- Governance +The guideline is organized around the three core pillars of DevSecOps: -Under the Process section, we have conducted a detailed examination of the product development process and have divided it into the following seven steps: +- **People** — teams, roles, culture, and training. +- **Process** — security activities woven into every stage of the software development lifecycle. +- **Governance** — compliance, measurement, reporting, and oversight. -- Design -- Develop -- Build -- Test -- Release -- Deploy -- Operate - -The following image can illustrate it better. +Under **Process**, the product development lifecycle is divided into seven stages: **Design, Develop, Build, Test, Release, Deploy, Operate** — with security controls mapped to each. ![DevSecOps Pillars](/current-version/assets/images/devsecops-pillars.png) -If you need the old verions please check [old-versions](../old-versions/) directory. +This revision refreshes every topic for 2025/2026 and adds coverage of modern concerns: software supply-chain security (SBOM, signing/provenance, CI/CD pipeline security), AI-assisted development and AI governance, Application Security Posture Management (ASPM), and explicit alignment with frameworks such as NIST SSDF, OWASP SAMM, OWASP DSOMM, and SLSA. + +If you need earlier editions, see the [old-versions](../old-versions/) directory. ## Table of Contents - [0-Intro](0-Intro) - [0-1-Intro](0-Intro/0-1-Intro.md) - [0-2-Overview](0-Intro/0-2-Overview.md) + - [0-3-Frameworks-and-Standards](0-Intro/0-3-Frameworks-and-Standards.md) - [1-People](1-People) - [1-1-Shape-the-team](1-People/1-1-Shape-the-team) - [1-1-1-Security-champions](1-People/1-1-Shape-the-team/1-1-1-Security-champions.md) + - [1-1-2-Roles-and-Responsibilities](1-People/1-1-Shape-the-team/1-1-2-Roles-and-Responsibilities.md) - [1-2-Training](1-People/1-2-Training) - [1-2-1-Secure-coding](1-People/1-2-Training/1-2-1-Secure-coding.md) - [1-2-2-Security-CICD](1-People/1-2-Training/1-2-2-Security-CICD.md) + - [1-2-3-Security-culture-and-awareness](1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md) - [2-Process](2-Process) - [2-1-Design](2-Process/2-1-Design) - [2-1-1-Threat-modeling](2-Process/2-1-Design/2-1-1-Threat-modeling.md) - - [2-2-Code](2-Process/2-2-Code) - - [2-2-3-Interactive-Application-Security-Testing](2-Process/2-2-Code/2-2-3-Interactive-Application-Security-Testing.md) - - [2-2-1-Pre-commit](2-Process/2-2-Code/2-2-1-Pre-commit) - - [2-2-1-1-Pre-commit](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md) - - [2-2-1-2-Secrets-Management](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md) - - [2-2-1-3-Linting-code](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-3-Linting-code.md) - - [2-2-1-4-Repository-Hardening](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md) - - [2-2-2-Static-Analysis](2-Process/2-2-Code/2-2-2-Static-Analysis) - - [2-2-2-1-Static-Application-Security-Testing](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-1-Static-Application-Security-Testing.md) - - [2-2-2-2-Software-Composition-Analysis](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-2-Software-Composition-Analysis.md) - - [2-2-2-3-Infastructure-as-Code-Scanning](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-3-Infastructure-as-Code-Scanning.md) - - [2-2-2-4-Container-Security](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-4-Container-Security) - - [2-2-2-4-1-Container-Scanning](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-4-Container-Security/2-2-2-4-1-Container-Scanning.md) - - [2-2-2-4-2-Container-Hardening](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-4-Container-Security/2-2-2-4-2-Container-Hardening.md) + - [2-1-2-Secure-design-and-requirements](2-Process/2-1-Design/2-1-2-Secure-design-and-requirements.md) + - [2-2-Develop](2-Process/2-2-Develop) + - [2-2-1-Pre-commit](2-Process/2-2-Develop/2-2-1-Pre-commit) + - [2-2-1-1-Pre-commit](2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md) + - [2-2-1-2-Secrets-Management](2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md) + - [2-2-1-3-Linting-code](2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md) + - [2-2-1-4-Repository-Hardening](2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md) + - [2-2-2-IDE-and-AI-assisted-development](2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md) - [2-3-Build](2-Process/2-3-Build) - - [2-3-1-Dynamic-Application-Security-Testing](2-Process/2-3-Build/2-3-1-Dynamic-Application-Security-Testing.md) - - [2-3-2-Mobile-Application-Security-Test](2-Process/2-3-Build/2-3-2-Mobile-Application-Security-Test.md) - - [2-3-3-API-Security](2-Process/2-3-Build/2-3-3-API-Security.md) - - [2-3-4-Miss-Configuration-Check](2-Process/2-3-Build/2-3-4-Miss-Configuration-Check.md) - - [2-4-Operation](2-Process/2-4-Operation) - - [2-4-1-Cloud-Native-Security](2-Process/2-4-Operation/2-4-1-Cloud-Native-Security.md) - - [2-4-2-Logging-and-Monitoring](2-Process/2-4-Operation/2-4-2-Logging-and-Monitoring.md) - - [2-4-3-Pentest](2-Process/2-4-Operation/2-4-3-Pentest.md) - - [2-4-4-Vulnerability-Management](2-Process/2-4-Operation/2-4-4-Vulnerability-Management.md) - - [2-4-5-VDP|Bug-bounty](2-Process/2-4-Operation/2-4-5-VDP|Bug-bounty.md) - - [2-4-6-Breach-and-attack-simulation](2-Process/2-4-Operation/2-4-6-Breach-and-attack-simulation.md) + - [2-3-1-Static-Analysis](2-Process/2-3-Build/2-3-1-Static-Analysis) + - [2-3-1-1-Static-Application-Security-Testing](2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md) + - [2-3-2-Software-Composition-Analysis](2-Process/2-3-Build/2-3-2-Software-Composition-Analysis) + - [2-3-2-1-Software-Composition-Analysis](2-Process/2-3-Build/2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md) + - [2-3-3-Container-Security](2-Process/2-3-Build/2-3-3-Container-Security) + - [2-3-3-1-Container-Scanning](2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md) + - [2-3-3-2-Container-Hardening](2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md) + - [2-3-4-Infrastructure-as-Code-Security](2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security) + - [2-3-4-1-Infrastructure-as-Code-Scanning](2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md) + - [2-3-5-Security-Gates](2-Process/2-3-Build/2-3-5-Security-Gates.md) + - [2-3-6-Supply-Chain-Security](2-Process/2-3-Build/2-3-6-Supply-Chain-Security) + - [2-3-6-1-SBOM](2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md) + - [2-3-6-2-Artifact-Signing-and-Provenance](2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md) + - [2-3-6-3-CICD-Pipeline-Security](2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md) + - [2-4-Test](2-Process/2-4-Test) + - [2-4-1-Interactive-Application-Security-Testing](2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md) + - [2-4-2-Dynamic-Application-Security-Testing](2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md) + - [2-4-3-Mobile-Application-Security-Test](2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md) + - [2-4-4-API-Security](2-Process/2-4-Test/2-4-4-API-Security.md) + - [2-4-5-Misconfiguration-Check](2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md) + - [2-5-Release](2-Process/2-5-Release) + - [2-5-1-Release](2-Process/2-5-Release/2-5-1-Release.md) + - [2-6-Deploy](2-Process/2-6-Deploy) + - [2-6-1-Deploy](2-Process/2-6-Deploy/2-6-1-Deploy.md) + - [2-7-Operate](2-Process/2-7-Operate) + - [2-7-1-Cloud-Native-Security](2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md) + - [2-7-2-Logging-and-Monitoring](2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md) + - [2-7-3-Pentest](2-Process/2-7-Operate/2-7-3-Pentest.md) + - [2-7-4-Vulnerability-Management](2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md) + - [2-7-5-VDP-and-Bug-bounty](2-Process/2-7-Operate/2-7-5-VDP-and-Bug-bounty.md) + - [2-7-6-Breach-and-attack-simulation](2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md) - [3-Governance](3-Governance) - - [3-2-Data-protection](3-Governance/3-2-Data-protection.md) - [3-1-Compliance-Auditing](3-Governance/3-1-Compliance-Auditing) - [3-1-1-Compliance-Auditing](3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md) - [3-1-2-Policy-as-code](3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md) - [3-1-3-Security-benchmarking](3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md) + - [3-2-Data-protection](3-Governance/3-2-Data-protection.md) - [3-3-Reporting](3-Governance/3-3-Reporting) - [3-3-1-Tracking-maturities](3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md) - [3-3-2-Central-vulnerability-management-dashboard](3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md) + - [3-3-3-ASPM](3-Governance/3-3-Reporting/3-3-3-ASPM.md) + - [3-4-AI-Governance-and-Risk](3-Governance/3-4-AI-Governance-and-Risk.md) diff --git a/doc-utilities/scripts/toc.md b/doc-utilities/scripts/toc.md index bf591ff..430ba14 100644 --- a/doc-utilities/scripts/toc.md +++ b/doc-utilities/scripts/toc.md @@ -1,16 +1,21 @@ - [0-Intro](current-version/0-Intro) - [0-1-Intro](current-version/0-Intro/0-1-Intro.md) - [0-2-Overview](current-version/0-Intro/0-2-Overview.md) + - [0-3-Frameworks-and-Standards](current-version/0-Intro/0-3-Frameworks-and-Standards.md) - [1-People](current-version/1-People) - [1-1-Shape-the-team](current-version/1-People/1-1-Shape-the-team) - [1-1-1-Security-champions](current-version/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md) + - [1-1-2-Roles-and-Responsibilities](current-version/1-People/1-1-Shape-the-team/1-1-2-Roles-and-Responsibilities.md) - [1-2-Training](current-version/1-People/1-2-Training) - [1-2-1-Secure-coding](current-version/1-People/1-2-Training/1-2-1-Secure-coding.md) - [1-2-2-Security-CICD](current-version/1-People/1-2-Training/1-2-2-Security-CICD.md) + - [1-2-3-Security-culture-and-awareness](current-version/1-People/1-2-Training/1-2-3-Security-culture-and-awareness.md) - [2-Process](current-version/2-Process) - [2-1-Design](current-version/2-Process/2-1-Design) - [2-1-1-Threat-modeling](current-version/2-Process/2-1-Design/2-1-1-Threat-modeling.md) + - [2-1-2-Secure-design-and-requirements](current-version/2-Process/2-1-Design/2-1-2-Secure-design-and-requirements.md) - [2-2-Develop](current-version/2-Process/2-2-Develop) + - [2-2-2-IDE-and-AI-assisted-development](current-version/2-Process/2-2-Develop/2-2-2-IDE-and-AI-assisted-development.md) - [2-2-1-Pre-commit](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit) - [2-2-1-1-Pre-commit](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md) - [2-2-1-2-Secrets-Management](current-version/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md) @@ -20,13 +25,17 @@ - [2-3-5-Security-Gates](current-version/2-Process/2-3-Build/2-3-5-Security-Gates.md) - [2-3-1-Static-Analysis](current-version/2-Process/2-3-Build/2-3-1-Static-Analysis) - [2-3-1-1-Static-Application-Security-Testing](current-version/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md) - - [2-3-2-Software Composition Analysis](current-version/2-Process/2-3-Build/2-3-2-Software Composition Analysis) - - [2-3-2-1-Software-Composition-Analysis](current-version/2-Process/2-3-Build/2-3-2-Software Composition Analysis/2-3-2-1-Software-Composition-Analysis.md) + - [2-3-2-Software-Composition-Analysis](current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis) + - [2-3-2-1-Software-Composition-Analysis](current-version/2-Process/2-3-Build/2-3-2-Software-Composition-Analysis/2-3-2-1-Software-Composition-Analysis.md) - [2-3-3-Container-Security](current-version/2-Process/2-3-Build/2-3-3-Container-Security) - [2-3-3-1-Container-Scanning](current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md) - [2-3-3-2-Container-Hardening](current-version/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md) - - [2-3-4-Infrastructure as Code Security](current-version/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security) - - [2-3-1-3-Infastructure-as-Code-Scanning](current-version/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security/2-3-1-3-Infastructure-as-Code-Scanning.md) + - [2-3-4-Infrastructure-as-Code-Security](current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security) + - [2-3-4-1-Infrastructure-as-Code-Scanning](current-version/2-Process/2-3-Build/2-3-4-Infrastructure-as-Code-Security/2-3-4-1-Infrastructure-as-Code-Scanning.md) + - [2-3-6-Supply-Chain-Security](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security) + - [2-3-6-1-SBOM](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-1-SBOM.md) + - [2-3-6-2-Artifact-Signing-and-Provenance](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-2-Artifact-Signing-and-Provenance.md) + - [2-3-6-3-CICD-Pipeline-Security](current-version/2-Process/2-3-Build/2-3-6-Supply-Chain-Security/2-3-6-3-CICD-Pipeline-Security.md) - [2-4-Test](current-version/2-Process/2-4-Test) - [2-4-1-Interactive-Application-Security-Testing](current-version/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md) - [2-4-2-Dynamic-Application-Security-Testing](current-version/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md) @@ -42,9 +51,11 @@ - [2-7-2-Logging-and-Monitoring](current-version/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md) - [2-7-3-Pentest](current-version/2-Process/2-7-Operate/2-7-3-Pentest.md) - [2-7-4-Vulnerability-Management](current-version/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md) + - [2-7-5-VDP-and-Bug-bounty](current-version/2-Process/2-7-Operate/2-7-5-VDP-and-Bug-bounty.md) - [2-7-6-Breach-and-attack-simulation](current-version/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md) - [3-Governance](current-version/3-Governance) - [3-2-Data-protection](current-version/3-Governance/3-2-Data-protection.md) + - [3-4-AI-Governance-and-Risk](current-version/3-Governance/3-4-AI-Governance-and-Risk.md) - [3-1-Compliance-Auditing](current-version/3-Governance/3-1-Compliance-Auditing) - [3-1-1-Compliance-Auditing](current-version/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md) - [3-1-2-Policy-as-code](current-version/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md) @@ -52,3 +63,4 @@ - [3-3-Reporting](current-version/3-Governance/3-3-Reporting) - [3-3-1-Tracking-maturities](current-version/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md) - [3-3-2-Central-vulnerability-management-dashboard](current-version/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md) + - [3-3-3-ASPM](current-version/3-Governance/3-3-Reporting/3-3-3-ASPM.md) diff --git a/old-versions/V0.3/0-Intro/0-1-Intro.md b/old-versions/V0.3/0-Intro/0-1-Intro.md new file mode 100644 index 0000000..376a71d --- /dev/null +++ b/old-versions/V0.3/0-Intro/0-1-Intro.md @@ -0,0 +1,25 @@ +# Introduction to the OWASP DevSecOps Guideline + +The OWASP DevSecOps Guideline explains how we can transition from a traditional approach to achieving security that starts with requirements and ends with security testing to an approach that brings together Development, Security, and Operations throughout the software lifecycle -- a "DevSecOps" approach. + +This project's goal is to help companies of any size to add security to their DevOps pipeline and culture. There is no one **right** way to do DevSecOps, so it's important to stay focused. + +DevSecOps strives to **"produce demonstrably secure code"** by: + +- leveraging automation to create short feedback loops to developers +- breaking down the silos between development, security, and operations +- breaking down security work into small pieces to create flow +- making decisions based on threat intelligence from operations +- establishing a culture of security experimentation and learning + +There are tools to support security processes across the software development lifecycle. Every company should have processes in place to ensure: + +- **Custom Code Security** - your custom code has the right defenses and is free from vulnerabilities, including applications, APIs, serverless, mobile, infrastructure as code, etc... +- **Supply Chain Security** - your platform, framework, libraries, containers, and other components +- **Runtime Protection** - you detect attacks on your software and prevent them from being exploited + +If you do these three processes well, you will be in relatively good shape in terms of application security. In this document, we will explore a variety of automated solutions that can help you implement these three processes. + +The goal is not to use all of the tools in your pipeline. The goal is to ensure secure code emerges from your pipeline. You need to pick and choose the tools that are effective with your organization's people, process, technology, and culture. You will very likely want to use each tool for what it is best at, rather than repeating all tests with all tools. Of course, every software development organization is different and you are free to select tools and the exact location where you want to implement the tools. + +![Secure Pipeline](/current-version/assets/images/Pipeline-view.png) diff --git a/old-versions/V0.3/0-Intro/0-2-Overview.md b/old-versions/V0.3/0-Intro/0-2-Overview.md new file mode 100644 index 0000000..b3fc2e0 --- /dev/null +++ b/old-versions/V0.3/0-Intro/0-2-Overview.md @@ -0,0 +1,106 @@ +# DevSecOps Intro + +Today, DevOps is empowering any organizations to deploy changes to production environments at blazing rates. +Since time to deliver is so important feature during this process, the main question for a security person is +"How I can secure this process?" or "How much our deliverable products are secure?". +In this regard, we can embed some security-related steps entire our DevOps process to perform some automated tests. +So considering the DevSecOps or secure DevOps culture helps us to promote the shift-left security strategy in our company, +at least in the tech department. + +## What's the Shift-left security strategy? + +As a simple definition, the shift-left security strategy is a way or solution to embedding security as a part of our development process +and consider security from the inception steps of application or system design. +In other words, security is responsible for everyone who works in the software development and operating process. +Of course, security is a profession and we need highly skilled people to play security-related roles; +but in this approach, any designer, software architecture, developer, DevOps engineer, and ... together with security guys have liability about security. + +## Dev+Sec+Ops + +![DevSecOps Venn Diagram](/current-version/assets/images/DevSecOps.png) + +Suppose that these 3 different areas for covering each other is something like the image, +so in conclusion with the above words, we need to implement some tools and working on promoting a DevSecOps culture too. + +As Shannon Lietz - founder at DevSecOps foundation - said: + +> The purpose and intent of DevSecOps is to build on the mindset that +> "everyone is responsible for security" with the goal of safely distributing +> security decisions at speed and scale to those who hold the highest level of +> context without sacrificing the safety required." + +## The DevSecOps culture + +As you heard before we want to talk about the Shift-left security. +It means we should consider security from design (in a simple definition) which target is moving security earlier in the development process. + +Let's suppose that you are working in a DevOps team and you are traditionally doing security test +(yes, end of all QA tests and before going to production), what happens? +Well, all bugs should be fixed ASAP, Developer team is under pressure to fix issues, +QA tests should be performed again, and security test again. +This means that the costs, money and time, increase. +In the end, you sacrifice agility for security things do not like a business team. + +The solution is introducing security earlier in the process instead of having it in the final steps. +Considering security in design by threat modeling and +break down huge security tests in smaller security testing and integrating them in the development pipeline. + +The following picture shows the differences between DevOps and DevSecOps lifecycles. + +![DevOps vs DevSecOps](/current-version/assets/images/DevOps-vs-DevSecOps.png) + +## Privacy + +Privacy has become a major topic for companies of all sizes, since GDPR (Europe’s General Data Protection Regulations), CCPA (California Consumer Privacy Act), LGPD – Brazil’s Lei Geral de Proteção de Dados, and other laws and regulations are being enforced around the world. + +Applications that will process a large volume of PII (personally identifiable information) should adapt the DevSecOps to follow the Privacy by Design approach, where the development process addresses privacy concerns thru the whole cycle. + +## Software testing strategies + +When, we talk about testing we should have in mind +we have different definitions in testing which is can change our route to achieving +a secure DevSecOps cycle. +Let's take look into this definitions. + +### Different software testing strategies + +1. **Positive testing** + + Positive testing assumes that, under normal conditions and inputs, + everything will behave as expected. + It is performed with the assumption that only valid and relevant things will happen: + data set and all other functionalities will be as expected. + +2. **Negative testing** + + Negative testing checks the system behavior under unexpected conditions. + Negative testing plays a much important role in high-performance software development: + it checks the software behavior under unexpected conditions and inputs. + +#### Methods of testing + +1. **Static testing** + + Static Testing checks software defects without executing the application code. + It is performed in the early stage of development to avoid errors, as it is easier to find sources of failures and it can be fixed easily. + Some issues that can’t be found using Dynamic Testing, can be easily found by Static Testing. Such issues consists of hard coded credentials, deprecated encryption algorithms, 2nd order injections, weak random, etc. + Most static analysis tools have the testing scope limited to one component and can not perform tests across different components. (EG. for a microservice architecture, static analysis tools will test each microservice independently) + ![Static testing](/current-version/assets/images/sast_scanning.png) + +2. **Dynamic testing** + + Dynamic Testing analyzes the behavior of the application code at runtime. Scanners send specially crafted requests to the target application. Request parameters are constantly modified during testing to try and expose a range of vulnerabilities. Based on the response of the application the tool can then identify potential vulnerabilities and report back. Some issues that can't be found by static analysis are easily detected by dynamic analysis. Such issues include client side vulnerabilities like authentication & session issues, sensitive data sent in plain text, etc. + Dynamic analysis tools have the possibility of testing the entire application flow(multiple components at once). (Eg. for a microservice architecture, dynamic analysis tools can point to one microservice, but as they interact with each other results will represent the behaviour of the entire application) + ![Dynamic testing](/current-version/assets/images/dast_scanning.png) + +3. **Interactive analysis** + + Also known as Interactive Application Security Testig (IAST) monitors the application while other systems interact with it and observe vulnerabilities. This is achieved via sensors or agents deploy with the application. The sensors can see the entire flow from HTTP request down to the executed code, tracing the data through the application. Similar to static analysis, it can test one component at a time, but not multiple components. However, if agents/sensors are deployed on all components, when they interact with eachother this could reveal vulnerabilities in each component used in the application. (Eg. for a microservice architecture, only the microservices that have agents/sensors attached will report vulnerabilities) + ![Interactive analysis](/current-version/assets/images/iast_analysis.png) + +--- + +#### References + +1. +2. diff --git a/old-versions/V0.3/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md b/old-versions/V0.3/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md new file mode 100644 index 0000000..c6a9e7a --- /dev/null +++ b/old-versions/V0.3/1-People/1-1-Shape-the-team/1-1-1-Security-champions.md @@ -0,0 +1 @@ +# Security Champions diff --git a/old-versions/V0.3/1-People/1-2-Training/1-2-1-Secure-coding.md b/old-versions/V0.3/1-People/1-2-Training/1-2-1-Secure-coding.md new file mode 100644 index 0000000..c1154a9 --- /dev/null +++ b/old-versions/V0.3/1-People/1-2-Training/1-2-1-Secure-coding.md @@ -0,0 +1 @@ +# Secure Coding diff --git a/old-versions/V0.3/1-People/1-2-Training/1-2-2-Security-CICD.md b/old-versions/V0.3/1-People/1-2-Training/1-2-2-Security-CICD.md new file mode 100644 index 0000000..7ae487a --- /dev/null +++ b/old-versions/V0.3/1-People/1-2-Training/1-2-2-Security-CICD.md @@ -0,0 +1 @@ +# Security CICD diff --git a/old-versions/V0.3/2-Process/2-1-Design/2-1-1-Threat-modeling.md b/old-versions/V0.3/2-Process/2-1-Design/2-1-1-Threat-modeling.md new file mode 100644 index 0000000..459cd79 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-1-Design/2-1-1-Threat-modeling.md @@ -0,0 +1,168 @@ +# Threat Modeling + +Threat modeling is a crucial component of the DevSecOps approach, focused on identifying and managing risks in a structured way. Here’s a more detailed look at this topic: + +## What is Threat Modeling? + +Threat modeling involves enumerating all potential attack vectors on an application, producing a list of threat scenarios along with mitigations. This holistic and collaborative process ensures comprehensive coverage of potential threats. + +Another important note is that Threat Modeling is a **Collaborative** and **Repeatable** process and it is a process **NOT** a project! + +### Key Outputs + +- **System Diagrams:** Detailed representations of the architecture and data flows. +- **Security Requirements:** Specific criteria for safeguarding the system. +- **Threat List:** Catalog of potential threats with mitigation strategies. + +### Terms + +- **Weakness:** A software defect or bug. (e.g., input validation errors, missing user email validation) +- **Vulnerability:** A weakness that can be exploited. (Ex: we can abuse the user email field to insert SQL statements) +- **Attack:** Exploitation of vulnerabilities. + - **Target:** The objective of the attack (e.g., sensitive data). + - **Attack Vector:** The path that the attacker can take to exploit a vulnerability (e.g., web interface). + - **Threat Actor:** The threat source (e.g., hacker, insider). +- **Attack Surface:** Anything that can be obtained, used, or attacked by a threat actor. +- **Risk:** Impact and likelihood of a threat being exploited (Risk = Impact x Likelihood). + - **Impact:** Size of negative consequences that each risk brings. + - **Likelihood:** Probability of a risk to happen. +- **Approach:** Describes how one could start with the process. +- **Methodology:** Describes the process itself. + +## Why Threat Modeling? + +As benefits ofthreat modeling, we can say: + +- **Proactive Threat Identification:** Early discovery of potential security issues. +- **Cost Efficiency:** Mitigating threats early reduces remediation costs. +- **Prioritization:** Focus on the most critical vulnerabilities. +- **System Understanding:** Better comprehension of system interactions and data flows. + +## Who should be involved in the threat modeling? + +- **Architect:** Knows how the application has been designed and how data flows across to ensure proper design and flow. +- **Developer:** Knows how the application was built, and the interactions between components to provide insight into code and interactions. +- **Tester:** Knows the requirements, and what the application is supposed to do, to validate requirements and behavior. +- **Security expert:** Knows about specific attack factors and vulnerabilities to identify and assess security risks. + +But, the best answer to this question is, **it depends on the organization**. + +## When to perform Threat modeling? + +Ideally, Threat Modeling should be performed early in the software design process. This allows for easier and cheaper fixes. + +In an Agile environment, Threat Modeling should be done during each sprint. But, we do not have to start from scratch each time. Each sprint only requires an iteration of the previous threat model output. + +## Selecting the Right Approach & Methodology + +### Common Methodologies + +Common Threat Modeling methodologies are: + +- **PASTA (Process for Attack Simulation and Threat Analysis):** Focuses on business impact. +- **Microsoft Threat Modeling:** Uses data flow diagrams (DFDs) to identify threats. +- **OCTAVE (Operationally Critical Threat, Asset, and Vulnerability Evaluation):** Emphasizes organizational risk. +- **TRIKE:** A security auditing framework. +- **VAST (Visual, Agile, and Simple Threat):** Supports Agile development with automation. + +## Approaches + +| **Approach** | **Steps** | +|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Asset-Centric** | 1. Identify and classify assets.
2. Diagram components and data flows.
3. Identify threats specific to each element. | +| **Attacker-Centric** | 1. Define potential threat actors (e.g., insiders, external hackers).
2. Determine their motives, means, and opportunities.
3. List and prioritize potential threats. | +| **Application-Centric** | 1. Create detailed diagrams of the application.
2. Identify threats for each element.
3. Use threat classification models (e.g., STRIDE, OWASP Top 10).
4. Rank threats using risk classification models (e.g., DREAD - Damage, Reproducibility, Exploitability, Affected Users, Discoverability). | + +## Detailed Steps for Each Approach + +### Asset-Centric + +1. Asset Identification: + - List all assets, including data, software, and hardware. + - Classify assets based on their criticality and sensitivity. +2. Component Diagramming: + - Use data flow diagrams (DFDs) to map out interactions. + - Highlight trust boundaries and data entry points. +3. Threat Identification: + - Analyze each component for possible threats. + - Use tools like Microsoft Threat Modeling Tool to automate threat discovery. +4. Threat Mitigation: + - Develop specific countermeasures for each identified threat. + - Prioritize mitigations based on risk assessment. + +### Attacker-Centric + +1. Threat Actor Identification: + - Identify potential attackers (e.g., external hackers, malicious insiders). + - Categorize actors by their access level and intent. +2. Attacker Profiling: + - Understand attackers’ goals and capabilities. + - Use threat intelligence sources to gather information about typical attack methods. +3. Threat Enumeration: + - List potential attack scenarios. + - Use attack trees to map out how an attacker might exploit vulnerabilities. +4. Threat Mitigation: + - Implement defenses like intrusion detection systems, access controls, and encryption. + - Regularly update threat profiles and defenses based on new intelligence. + +### Application-Centric + +1. Application Diagramming: + - Create detailed architecture diagrams. + - Include data flows, components, and interactions. +2. Threat Identification: + - Apply models like STRIDE or OWASP Top 10 to each component. + - Identify threats such as spoofing, tampering, and data breaches. +3. Risk Assessment: + - Use the DREAD model to evaluate threats. + - Rank threats based on their potential impact and exploitability. +4. Threat Mitigation: + - Develop countermeasures for high-risk threats. + - Implement secure coding practices and conduct regular security reviews. + +## What is DREAD? + +DREAD is a risk assessment model used in cybersecurity to evaluate and prioritize potential threats. The acronym stands for: + +- **Damage potential:** Assessing the potential damage that could result from a successful exploit. +- **Reproducibility:** Evaluating how easily the exploit can be replicated. +- **Exploitability:** Determining the ease with which the vulnerability can be exploited. +- **Affected users:** Identifying the number of users or systems affected by the vulnerability. +- **Discoverability:** Assessing how easily the vulnerability can be discovered. + +Each of these factors is typically scored on a scale, often from 0 to 10, with higher scores indicating a greater level of risk. + +## Practical Steps for Threat Modeling + +1. **Define Scope:** Identify boundaries of the system and critical assets. +2. **Create Diagrams:** Develop DFDs and architecture diagrams. +3. **Identify Threats:** Use methodologies like STRIDE to discover potential threats. +4. **Analyze Threats:** Assess risk using models like DREAD. +5. **Develop Mitigations:** Define strategies to mitigate identified threats. +6. **Review and Iterate:** Regularly update the threat model throughout the development lifecycle. + +--- + +## Tools[^1] + +### Open-source + +- [CAIRIS](https://cairis.org/): A tool for building models and conducting risk assessments based on these models. +- [Microsoft Threat Modeling Tool](https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool) - A tool for creating data flow diagrams and identifying threats using STRIDE. +- [OWASP Threat Dragon](https://owasp.org/www-project-threat-dragon/) - An open-source tool for creating threat model diagrams and managing threats. +- [threat-composer](https://github.com/awslabs/threat-composer?tab=readme-ov-file) - A simple threat modeling tool to help humans to reduce time-to-value when threat modeling. + +### Commercial + +- [IriusRisk](https://www.iriusrisk.com/threat-modeling-platform) - A platform for automated threat modeling and risk management. +- [ThreatModeler](https://threatmodeler.com/) - An enterprise-grade tool for automated threat modeling, integrating with CI/CD pipelines. + +--- + +### Links + +- [Awesome Threat Modeling](https://github.com/hysnsec/awesome-threat-modelling) +- [OWASP - Threat Modeling](https://owasp.org/www-community/Threat_Modeling) +- [Threat Modeling Cheat Sheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Threat_Modeling_Cheat_Sheet.md) + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md new file mode 100644 index 0000000..5ac88a2 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md @@ -0,0 +1,34 @@ +# Pre-commit + +The Pre-commit phase is important because it can prevent security issues before they are submitted to a central (Git) repository. + +Making sure that there are no secrets in the code, and that the code follows certain guidelines (According to the Linter rules) will result in a higher quality code. + +In the following, we take a look into different types of pre-commit actions that are as follows: + +1. Secrets Management +2. Linting Code + +**Pre-commit** is a git feature that can be leveraged as part of the **shift-left security** approach where the developers are empowered to view the issues in the source code earlier in the SDLC process. When the developer runs a git-commit command to commit the code into their local repository, **pre-commit hook** check can be integrated with a security scanning tool executed to look for code quality issues, hard-coded secrets, insecure code, vulnerable dependencies/opensource libraries, etc.. + +It is to be noted that pre-commit hooks are at the developer's local repository level and not the remote repository commonly used by all the developers working on the same project/application. In such cases when it's required to prevent security issues before they are submitted to a remote/central (Git) repository **pre-push hook** or **git-push** checks can be configured. Refer: + +Another alternative approach to scan the source code for security issues (such as hardcoded-secrets, insecure code and vulnerable dependencies/opensource libraries) is the use of **SAST/SCA IDE plugins**. This works together with the IDEs used by developers while they write the code. Whereas, git-commit and git-push actions are used after the code is written by the developer. It is necessary to discern these distinct use-cases in order to implement the proper security controls at various levels based on the requirement. + +The following image can give you a better view of what the pre-commit means and why we must consider it. + +![Pre Commit](/current-version/assets/images/pre-commit.png) + +--- + +## Tools[^1] + +### Open-source + +- [Pre-Commit](https://pre-commit.com/) - A framework for managing and maintaining multi-language pre-commit hooks. + +### Links + +- [Wikipedia - Lint (software)](https://en.wikipedia.org/wiki/Lint_(software)) + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md new file mode 100644 index 0000000..1d2441c --- /dev/null +++ b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md @@ -0,0 +1,66 @@ +# Take care secrets and credentials + +*How can you ensure that sensitive information are not pushed to a repository?* + +This is one of the [OWASP Top Ten issues](https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure) and +several bug bounties write-ups are related to this kind of issue, eg hard-coded credentials pushed by mistake. + +You should scan your commits and your repository, and detect any sensitive information such as password, secret key, confidential, etc. +following the process shown in the picture. + +The ideal approach is detecting and preventing the exposure of sensitive data before that they hit the repository, +because they are then visible in the history. In case of code hosting platforms, secrets can still linger +on the web and be searchable after you remove them from the repository. + +A complimentary approach is scanning the repo for sensitive information, and then remove them; +note that when a credential is leaked, it is already compromised and should be invalidated. + +## Detecting secrets in several locations + +- **Detecting existing secrets** by searching in a repository for existing secrets. +- **Using Pre-commit hooks** in order to prevent secrets for entering our code base. +- **Detecting secrets in a pipeline** . + +## Why Detecting Secrets? + +- The secrets should not be hardcoded. +- The secrets should not be unencrypted. +- The secrets should not be stored in source code. +- The code history does not contain inadvertent secrets. + +## Where and when to Detect Secrets? + +![Pre Commit](/current-version/assets/images/pre-commit.png) + +Well, the best location is the **pre-commit** location, This ensure that before a secret actually enters your code base, it is intercepted, and the developer or to committer gets a message. Using **SAST IDE plugins** comes in handy while trying to fix such issues where the IDE warnings can be found as soon as the developer writes an insecure code with security misconfigurations. Another location is the build server or the **build** process. The build server retrieves source code, which is already committed and then it can analyze the source code where it contains new secrets or when it contains known secrets that the secrets are actually validated or audited. + +--- + +Here are some helpful tools to automatically scan repositories for sensitive information. +Scans can be implemented directly in our pipeline, and be repeatable and efficient. + +## Tools[^1] + +### Open-source + +- [Git Hound](https://github.com/ezekg/git-hound) - Git plugin that prevents sensitive data from being committed +- [git-secrets](https://github.com/awslabs/git-secrets) - Prevents you from committing secrets and credentials into git repositories +- [Github Secret Scanning](https://docs.github.com/en/code-security/secret-scanning) - Github built in feature for secret detection +- [gittyleaks](https://github.com/kootenpv/gittyleaks) - Find sensitive information for a git repo +- [Repo-supervisor](https://github.com/auth0/repo-supervisor) - Scan your code for security misconfiguration, search for passwords and secrets +- [truffleHog](https://github.com/dxa4481/truffleHog) - Searches through git repositories for high entropy strings and secrets, digging deep into commit history + +### Commercial + +- [BluBracket](https://blubracket.com) - Prevent secrets and credentials in code +- [GitGuardian](https://gitguardian.com) - Keep secrets out of your source code +- [GitHub Advanced Security](https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning) - GitHub scans repositories for known types of secrets, to prevent fraudulent use of secrets that were committed accidentally +- [Nightfall](https://nightfall.ai) - Find and protect secrets and keys across the cloud +- [Spectralops](https://spectralops.io) - Developer-first Cloud Security +- [TruffleSecurity](https://trufflesecurity.com) - Unhearth your secrets + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md new file mode 100644 index 0000000..052c08b --- /dev/null +++ b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-3-Linting-code.md @@ -0,0 +1,60 @@ +# Linting Code + +## What Is Linting? + +Linting is the automated checking of your source code for programmatic and stylistic errors. This is done by using a lint tool (otherwise known as linter). A lint tool is a basic static code analyzer. + +## What can Linting do? + +- Linting can **detect errors** in a code and errors that can lead to a security vulnerabilities. +- Linters Can Also **detect formatting or styling issues** and makes the code more readable for more secure code. +- Linters can **suggest best practices**. +- Also they can **increases overall quality of the code**. +- Since everybody follows the same linting rules it **makes maintenance of code easier**. + +## Basic Lint Tools + +Lint tools are the most basic form of static analysis. Using lint tools can be helpful for identifying common errors, such as: + +- Indexing beyond arrays. +- Dereferencing null pointers. +- (Potentially) dangerous data type combinations. +- Unreachable code. +- Non-portable constructs. + +## Advanced Static Analysis Tools + +Advanced static analysis tools typically deliver: + +- Pattern-based simulation. +- Quality and complexity metrics. +- Best practice recommendations for developers. +- Support for multiple safety and security-focused coding standards. +- Out-of-the-box certification for use in the development of safety-critical applications. + +## Issues with Linters + +- Not every language has "quality" standard linter tools available, each framwork usually has one or several linters. + +- Different versions or configurations can lead to different results. +- Since some linters are very verbose and information overload can lead to focusing on "unimportant" issues. + +## Where and When to Use Linter + +![Pre Commit](/current-version/assets/images/pre-commit.png) + +You can perform it in the **pre-commit** phase, so locally before actually committing code to your local repository to your local clone. Another phase where you often see linting is during the **build** phase, So here the build server pulls the code from the Git repository and performs linting on it and reports back that results from linting phase. + +--- + +## Tools[^1] + +### Open-source + +- [Pre-Commit](https://pre-commit.com/) - A framework for managing and maintaining multi-language pre-commit hooks. + +--- + +### Links + +- [Preforce](https://www.perforce.com/blog/qac/what-lint-code-and-why-linting-important) diff --git a/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md new file mode 100644 index 0000000..af5deed --- /dev/null +++ b/old-versions/V0.3/2-Process/2-2-Develop/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md @@ -0,0 +1,51 @@ +# Repository Hardening + +Securing a code repository involves implementing a variety of practices and techniques to protect it from unauthorized access, data breaches, and other security threats. By doing so, you can ensure the integrity, confidentiality, and availability of the code and its associated resources. + +## Objectives + +- **Prevent Unauthorized Access:** Ensure that only authorized personnel can access and modify the repository. +- **Protect Sensitive Information:** Safeguard secrets, passwords, and other sensitive data. +- **Maintain Code Integrity:** Ensure that the code is not tampered with or corrupted. +- **Compliance:** Adhere to regulatory and industry standards for code security. + +## Key Concepts + +- **Access Control:** Managing who can access the repository and what actions they can perform. +- **Secrets Management:** Handling sensitive data such as API keys and passwords securely. +- **Audit and Monitoring:** Keeping track of repository activities to detect and respond to security incidents. +- **Code Quality and Security:** Ensuring the codebase is free from vulnerabilities and adheres to security best practices. +- **Backup and Recovery:** Ensuring data is backed up and can be restored in case of a failure or breach. + +## Best Practices for Repository Hardening + +1. **Access Control** + - **Principle of Least Privilege:** Grant the minimum necessary permissions to users. + - **Role-Based Access Control (RBAC):** Define roles with specific permissions and assign users to these roles. + - **Multi-Factor Authentication (MFA):** Require MFA for accessing the repository to add an extra layer of security. + - **SSH Keys and Token Management:** Use SSH keys or personal access tokens instead of passwords for authentication. +2. **Secrets Management** + - **Environment Variables:** Use environment variables to manage secrets in CI/CD pipelines. + - **Secret Management Tools:** Use tools like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault to store and manage secrets securely. + - **Scanning for Secrets:** Use tools like GitSecrets, TruffleHog, and Talisman to scan the repository for accidentally committed secrets. +3. **Audit and Monitoring** + - **Audit Logs:** Enable and regularly review audit logs to monitor access and changes to the repository. + - **Activity Alerts:** Set up alerts for suspicious activities, such as failed login attempts or unexpected repository modifications. + - **Repository Scanning:** Regularly scan the repository for vulnerabilities using tools like SonarQube or CodeQL. +4. **Code Quality and Security** + - **Static Code Analysis:** Integrate static analysis tools to detect security vulnerabilities and code quality issues. + - **Code Reviews:** Implement a mandatory code review process to ensure that all code changes are reviewed by peers. + - **Dependency Management:** Regularly update dependencies and use tools like Dependabot or Snyk to detect vulnerabilities in third-party libraries. +5. **Backup and Recovery** + - **Regular Backups:** Ensure that repository data is backed up regularly and stored securely. + - **Disaster Recovery Plan:** Develop and test a disaster recovery plan to restore repository data in case of a breach or failure. + +--- + +### Links + +- [GitHub Security Best Practices](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure) +- [GitLab Security Guide](https://docs.gitlab.com/ee/user/application_security/) +- [HashiCorp Vault Documentation](https://www.vaultproject.io/docs) +- [OWASP Secure Coding Practices](https://owasp.org/www-project-secure-coding-practices-quick-reference-guide/) +- [SonarQube Documentation](https://docs.sonarqube.org/latest/) diff --git a/old-versions/V0.3/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md b/old-versions/V0.3/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md new file mode 100644 index 0000000..946e125 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-3-Build/2-3-1-Static-Analysis/2-3-1-1-Static-Application-Security-Testing.md @@ -0,0 +1,52 @@ +# Static scanning is an important part of the process + +![Static scanning diagram showing analysis process](/current-version/assets/images/Static scanning.png) + +Static Code Analysis or Source Code Analysis is usually part of a Code Review (white-box testing) and it is a method of computer program debugging that is done by examining the code without executing the program. + +Static scanning is good way finding coding issues such as: + +- Syntax violations +- Security vulnerabilities +- Programming errors +- Coding standard violations +- Undefined values + +For more information about the Static Code Analysis please visit [the OWASP page](https://owasp.org/www-community/controls/Static_Code_Analysis) +To achieve a better result we can combine static security scanning and 3rd party code (open-source libraries (dependency) scanning. +To doing this part better and more complete (prevent misconfigurations), we can bring up IaC (Infrastructure as code) security scan too. For example check Terraform, helm, Ansible code, etc. +So according to the above lines the possible actions in this step are as follows: + +- Static Code Analysis (known as SAST) +- Open-source libraries (3rd party / dependency) scanning (known as SCA) +- IaC Security scanning + +--- + +## Tools[^1] + +### Open-source + +- [Brakeman](https://github.com/presidentbeef/brakeman) - A static analysis security vulnerability scanner for Ruby on Rails applications +- [CodeQL](https://github.com/github/codeql) - Discover vulnerabilities across a codebase with CodeQL, our industry-leading semantic code analysis engine. +- [CodeSec by Contrast Security](https://www.contrastsecurity.com/developer) - A high-speed high-quality free SAST tool designed for use by developers and in CI/CD pipelines. +- [SonarQube](https://www.sonarqube.org) - An open-source web-based tool, extending its coverage to more than 20 languages, and also allows a number of plugins + +### Commercial + +- [Checkmarx SAST](https://checkmarx.com) - A static analysis security vulnerability scanner +- [CodeSweep](https://hclsw.co/codesweepgithub) - Static Analysis tool for GitHub that's free to use and can scan code on pull request. Support over 20 languages and IaC (docker, k8s). [Download CodeSweep VS Code extension](https://hclsw.co/codesweep) +- [Enlightn](https://github.com/enlightn/enlightn) - A static analysis vulnerability scanner for Laravel PHP applications +- [Fortify](https://www.microfocus.com/en-us/cyberres/application-security/static-code-analyzer) - A static analysis security vulnerability scanner +- [HCL AppScan on Cloud](https://cloud.appscan.com ) - SAST tool built as a service. The tool can perform traditional SAST, SCA and IaC scanning. +- [Inquisition](https://github.com/rubygarage/inquisition) - A set of tools for convenient technical analysis of web applications built with Ruby and Ruby on Rails. Now you don't need to set up and configure every single gem. Use Inquisition gem instead +- [PT Application Inspector](https://www.ptsecurity.com/ww-en/products/ai/) - Is the only source code analyzer providing high-quality analysis and convenient tools to automatically confirm vulnerabilities — significantly speeding up the work with reports and simplifying teamwork between security specialists and developers +- [security code scan](https://github.com/security-code-scan/security-code-scan) - Vulnerability Patterns Detector for C# and VB.NET +- [Semgrep](https://semgrep.dev) - Lightweight static analysis for many languages. Find bug variants with patterns that look like source code. +- [Veracode](https://www.veracode.com/security/static-analysis-tool) - A static analysis tool that is built on the SaaS model. This tool is mainly used to analyze the code from a security point of view + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/current-version/2-Process/2-3-Build/2-3-2-Software Composition Analysis/2-3-2-1-Software-Composition-Analysis.md b/old-versions/V0.3/2-Process/2-3-Build/2-3-2-Software Composition Analysis/2-3-2-1-Software-Composition-Analysis.md similarity index 100% rename from current-version/2-Process/2-3-Build/2-3-2-Software Composition Analysis/2-3-2-1-Software-Composition-Analysis.md rename to old-versions/V0.3/2-Process/2-3-Build/2-3-2-Software Composition Analysis/2-3-2-1-Software-Composition-Analysis.md diff --git a/old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md b/old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md new file mode 100644 index 0000000..7467cbb --- /dev/null +++ b/old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-1-Container-Scanning.md @@ -0,0 +1,52 @@ +# Container Vulnerability Scanning + +As containers become an almost ubiquitous method of packaging and deploying applications, the instances of malware have increased. Securing containers is now a top priority for DevOps engineers. Fortunately, a number of open source programs are available that scan containers and container images. Let’s look at five such tools. + +## What can Container Security Scanning do? + +- Detect insecure containers + - Detect outdated libraries + - Detect incorrectly configured containers + - Detect outdated operating system +- Detect compliance validations +- Suggest best practices + +## Issues with Container Security Scanner + +- Level of depth depends on tool being used, So the results that you'll get are very dependent on the type of tool you choose. +- Easy to go "too far" with configuration, there are tools where you can configure so much different settings, that it's easy to jump overboard. +- The scan results will lead to actionable events? + +## Where and When to use Container Scanner? + +![Development process diagram showing container scanning](/current-version/assets/images/Dev-process.png) + +You can use it at the build phase when you're actually building for instance a Dockerfile and looking at the resulting image that you're creating. Another location to perform container scanning would be when you push a container to the registry or when you pull a container from a registry. However, a good approach is scanning before pushing into a trusted container registry then you can say we have a container registry with a scanned version of all images and for deploying in production you can pull from this trusted container registry. (Plase take look into the following image) + +![Container security pipeline showing scanning process](/current-version/assets/images/container-security-pipeline.png) + +--- + +## Tools[^1] + +### Open-source + +- [Clair](https://github.com/quay/clair) - Vulnerability Static Analysis for Containers +- [Anchore](https://anchore.com/opensource/) - Open-source project for deep analysis of docker images +- [Dagda](https://github.com/eliasgranderubio/dagda/) - A tool to perform static analysis of known vulnerabilities, trojans, viruses, malware & other malicious threats in docker images/containers and to monitor the docker daemon and running docker containers for detecting anomalous activities +- [Falco](https://falco.org/) - Falco, the cloud-native runtime security project, is the de facto Kubernetes threat detection engine +- [Harbor](https://goharbor.io/) - Harbor is an open source registry that secures artifacts with policies and role-based access control, ensures images are scanned and free from vulnerabilities, and signs images as trusted. +- [Trivy](https://aquasecurity.github.io/trivy/) - Trivy is a simple and comprehensive vulnerability/misconfiguration scanner for containers and other artifacts. +- [Kbescape](https://github.com/armosec/kubescape) - Kubescape is a K8s open-source tool providing a multi-cloud K8s single pane of glass, including risk analysis, security compliance, RBAC visualizer and image vulnerabilities scanning. + +### Commercial + +- [Aquasec](https://www.aquasec.com/products/container-vulnerability-scanning/) - With Aqua’s advanced vulnerability scanning & management DevOps can detect vulnerabilities, embedded secrets, and other risks during the development cycle, and prioritize mitigation by risk-based insights. Available on Aqua Enterprise, Self-hosted or SaaS. + +--- + +### Links + +- [Opensource.com - tools for container security](https://opensource.com/article/18/8/tools-container-security) + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md b/old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md new file mode 100644 index 0000000..fae61dc --- /dev/null +++ b/old-versions/V0.3/2-Process/2-3-Build/2-3-3-Container-Security/2-3-3-2-Container-Hardening.md @@ -0,0 +1,45 @@ +# Container Hardening + +Containers have revolutionized the way applications are deployed and managed, offering flexibility and scalability. However, like any other technology, containers are not immune to security risks. To mitigate these risks, it is crucial to implement container hardening practices. This document outlines best practices and guidelines for securing containers and provides references for further information. + +## Container Hardening Best Practices + +- **Use Only Trusted Base Images** +Ensure that you use base images from trusted sources, such as official repositories or reputable vendors. Regularly update base images to include the latest security patches and fixes. + +- **Apply Security Patches** +Keep all container software and dependencies up to date by regularly applying security patches. This includes the host system, container runtime, and any additional software or libraries. + +- **Implement Principle of Least Privilege** +Apply the principle of least privilege to container configurations. Limit container capabilities, such as restricting root access and minimizing privilege escalation opportunities. + +- **Enable Resource Limitations** +Define resource limitations for containers to prevent resource exhaustion attacks. Set appropriate limits for CPU, memory, and network bandwidth to ensure fair resource sharing and protect against DoS attacks. + +- **Use Image Vulnerability Scanning** +Employ image vulnerability scanning tools to identify and remediate known vulnerabilities in container images. These tools can provide valuable insights into security risks and suggest appropriate fixes. Check out [Container Vulnerability Scanning](3-1-3-1-Container-scanning.md) for more information. + +- **Employ Secure Network Configuration** +Implement network security controls, such as container network segmentation and isolation. Use firewalls and network policies to restrict container communication and prevent unauthorized access. + +- **Harden Host Systems** +Ensure that host systems running container engines are hardened and regularly updated. Follow best practices for securing the underlying infrastructure, including patch management, access control, and intrusion detection. + +- **Implement Container Runtime Security Measures** +Utilize security features provided by container runtimes, such as SELinux, AppArmor, or seccomp, to enforce additional security policies and restrict container behavior. + +- **Monitor Container Activity** +Implement logging and monitoring mechanisms to detect and respond to security incidents. Monitor container behavior, access logs, and system logs to identify any suspicious activity. + +- **Secure Container Registry** +Protect container images by securing the container registry. Implement authentication, access controls, and encryption to ensure that only authorized users can access and modify container images. + +--- + +### Links + +- [CIS Benchmarks for Docker and Kubernetes](https://www.cisecurity.org/benchmark/docker/) +- [Docker Security](https://docs.docker.com/engine/security/) +- [Kubernetes Security](https://kubernetes.io/docs/concepts/security/) +- [NIST Special Publication 800-190: Application Container Security Guide](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-190.pdf) +- [OWASP Docker Security Project](https://owasp.org/www-project-docker-security/) diff --git a/current-version/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security/2-3-1-3-Infastructure-as-Code-Scanning.md b/old-versions/V0.3/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security/2-3-1-3-Infastructure-as-Code-Scanning.md similarity index 100% rename from current-version/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security/2-3-1-3-Infastructure-as-Code-Scanning.md rename to old-versions/V0.3/2-Process/2-3-Build/2-3-4-Infrastructure as Code Security/2-3-1-3-Infastructure-as-Code-Scanning.md diff --git a/old-versions/V0.3/2-Process/2-3-Build/2-3-5-Security-Gates.md b/old-versions/V0.3/2-Process/2-3-Build/2-3-5-Security-Gates.md new file mode 100644 index 0000000..6b3e1c4 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-3-Build/2-3-5-Security-Gates.md @@ -0,0 +1,3 @@ +# Security Gates + + diff --git a/old-versions/V0.3/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md b/old-versions/V0.3/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md new file mode 100644 index 0000000..e9332f6 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-4-Test/2-4-1-Interactive-Application-Security-Testing.md @@ -0,0 +1,67 @@ +# Interactive Application Security Testing + +**IAST (interactive application security testing)** is an application security testing method that tests an application, API, or function while it is being exercised by automated tests, human testers, or any other "interaction" with the code's functionality. This makes it highly compatible with just about any software development lifecycle, especially DevOps. + +IAST does not scan applications, but installs onto application and API servers and continuously analyzes applications forever. IAST works by instrumenting code with sensors that can directly observe security relevant application behavior. IAST uses the same proven technqiues as APM tools and profilers, just highly optimized for security and speed. + +IAST requires zero changes to the way teams build, test, and deploy code. IAST performs security testing in real time during normal development and testing, and identifies vulnerabilities without requiring them to be exploited. This means with IAST, anyone can perform high quality security tests, even without a security background. + +IAST can be deployed to development servers, CI/CD pipelines, or quality assurances servers, or even while in production. Wherever the code runs, that's where IAST is installed, including servers, containers, virtual machines, cloud, and other environments. IAST is uniquely well suited for API security testing, as it overcomes the challenges SAST and DAST have with complex API code and data. + +IAST sensors have access to: + +- Entire code +- Full HTTP request and response +- Data flow and control +- Configuration data +- Libraries and frameworks and how they are used +- Back-end connection data + +This rich context makes IAST extremely accurate compared with traditional appsec testing tools and it enables IAST to deliver very detailed findings that enable developers to understand issues and fix them correctly. It also enables IAST to cover a very broad range of appsec vulnerabilities, including: + +- Code issues like hardcoded secrets and weak encryption algorithms +- Data flow issues like injection and SSRF +- HTTP issues like clickjacking, parameter pollution, and missing headers +- Backend connection issues like SSRF +- Configuration issues like verb tampering and weak authentication +- and more... + +One challenge with IAST is that only code that is exercised is tested. However, it's easy to use simple end-to-end "smoke" tests, or even a simple crawler, to generate this coverage. IAST does not require extensive functional testing, just basic end-to-end execution of routes. Some IAST tools extract the set of routes from an application and simplify the process of getting to 100% route coverage. + +--- + +## IAST vs SAST + +**Static Application Security Testing** method examines source code in a non-runtime environment early in the SDLC. It looks for suspicious code patterns that indicate security risks. Even though they are easy to deploy, SASTs report large numbers of false positives because SASTs do not take into account the presence of other security countermeasures, and they lack visibility during runtime. SAST tools normally run during the build process, and can introduce delays as the scan process takes time to finish. IASTs are more flexible than SASTs, because they are applicable in production runtime environments (SASTs require direct access to the source code). + +## IAST vs DAST + +**Dynamic Application Security Testing** method works like a black-box scanner that sends malicious HTTP requests to an application and evaluate the HTTP responses to determine whether a security vulnerability was found. DASTs look at the applications from the exterior and determine the presence of risks by looking at the response (including body and headers) of the server to a battery of tests, but DASTs have no visibility of the internal workings of the app. Furthermore, DAST tests are hard to automate, because DASTs must be operated by experienced appsec teams, such as penetration testers, to be truly useful. Forrester estimates that the duration of a DAST scan can take around 5 to 7 days, while testing with IAST is a real-time (zero minutes) operation. + +--- + +## Tools[^1] + +### Open-source + +### Commercial + +- [Checkmarx Interactive Application Security Testing(CxIAST)](https://www.checkmarx.com/products/interactive-application-security-testing/) +- [Contrast Assess](https://www.contrastsecurity.com/contrast-assess) and [Contrast Community Edition](https://www.contrastsecurity.com/contrast-community-edition) +- [HCL AppScan on Cloud](https://cloud.appscan.com) +- [Seeker Interactive Application Security Testing](https://www.synopsys.com/software-integrity/security-testing/interactive-application-security-testing.html) + +--- + +### Links + +- [Acunetix - IAST](https://www.acunetix.com/blog/web-security-zone/what-is-iast-interactive-application-security-testing/) +- [Contrast Security - What is Interactive Application Security Testing?](https://www.contrastsecurity.com/knowledge-hub/glossary/interactive-application-security-testing) +- [Contrast Security - Why the difference sast, dast, and iast mastters](https://www.contrastsecurity.com/security-influencers/why-the-difference-between-sast-dast-and-iast-matters) +- [Esecurityplanet - Application security vendors](https://www.esecurityplanet.com/products/application-security-vendors/) +- [Hdivsecurity - IAST](https://hdivsecurity.com/bornsecure/what-is-iast-interactive-application-security-testing/) +- [OWASP - Free IAST Tools](https://owasp.org/www-community/Free_for_Open_Source_Application_Security_Tools#:~:text=open%20source%20projects.-,IAST%20Tools,-IAST%20tools%20are) +- [Synk - IAST](https://snyk.io/learn/iast-interactive-application-security-testing/) +- [Veracode - IAST](https://www.veracode.com/security/interactive-application-security-testing-iast) + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md b/old-versions/V0.3/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md new file mode 100644 index 0000000..1a7df3d --- /dev/null +++ b/old-versions/V0.3/2-Process/2-4-Test/2-4-2-Dynamic-Application-Security-Testing.md @@ -0,0 +1,43 @@ +# Dynamic Application Security Testing (DAST) + +DAST is a “Black-Box” testing technique that can find security vulnerabilities and weaknesses in a running application by injecting malicious payloads to identify potential flaws that allow for attacks like SQL injections or cross-site scripting (XSS), etc. DAST tools are especially helpful for detecting: + +- Input or output validation +- Authentication issues +- Server configuration mistakes + +DAST tools allow for extensive scans from the client side and server side without needing the source code or the framework the application is built on. While configuration requires expertise, scans usually require minimal user interaction once configured and can be run as part of a nightly scan. As more important DAST tools we can look at the following: + +- Dynamic security scanner +- Fuzzers +- Attack Proxies + +--- + +## Tools[^1] + +### Open-source + +- [OWASP Nettacker](https://owasp.org/www-project-nettacker/) - Automated information gathering and vulnerability scanner with API and Web UI. +- [ZED Attack Proxy](https://www.zaproxy.org) - It is an open source tool which is offered by OWASP for performing security testing + +### Commercial + +- [Acunetix](https://www.acunetix.com) - An automatic web security testing scanner that accurately scans and audits all web applications, including HTML5, JavaScript and Single Page applications (SPAs) +- [Burp Suite](http://www.portswigger.net/) is an integrated platform for performing security testing of web applications. Its various tools work seamlessly together to support the entire testing process, from initial mapping and analysis of an application’s attack surface, through to finding and exploiting security vulnerabilities. +- [Dastardly](https://portswigger.net/burp/documentation/dastardly) - Lightweight web application security scanner designed to run in CI/CD pipelines. +- [HCL AppScan on Cloud](https://cloud.appscan.com) - DAST tool built as a service. It can scan both public and privatly hosted application. Can explore and test modern web applications, leverage manually recorded steps and handle complex login scenarios. +- [InsightAppSec (AppSpider)](https://www.rapid7.com/products/insightappsec) - Application security testing for the modern web +- [Netsparker](https://www.netsparker.com) - It can identify vulnerabilities in all types of modern web applications, regardless of the underlying architecture or platform +- [Nuclei](https://github.com/projectdiscovery/nuclei) - Fast and customisable vulnerability scanner based on simple YAML based DSL. +- [Veracode Dynamic Analysis](https://www.veracode.com/products/dynamic-analysis-dast) - Veracode Dynamic Analysis helps companies scan their web applications for exploitable vulnerabilities at scale. +- [Escape DAST](https://escape.tech) - Escape DAST is purposely built for testing for business logic vulnerabilities at scale and handling complex auth scenarios in modern applications: APIs (including GraphQL) and Single Page Apps (SPAs) + +--- + +### Links + +- [OWASP - Vulnerability Scanning Tools](https://owasp.org/www-community/Vulnerability_Scanning_Tools) +- [RAPID7 - Dynamic Application Security Testing](https://www.rapid7.com/fundamentals/dast/) + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md b/old-versions/V0.3/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md new file mode 100644 index 0000000..1f03d37 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-4-Test/2-4-3-Mobile-Application-Security-Test.md @@ -0,0 +1,3 @@ +# Mobile Application Security Test + + diff --git a/old-versions/V0.3/2-Process/2-4-Test/2-4-4-API-Security.md b/old-versions/V0.3/2-Process/2-4-Test/2-4-4-API-Security.md new file mode 100644 index 0000000..c89b66e --- /dev/null +++ b/old-versions/V0.3/2-Process/2-4-Test/2-4-4-API-Security.md @@ -0,0 +1,3 @@ +# API Security + + diff --git a/old-versions/V0.3/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md b/old-versions/V0.3/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md new file mode 100644 index 0000000..e53a816 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-4-Test/2-4-5-Misconfiguration-Check.md @@ -0,0 +1,3 @@ +# Misconfiguration Check + + diff --git a/old-versions/V0.3/2-Process/2-5-Release/2-5-1-Release.md b/old-versions/V0.3/2-Process/2-5-Release/2-5-1-Release.md new file mode 100644 index 0000000..623aa21 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-5-Release/2-5-1-Release.md @@ -0,0 +1,3 @@ +# Release + + diff --git a/old-versions/V0.3/2-Process/2-6-Deploy/2-6-1-Deploy.md b/old-versions/V0.3/2-Process/2-6-Deploy/2-6-1-Deploy.md new file mode 100644 index 0000000..623aa21 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-6-Deploy/2-6-1-Deploy.md @@ -0,0 +1,3 @@ +# Release + + diff --git a/old-versions/V0.3/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md b/old-versions/V0.3/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md new file mode 100644 index 0000000..0ce6742 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-7-Operate/2-7-1-Cloud-Native-Security.md @@ -0,0 +1,3 @@ +# Cloud Native Security + + diff --git a/old-versions/V0.3/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md b/old-versions/V0.3/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md new file mode 100644 index 0000000..11a3b0e --- /dev/null +++ b/old-versions/V0.3/2-Process/2-7-Operate/2-7-2-Logging-and-Monitoring.md @@ -0,0 +1,3 @@ +# Logging and-Monitoring + + diff --git a/old-versions/V0.3/2-Process/2-7-Operate/2-7-3-Pentest.md b/old-versions/V0.3/2-Process/2-7-Operate/2-7-3-Pentest.md new file mode 100644 index 0000000..3d95c6b --- /dev/null +++ b/old-versions/V0.3/2-Process/2-7-Operate/2-7-3-Pentest.md @@ -0,0 +1,98 @@ +# Penetration Test + +A penetration test, or pen test, is a simulated attack on systems and applications to identify exploitable vulnerabilities. It involves testing web and mobile applications, APIs, network devices, workstations, servers and more, uncovering issues like SQL injection, code injection, XSS and privilege escalation. + +While penetration testers use automated tools for scanning and information gathering, most testing is conducted manually. Manual testing is crucial for detecting vulnerabilities related to business logic and other issues that automated scans might miss. + +Penetration testing can be conducted during the testing phase of the software development lifecycle, ensuring vulnerabilities are addressed before the application is deployed. It can also be performed after the application is in production to identify and mitigate security risks in a live environment, ensuring ongoing protection against emerging threats. Doing it early on in the development process may depend on how mature the organization is. + +## Methodologies and Checklists + +A penetration test can be approached in three ways: black-box, gray-box, or white-box. + +- **Black-box:** Testers have no prior information about the application, except possibly an IP address or domain. +- **Gray-box:** Testers are given additional information, such as credentials for test accounts. This approach balances cost and effectiveness, providing deeper insights without the high expense of white-box testing. It should be the preferred approach most of the time. +- **White-box:** Testers have full access to all information about the asset being tested, including the application's source code. + +Regardless of the approach, penetration testers will generally follow publicly-available and/or internal checklists and testing guides. The most popular ones are: + +- [OWASP Web Security Testing Guide (WSTG)](https://owasp.org/www-project-web-security-testing-guide/) - A comprehensive guide to testing the security of web applications and web services. +- [OWASP Mobile Application Security Testing Guide (MASTG)](https://mas.owasp.org/MASTG/) - Similar to the OWASP WSTG, it is a comprehensive guide to testing mobile applications. +- [OWASP Top 10](https://owasp.org/www-project-top-ten/) - Most common and impactful web application security vulnerabilities. +- [OWASP Top 10 API](https://owasp.org/API-Security/editions/2023/en/0x11-t10/) - Most common security risks and vulnerabilities for APIs. +- [OWASP Mobile Top 10](https://owasp.org/www-project-mobile-top-10/) - A list containing the most common and impactful mobile application security vulnerabilities. + +## Process Overview + +### Assembling the team + +The composition of the penetration testing team is very important. It can either consist of: + +- **Internal:** cybersecurity professionals who understand the organization's systems and policies intimately. +- **External:** third-party hired for their specialized skills and objectivity, which can bring fresh perspectives and expertise in identifying vulnerabilities that internal teams might overlook. + +### Defining a scope + +After assembling the penetration testing team, the organization must meticulously define the scope of the test. This step is critical to avoid deviations from the planned objectives or unintended testing of additional assets and endpoints. Scope definition entails: + +- Decide between black-box, gray-box, or white-box methodologies. +- Establish clear timelines for the testing phases. +- Define which systems and endpoints will undergo testing. +- Decide whether tests will occur in production, staging, or other environments. +- Define the requirements - e.g. testing accounts, credentials, documentation, etc. + +### Requirements + +Once the scope and dates are defined, the penetration testing team will communicate their requirements to the organization. These may include testing credentials, application documentation, source code access and other necessary resources. It is crucial for the organization to promptly provide all requested information and access before testing begins to ensure a smooth and effective penetration testing process. + +### Execution + +After receiving the necessary requirements, such as credentials and documentation, the penetration testing team will begin assessing the system or application. It is crucial for the penetration testing team to: + +- Notify the organization immediately if their tests cause any disruption to a system, especially if it is in production, to mitigate potential impacts on business operations. +- Report any critical vulnerabilities discovered promptly to the organization, as these could have significant financial and/or reputational consequences, allowing for swift remediation and risk management. +- If the penetration testing team finds any indicators of compromise (IoC) that an incident may have happened, they must notify the organization immediately. + +### Reporting + +Upon completing all tests, the penetration testing team will begin compiling a comprehensive report. This report should be structured as follows: + +- Cover +- Table of Contents +- Executive Summary +- General Information + - Penetration Testing Team + - Methodology + - Scope +- Vulnerabilities + - Title + - Severity + - Description + - Proof of Concept (with screenshots) + - Impact + - Mitigation + - References +- Conclusion + +### Retesting + +Lastly, after delivering the report and initiating the vulnerability management process, the penetration testing team will retest all vulnerabilities that developers consider fixed. This retesting ensures that each vulnerability has been successfully addressed and that no bypasses to the newly implemented security controls exist. + +--- + +## Tools[^1] + +- [BurpSuite](https://portswigger.net/burp) - A comprehensive software tool used for web application security testing. Key features include a proxy for intercepting and modifying web traffic, a scanner for automated vulnerability detection and tools for performing manual testing, such as repeater, intruder and so forth. +- [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF) - Automated, open-source tool for security testing and analyzing mobile applications, supporting both Android and iOS platforms. +- [Postman](https://www.postman.com/) - API testing tool that allows sending various HTTP requests, manipulating headers and automating tests. It helps identify vulnerabilities like authentication issues and data exposure, integrating with other security tools for comprehensive analysis. +- [Zed Attack Proxy (ZAP)](https://www.zaproxy.org) - An open-source web proxy similar that has features similar to BurpSuite's. + +--- + +### Links + +- [Awesome Penetration Testing](https://github.com/enaqx/awesome-pentest) +- [OWASP Penetration Testing Methodologies](https://owasp.org/www-project-web-security-testing-guide/latest/3-The_OWASP_Testing_Framework/1-Penetration_Testing_Methodologies) +- [The Penetration Testing Execution Standard (PTES)](http://www.pentest-standard.org/index.php/Main_Page) + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md b/old-versions/V0.3/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md new file mode 100644 index 0000000..61b4345 --- /dev/null +++ b/old-versions/V0.3/2-Process/2-7-Operate/2-7-4-Vulnerability-Management.md @@ -0,0 +1,3 @@ +# Vulnerability Management + + diff --git a/old-versions/V0.3/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md b/old-versions/V0.3/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md new file mode 100644 index 0000000..d5a01bf --- /dev/null +++ b/old-versions/V0.3/2-Process/2-7-Operate/2-7-6-Breach-and-attack-simulation.md @@ -0,0 +1,3 @@ +# Breach and Attack Simulation + + diff --git a/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md b/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md new file mode 100644 index 0000000..b8bac01 --- /dev/null +++ b/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md @@ -0,0 +1 @@ +# Compliance Auditing diff --git a/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md b/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md new file mode 100644 index 0000000..92dd46f --- /dev/null +++ b/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md @@ -0,0 +1,39 @@ +# Policy as Code + +## What is Policy + +In each company there are lots of rules, requirements, or procedures that must consider before deploying any application or product to be in production level, and other of them for other type of level like staging or developing. These rules, requirements, or procedures must check and pass and if there is any misconfiguration, process has to be suspend until it fix. + +Some must comply with industry-recognized frameworks such as SOC 2, CIS, PCI DSS, or ISO 27001. These policies are either part of the business logic code or enforced manually.These are not easily trackable because every team implements it as it sees fit due to a lack of framework definition in organization level. + +## What is Policy as Code + +Having multiple security checklist in your organization will come to be time consuming and makes lots of differents meaning and behaviour in each team. despite of having a checklist or excel, you can manage all policies as code and make all of them proactive and apply them in each enviroment you need them. by this approach policeis are not only a checklist that one team can ignore some part of it or miss any part of it. + +## Benefits of Policy as Code + +**Policy Management**: Centralizing your policies into a single location, as opposed to dispersing them across multiple locations maintained by different IT teams, enables a more agile and adaptable approach to policy management. + +**Version Control**: Centralizing policies in a version control system like GitHub or GitLab offers organizations enhanced control and visibility. Stakeholders benefit from easy access to operational changes, while automated version control facilitates seamless updates and rollback options, ensuring smooth transitions and mitigating potential issues with new versions. + +**Faster and Efficient**: Efficiency is heightened as manual policy enforcement is eliminated, enabling dynamic updates and sharing of policies, thereby streamlining the process. Additionally, the combination of centralization and versioning fosters repeatability and idempotence in code execution. Repeatability ensures consistent code execution, while idempotence guarantees that repeated executions yield the same output. This reliability is crucial for instilling confidence among operators, empowering them to execute deployments without hesitation or fear. + +--- + +## Tools[^1] + +### Open-source + +- [Kyverno](https://kyverno.io/) - Kyverno (Greek for “govern”) is a policy engine designed specifically for Kubernetes. +- [OPA](https://www.openpolicyagent.org/) - Open Policy Agent (OPA) is an open source, general-purpose policy engine that enables unified, context-aware policy enforcement across the entire stack. + +### Commercial + +- [HashiCorp Sentinel](https://developer.hashicorp.com/sentinel) - A language and framework for policy built to be embedded in existing software to enable fine-grained, logic-based policy decisions. +- [Styra DAS](https://www.styra.com/pricing/) - Commercial tools for managing OPA at scale and created by the founders and maintainers of Open Policy Agent (OPA) + +--- + +### Links + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md b/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md new file mode 100644 index 0000000..128ed42 --- /dev/null +++ b/old-versions/V0.3/3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md @@ -0,0 +1 @@ +# Security benchmarking diff --git a/old-versions/V0.3/3-Governance/3-2-Data-protection.md b/old-versions/V0.3/3-Governance/3-2-Data-protection.md new file mode 100644 index 0000000..f969969 --- /dev/null +++ b/old-versions/V0.3/3-Governance/3-2-Data-protection.md @@ -0,0 +1,37 @@ +# Data Protection + +Privacy has become an important aspect of application security. GDPR, LGPD, CCPA and other laws and regulations have impose several controls over processing PII (Personally Identifiable Information). To comply with those regulations, DevSecOps have to be sure to use PII accordingly and protect data agains leaking. + +To start, it is important to have a good understanding of what is considered PII: + +- First and last name; +- Identifiable email (); +- Identity card numbers; +- Location data (mobile); +- IP Address. +- This is not a complete list. + +Some PII are considered sensitive, and require even more protection, such as: + +- Racial or ethnic origin; +- Political opinions; +- Religious or philosophical beliefs; +- Trade union membership; +- Genetic data; and +- Biometric data (where processed to uniquely identify someone). + +Most privacy regulations promote Privacy by Design, the aproach where the development process addresses privacy concerns thru the whole cycle. Even before coding starts. + +You have to create a PII data flow to make sure you apply the required protection to the data thru its lifecycle. You also have to follow all the requirements related to the quality and volume of processed data. + +All PII data processing requirements have to be specified. you have to create an inventory of all PII and evaluate the processing activity to make sure it follows all requirementes, such as: + +- Lawfulness, fairness and transparency +- Purpose limitation +- Data minimization +- Accuracy +- Storage limitation +- Integrity and confidentiality (security) +- Accountability + +After you make sure that the PII and the PII processing activity are mapped and comply to the privacy regulation you have to follow, it is important to apply the security measures to protect the data, accordingly with its criticity. diff --git a/old-versions/V0.3/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md b/old-versions/V0.3/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md new file mode 100644 index 0000000..b1f20dd --- /dev/null +++ b/old-versions/V0.3/3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md @@ -0,0 +1 @@ +# Tracking Maturities diff --git a/old-versions/V0.3/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md b/old-versions/V0.3/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md new file mode 100644 index 0000000..da86d24 --- /dev/null +++ b/old-versions/V0.3/3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md @@ -0,0 +1,55 @@ +# Central Vulnerability Management Dashboard + +## What Is Vulnerability Management? + +Vulnerability Management is a continuous process that helps organizations detect, report, prioritize, and remediate vulnerabilities in their software and platforms. It is an important part of DevSecOps Lifecycle because it allows the ability to organize the security flaws in a manageable, actionable, and traceable way. Also, VM helps to achieve visibility of an organization's security posture. When VM is executed alongside other processes, it helps minimize the attack surface and bridge the gap between isolated findings across distributed tools and processes. + +## Process Definition + +Taking the OWASP VMG Project as a reference, we can describe the overall VM process in three stages: + +- **Detection:** During the detection cycle, we conduct the tasks that support vulnerability tests in essential ways by defining the: who, what, where, why, and how. The principal activities are focused on defining and refining scope after each round of the process, getting tools ready and verifying their integrity, conducting tests, and verifying results. +- **Reporting:** The reporting cycle targets activities that help the organization understand vulnerability in a measurable way. The principal activities are focused on [quickly and concisely capturing](https://www.linkedin.com/pulse/how-vulnerability-jeff-williams/) all the system, vulnerability, threat, technical risk, and operational risk details associated with a vulnerability. Reporting can also involve creating organizational, meaningful metrics such as Mean Time to Remediate (MTTR) and Vulnerability Escape Rate (VER) to help the organization improve over time. +- **Prioritization:** The prioritization process selects vulnerabilities and working with development teams to get them fixed. Some vulnerabilities may represent minimal risk or may not be exploitable. Risk is one key factor in the prioritization process, but the effort and expertise required are also key factors. Organizations might also consider the retirement date of the system and details of the development process. +- **Remediation:** The Remediation cycle targets activities that reduce or eliminate vulnerabilities. Key activities are focused on defining priorities and terms of remediation work, discussing and documenting false positives, and dealing with exceptions. + +## How VM tools can help DevSecOps + +The tools we use to create a DevSecOps pipeline will generate plenty of vulnerabilities, and each tool will have its own separate format. Managing this data can be challening to track. Vulnerability Management tools consolidate reports generated by different tools and activities in one or a few dashboards, providing an overview of the security posture. Team members can track the progress of remediation efforts by metrics, triage and prioritize findings across the entire pipeline, and manage the vulnerabilities lifecycle across the process. Also, engineers can benefit from the de-duplication features, which help them deal with the noise generated by continuous scanning and duplication of findings. Finally, VM Tools provide integrations with other components to enable bi-directional communication, notifications, data export, and report generation. + +The following image can give you a better view of what the Vulnerability Management means and why we must consider it. + +![VM Inside Pipeline](/current-version/assets/images/Pipeline-view.png) + +## Cautions + +Be wary of generating a large security backlog in your VM tool that captures vulnerabilities but isn't contributing to getting them fixed. As Michal Zalewski describes in "The Tangled Web," underfunded security efforts plus risk management are no substitute for real security work. + +Also be careful that your VM process isn't extremely fast. DevSecOps pipelines should be designed to create fast feedback loops that feed vulnerabilities to developers quickly as a part of the normal development process. Adding delays makes fixing vulnerabilities much more complex and expensive. + +## Where, When and How + +You should implement and integrate VM tools at the central part of your DevSecOps program to provide governance capabilities at earlier stages of development. Tools like OWASP DefectDojo support automatic CI/CD integration and manual reports, it also includes a checklist to track your application against OWASP ASVS V4, which is an excellent way to complement the risk analysis process. + +--- + +## Tools[^1] + +### Open-source + +- [Archery Sec](https://www.archerysec.com) - Open Source Orchestration and Correlation Tool +- [OWASP DefectDojo](https://github.com/quay/clair) - OpenSource Application Security Management + +### Commercial + +- [kondukto](https://kondukto.io) - Instantly get all security testing tool results in a single view, automate vulnerability remediation workflows and manage risks with key security performance indicators (KPIs). + +--- + +### Links + +- [DefectDojo Supported Tools & Reports](https://defectdojo.github.io/django-DefectDojo/integrations/parsers/) +- [DefectDojo Model](https://defectdojo.github.io/django-DefectDojo/usage/models/) +- [Vulnerability Management Principles](https://www.tenable.com/principles/vulnerability-management-principles) + +[^1]: Listed in alphabetical order. diff --git a/old-versions/V0.3/README.md b/old-versions/V0.3/README.md new file mode 100644 index 0000000..279a01d --- /dev/null +++ b/old-versions/V0.3/README.md @@ -0,0 +1,73 @@ +# OWASP DevSecOps Guideline + +This is the updated version of the DevSecOps Guideline. In this version, we have revised our documentation approach to provide a more structured format. The primary focus of this restructuring was on the core pillars of DevSecOps, which include: + +- People +- Process +- Governance + +Under the Process section, we have conducted a detailed examination of the product development process and have divided it into the following seven steps: + +- Design +- Develop +- Build +- Test +- Release +- Deploy +- Operate + +The following image can illustrate it better. + +![DevSecOps Pillars](/current-version/assets/images/devsecops-pillars.png) + +If you need the old verions please check [old-versions](../old-versions/) directory. + +## Table of Contents + +- [0-Intro](0-Intro) + - [0-1-Intro](0-Intro/0-1-Intro.md) + - [0-2-Overview](0-Intro/0-2-Overview.md) +- [1-People](1-People) + - [1-1-Shape-the-team](1-People/1-1-Shape-the-team) + - [1-1-1-Security-champions](1-People/1-1-Shape-the-team/1-1-1-Security-champions.md) + - [1-2-Training](1-People/1-2-Training) + - [1-2-1-Secure-coding](1-People/1-2-Training/1-2-1-Secure-coding.md) + - [1-2-2-Security-CICD](1-People/1-2-Training/1-2-2-Security-CICD.md) +- [2-Process](2-Process) + - [2-1-Design](2-Process/2-1-Design) + - [2-1-1-Threat-modeling](2-Process/2-1-Design/2-1-1-Threat-modeling.md) + - [2-2-Code](2-Process/2-2-Code) + - [2-2-3-Interactive-Application-Security-Testing](2-Process/2-2-Code/2-2-3-Interactive-Application-Security-Testing.md) + - [2-2-1-Pre-commit](2-Process/2-2-Code/2-2-1-Pre-commit) + - [2-2-1-1-Pre-commit](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-1-Pre-commit.md) + - [2-2-1-2-Secrets-Management](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-2-Secrets-Management.md) + - [2-2-1-3-Linting-code](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-3-Linting-code.md) + - [2-2-1-4-Repository-Hardening](2-Process/2-2-Code/2-2-1-Pre-commit/2-2-1-4-Repository-Hardening.md) + - [2-2-2-Static-Analysis](2-Process/2-2-Code/2-2-2-Static-Analysis) + - [2-2-2-1-Static-Application-Security-Testing](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-1-Static-Application-Security-Testing.md) + - [2-2-2-2-Software-Composition-Analysis](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-2-Software-Composition-Analysis.md) + - [2-2-2-3-Infastructure-as-Code-Scanning](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-3-Infastructure-as-Code-Scanning.md) + - [2-2-2-4-Container-Security](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-4-Container-Security) + - [2-2-2-4-1-Container-Scanning](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-4-Container-Security/2-2-2-4-1-Container-Scanning.md) + - [2-2-2-4-2-Container-Hardening](2-Process/2-2-Code/2-2-2-Static-Analysis/2-2-2-4-Container-Security/2-2-2-4-2-Container-Hardening.md) + - [2-3-Build](2-Process/2-3-Build) + - [2-3-1-Dynamic-Application-Security-Testing](2-Process/2-3-Build/2-3-1-Dynamic-Application-Security-Testing.md) + - [2-3-2-Mobile-Application-Security-Test](2-Process/2-3-Build/2-3-2-Mobile-Application-Security-Test.md) + - [2-3-3-API-Security](2-Process/2-3-Build/2-3-3-API-Security.md) + - [2-3-4-Miss-Configuration-Check](2-Process/2-3-Build/2-3-4-Miss-Configuration-Check.md) + - [2-4-Operation](2-Process/2-4-Operation) + - [2-4-1-Cloud-Native-Security](2-Process/2-4-Operation/2-4-1-Cloud-Native-Security.md) + - [2-4-2-Logging-and-Monitoring](2-Process/2-4-Operation/2-4-2-Logging-and-Monitoring.md) + - [2-4-3-Pentest](2-Process/2-4-Operation/2-4-3-Pentest.md) + - [2-4-4-Vulnerability-Management](2-Process/2-4-Operation/2-4-4-Vulnerability-Management.md) + - [2-4-5-VDP|Bug-bounty](2-Process/2-4-Operation/2-4-5-VDP|Bug-bounty.md) + - [2-4-6-Breach-and-attack-simulation](2-Process/2-4-Operation/2-4-6-Breach-and-attack-simulation.md) +- [3-Governance](3-Governance) + - [3-2-Data-protection](3-Governance/3-2-Data-protection.md) + - [3-1-Compliance-Auditing](3-Governance/3-1-Compliance-Auditing) + - [3-1-1-Compliance-Auditing](3-Governance/3-1-Compliance-Auditing/3-1-1-Compliance-Auditing.md) + - [3-1-2-Policy-as-code](3-Governance/3-1-Compliance-Auditing/3-1-2-Policy-as-code.md) + - [3-1-3-Security-benchmarking](3-Governance/3-1-Compliance-Auditing/3-1-3-Security-benchmarking.md) + - [3-3-Reporting](3-Governance/3-3-Reporting) + - [3-3-1-Tracking-maturities](3-Governance/3-3-Reporting/3-3-1-Tracking-maturities.md) + - [3-3-2-Central-vulnerability-management-dashboard](3-Governance/3-3-Reporting/3-3-2-Central-vulnerability-management-dashboard.md) diff --git a/old-versions/V0.3/assets/images/Cred scanning.png b/old-versions/V0.3/assets/images/Cred scanning.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8a87b4e7c09311997080e1ac68c5899af94469 GIT binary patch literal 117131 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μ&t^kz~!ArfsbvM5}dSWPZudaxBRTF58(Vc*8$2Bl}_z00fU1 zQSU{8h8sYtnK?v106XStSXq6oDwyQQVyT3jWh{L#@){z#7V|Azy{oqD;MoA;nfgD* z`d?<6H4g@Xh&2V+x^9Ne4_{AG?g$xvIaxL{sFe~mMA;K!PXJv zwURTmp8^W%i!UmCuf{{13;+5(ur%0zd&L-Y7V-tU@7#S@nfx>*F+MoeyTL@S5lFbygP}TC0|XUx4$R{YgH;tww9&9_?#ZEw%(dda@ z-j79?qZ3=p7+<-dv5CeOk7?bYJLyx9bU9ON^N-4y{013ixt{@R9jA2%#At`p;^>c@Ngt zAqnW=C*@3~mNnZz8&udLdy^w%-dXzl^oDi=;~5csSRxi{vp`7$7JnTn6#s(2SFY)X z-C4t_rFoaN7ZJdcfZ~K;7oBvM63D;KjZ3q{W}3$I7)p)EAB)B-Cnm}nYr|ehSba#+ zF1x{`hPw*%ySCJSIhP$)^cndj0!RX~`q&h4_;h0%n)s9duEp0+BsZMFzt>(LT6Pz2 z$>0XI$*Km=QgEHuc@-=)n?WfxE5B$(r(LALP!#m~r3Nr-3G@DF@G!>AB?f_C)b$!F z-j;no3%1lWQK(J`goAo#CoF<7s^Pnr#Er&o#NcV!KcU=hUMK)4wXorHk+u}J85)vm&wq`5taza4*ob6igo4J(A8<{}rJ z@yk+8Y9I)lhkC$PeS+^_hwf?y2n#NnBGFibKk7~0qGQMMKFK@OS(>+Xduiuit-k2Q z16X`+e-HziM+t*GIaXP(otFW9XP*K72zJ7CYyH<+rU7c92BC${JM_CcISjXlm3A*t zoO6RkIj%M)^KXLyA7$oh)?w;>(Ydvov21VS0nCf}ZRTC#&YreLU?Ssox9TV{i4iAy zbWeH_pxQ70DMt8Es({ZzTB1F-Iqa1DkdxHYv{)rC%6({~hjPy_IksQL9JLJkYl-Gf!!tw4z*Vv{+oGn7cAy`NYC~f4=p`gexN< zIx6&S_LVhE3Z*KP>9ZVuBT-Khm-Cw-`UHO&CVUd+_iF@tfepNtsaN+*JiOWs!ztAW%cO>V*DVmk{!w>2tsS{L|o znFCe0G666G8~3`gN;*GyphKnR53}@gYKs?<5FJLcD@itmB+G)fTxx-UbPK2qydLnKx--^Lb-!d;iw8 zsEP2Bhn{&H`aS=X0WMH_F8xpRtPFB@v$-scu-~2g(Try1tv-E=^~|`jcwVHixBdRI zZ?g`Sp++=cd?=BMU)Z3eVZW&M)9_E&u))JhhyC&vI4|MJ&GGYSO3q2H`?Z`f`z9`v z%yjO-+jMYp(>r3&oi!!phb~(BHAKBj9#g&Rs2Z!4= zhoq4qRj&mZibu(tIJGFvUHFzmOGAjI@0Y()mzi#0C1KXlSWd_xm& z1(8BOS%)ts3{C4tKH*^{Z^vEPXt&iN<;bJU5Vy1EMi}+XP;-1l?l;sa>OIY3Q|HhS zJ9kz2se4qaD5DG8$++439oOvdEWNR^6`W@+6T0kkSmE$kL>*{1`{GjPJ4SucAcrD; zyYg!Q>2pHq#NqmMOqpbtSAnTavu~%|Kd}?BKV)vbNC+lBq{&e|UH&zmP*nPZ1lWL% z0QRGg$X3-0Rij?lsf@eFqaxhOn;@t9Y{jPX6i!IfB+koX5=W|ZdBil>*k|3l<$f&C z8J7&qD!38x{^&0gmFF#%I9|?D85yFwJe~DgskxfmMNU<5F+w_tBVxSHpC8ii+wg?w z;$RH)QP;BNk(uOx=&16aaNU_5H0V5r>$K%>!^^|$OogMN$ z<%0-v2n7f*RGR=i7s{&wu7fTz$Kk-J1&^w47O4NAd-J8Ixocx**Cz9_DbEsj2*I9qWhHQ}y7S;YLsR)yrJ9EjehapzE z^?o5iLq(tuF0QulT)OvVOD3lc-1KSqHI%|-F7YGhWZo#>TObR21V?zvT$-!o zW0<6_QC4L`t3lC2NIlX)7{b@}$Tu&xwuz+X^3|qI5o|;GJUbCov0kV&_{|M3=~V*S z#T$!}9bI+3X42zayUCT{oo!-sNdBTj%U_q|=%LR@{?Jq$6qcK%sLI7VMaz~Ce{U!hRbQR`&7|Q7N=6a~@o38IRC(HUEAt9O_yxEPV z*6eWx8lu<)v*nskSR58hVJmv(LNj{W31C%0KqstL5!c8I7|CmU9Pjq>&vLAtl zS_Dag<*nq9wwV+ECvYPfpj7mi;C#3DrQOWMwpRHa&Iy0RQG|hosdJqtJDa2>=F&I$ zQq(U{x5D=z3+(d!W>>9bIh=LYv*4wRWFr@UEOEBt#JtCk)d8m94acAAvL-d`=Nw$XNV(>AC^R@Kc4z@N z@9?K^C#Rt+VtaBM!xyd=6qA@LN<*VGCDJ^RPFf&^_ zmnx-3L=;cm-=De-PC?mo&ekzO*J9*(3uX&-@4l}jik}+gz9SI|3I@%Tfa*aFYN~CS zN%{gb=Nt+TlrC!%9t%SQO`B)oqNZ$Sq~3?PHE06XPnUvS4`!sqKPXt`c#RrIgMhzp z!AtQb-9)5y-mLj16%XO~Zm1?6c<;GAc22sM_DN*SL#a6Q29KkiVs+ZGu-4LP6{)po zn>PcB<1V^LixxV|ARbzP&~GJ&x6O<`xO%dU`j2lGIgJj$g&OL~8Xnijo_CB8y72dI zKg`U5Klb59%WO%JWSWoY_yQD7pS5V3%(5d@qoY|VG&@!gXBLlPwt<$^#$MSmnrcQf z$d4@aytYpSvZb;Exjvsuvjfn7e%3@MF0hO>R}bdzDu`oKwC2;-RcP=1l8=I7b$&$+ zkr?2;sP;=_E&ZCqcdtNWc5*;YMTXf z9(q~0kES@8bXB5IXYT7XuIjY>%kV-JSQf2v{GTc+;B-cfAWl_CI8Hgj&nzYZZKX-u zEvgJ&`=5XH>$(Nqjx8(n`m?|4gHV3+4cCnOq~WYNwZNGeSbub;i9kio@!7gBtas4a zPIAdwn8J_ehN0zj#rNnx(;e01v39{3(bv1xnZnPpF=TLQ^|uCBqP54tA9|_iDCtjbPScz6Rr$i!?|(H7*WmVH4EZ{JpKwb&snx*3Vno5WAVAyE<#`qr(!{ z3fs7Lk1MC_Dh-Nw_2-@z%qfXnRzWifl^{i?x)!OO z0+mnen$ZuEo*wDBzCEim1<$kIcV<@IHrhCBeqwh42M=r@E}yImEZf@E4-7b*?kAjD zcmZEWNIVb1DO@59J(t~2M54qI^>kPYYgplG2|50vp+lSB3xDS{O=?%k&D(Ak7E$*C zMhV^`(exlnK$>>QGOzx6`EI_5>5f;|wmnn^l6Ew~>+0pvrNCm#2nvaHg9eo}aVP1X z{+pfW+r^H5Cx?|C9{v>EevNG<;fkEx1Fg1(&2DgE3+3`3Pj|7v$KwXQ-O3C{Gu77f zKRovvinf33iKzuAMbHubE-j>M97{*voRKzs{gndrhQ$i(kbILUw0R1ic~Y>R?P|Z@ zA%_{mbM4;BUk0W}pKvTD)td910Gr?-m(#cJD_R1`w_VKtm^cq_@9p0|u3YGodros6 zUuHsTk*IxuqEN~QnU_g9=x@|d5-6{i192hKW)|ga#ps`Or}z9%4lcxP6`SmblQ4-Y z*m0%$AhbRTxK?S*iZdx?ZP^W<>G0+cNc1jQNG|WOqnU4C;lQK2Z&il^Zr|-pFDcN_ zmgSsUwsubc!8W4R@Xgm9PtV!A73$qSV&mur^QTPrAoyAZ zltGu9-Ch4TETeA}_= zzNtmKxb}iZepxwi6cO^k6xxv}{Y1K7^ocjLbOOt3Dspr0QmuH;lk%}%u^7o6SX^HvB zZHfB>P#2gfdk>-(jzfv4%O`QZ1rD~_gxC+2X9NR_?MrP&YG0QQ9$YyMUGKLs?Lo#x zj2Rh_Wqr;UHawl_x!vy?DzVpwdSnECLZXc~!)!Kwr>DvRAx0~H8>f)J+k&xauWn*u z&mEro{iWk=_osL5dh{Q^d~|;DGVXxuzbPQ%hoMal(yWnzX&rVYi;Pfbr^$1%ILF(~ z!*Ph=hwWugMBS7CISET==UhvJtQS%K=VX(oO2_EHhWD#@dr=lbHbLNP7lc`#`*;8f zr;9Gi2*b zj)_gAiRI1JKf&;~G z**M4q?&>2Ld^^_uv0nsR_`DZC*vuz5yJqwFcIBJ#EFXS%+El9Gc#fcZ>0>q+VH}T8 z3}C_0ez$QK;P1I8(zv&wh$Qx>?Phru0SA{6PBvEAdM-H+G@Uy?6Dgt@?d)GZAP1cb zCPq#1xtcV6sG~L>%*T?NEOzFsrgTav99(R4^3V1T3~=h{$r)&vPUAB+@^t@j4)^fi zN7S@LWKUrEJ}Hg04AnOF=LukMl69%64Qaay@_48oKn-j^4>N%?=lUfFJ-azkr=J&% zDLn1Q3!FFapq%Y@bWl}Y-SKw!LpZF_A--3IgcIQi8ymw-#wT3z+@(CX5888dY!tn_ zHLpgazM1OI$FVz|O}~Tl!Jyot_s(KDSG7GMA-AhyD+BG1C*)b)-56aAMZbuE#OSoR z!e>E`FTL=44TcM_euRrXv|N0@3^9x8fgLxj96)a?e5}kL*FpByuTjQNbZZDnw@+f4 z12~H31sD?hPu{`BR}z-q-XC_7@k6Ww+r*YE!dv5lY=z1|z1V05in9(FPX+Y1vA&64 zKgy;bRZ&$9zUvFl45A0tX`tNYO8NV$fv}ao>Yw7qvyY^lRvySC!PQGw>C8RdTfiFQ>f$S~ls^=@xIkZ(GPsgGB4w1Wy2iqmgurwi^ZH!{4AaE~?a^wrn^ zBv*+$(xx>S(MlOe93PKioTxg%RLEy!1Q26t0@aMI{)a9!YUCWh3vegzm~Kd9Pt!}| zY#Xy9aP6s1Q~rteG|F=YM@qx9bA9pNe@yfoxr4>)gV4s&MuwwSu zTJnci{xIRm>rK^>ptm^OK}~)T(G}(_PC>JaItc)gp%;YD`%+|hp-2I8;)i)%Y9e0i z@)wYWznwtl?N@l{ZiXn^!=UJuaYaFH>Vso^=Jv@tc zJ-%&NUh~`ekhs-e)e|SUvYi*>dn!Gnb2bZ7J+nA2n7jBZGS<~|lG(jOQYDpU0uKQP z7l-hqWD#nHd~(}y+iZjPWs3HlxM*&^v`zqY;N%AGWPk87Z;>?MZ-)DFGs}B0!c8F` zaTPtKBJ`J0HTx(%bn1^vEhnMs#!H7GS2c*0*nQf*qc%94dR<*0!jLlX>6~K~97@&j zg}O?C>hAg1jHFVBCSfg{uP>q@r@J&;t>TM?F~n9)bSMsezRoF7IN8=6LLCj zlRC*=`ga212M9@e%SOyHM6v7SRco{oLuu7}oAoO6h19`|xnh}wm6AWTrdjCGjs{IX zE6?N;5)jS9Nt4s|*R!Dkd+8Ih+iX`^s^(p)Tc6vu+n=piaQwJZw_~O4_@yYvd2u`2 zv+~0mTC2Sun%}qinW(sFy9CWMi_DSCkgxFZqfHAD^pN*=|7LA8 zpHzaB6f3G3n-0t+TE_l~;4X5!<)7cLMl%O=`-*=Z-I(TmxF9#Ac1>Q3_yn`DPs?&o z9`ZLkZM}?rTwlF9T%C_;c$FV%oU4W#gB&j4toR1XE_zazzLbLsaSFInOc|QYxVfAM zH>#`6SD;Y)#h=+O(vi$nZMQ<5j7sSy{tpo+YzPq-ygMzoHPEB)SR77vEi(Ip4(0j@ z%>cyb;zFhf>Ni)0UpHkO7JtU{opjM+KagWZE_udWeMYvJd#xQ4bzS6WJ__8J?Ij!~ z+(#XPv!5VCR3IUNRt8h1Gq@h`sfl<^idvAcv0qOw9$n|Vd8s$z$#M$w`0kVeLn<3@o{Y0Cc5=*>b!B}>@X`T z_EC~$2i!vfWPz0%W!<0AC7IuepAf4`5tcfwU-prKxUgXAb;-(B0z{FB#LTNBr-vj7 zr9_iow&E|xgl6rT&O4L_d@kx|m%jykW(QqoZ;s)WAmx?Dc4K>VV=&DLGt7D(PWCa_ zAUSO}l^J-mQH|Te?YBuvR_8Q3TXvN@peUTruo*wdYJyu`TcMB4;)=-Z)XU&{_xGR^ z6&5A{Vn4O&kdjWMwY?>a1Vfsdy}e|g(~w5~AbYYW?pI;|+P@n8ZIRU*xrU$nP^0C} zq}8X$X9khz@=~Nsf;eSahy%WdPagM)y}if)r#;b#sf`*}jq~{KoTDw{60hZsOpG)| z9WTKgYmBPiF+}@MY!sgOH{5Ws_4|)gyL1drOI8Koy(>s?&)O#F3t$M19}=X+9L z&HDmVr3}qEtu~s)%vFpu>vZoU)ZVkM2iGP-nFUzc1w2-&o=kR4Gt|AgWHE+bhIkyO zQpvDYcJ4rjW=V=)-?Qk~INj^r4(EtG4qTYzLLFH^>R*48y#Hud=;ISuwo`psRKXTZ zsNlH9Uqz>3$zu*OchB==EiE|ECV{-Ht0NWkIC-=6Bc|Wmc6~#Zv0nW8Q@k`_DCX)z zXN{nyZCA762zB%^=R&v4EvVH0h!sP2Ng z_SsE`h0=<+xA@+kcpQ}IWh#EuP!cRHtz@1KO^Cif`|NuZ8rXEJbmo#XpM=;z!6nCr z;`9&u3YX(k^Ue{sp##Ca8X>EkzEQnL%BwP!-&q&$YY5lPnTTiRQYge&r$M$f@$Z%L z{W-nK>!O^-g)n#&q9<~V`ZlK0d3uu05=2Cr3GYo<6vPt$@Ve{@pwhr{qRIT*7gY-5 zbxXBgyMkl!UPI#5Kb=S@vo0?9%4*-MDA8ne z<@-m9AUSX!n%6Ivco7X}!9&TWZvK;2)XK0~+|X+bGswLQ>IJ^fuFDv#>K|;7$E0)( z*-^S^^~1q6=Bm(O4_WY`ukgu3l+G{QMtG~8R3v{pgG-R{(Yf_^>g5W%Wj>My*suTY zmNLe#GYA1H?@;Lea}7TfOs$<(w8?$WYxm9-1EAA*p*76leEgVKO|M)L%JM^0|rFqfw6W(mB zSd;B#a+%gir~mK0zjCi4H!jb4NUXLWI4rhHK^*t#T(y*4KPB~eqm|`OLS6s`Z$#1z za)vS$ZFSnr*u9PSB%L`C+I4dr?3W?7DPkc29PdmsNPn0MX&)8;l~aE2QPpCcZ8)fp zr;rtcMkzZ}?xQo@l zFF%XumrDYhR;Q^8$fRjtS@Ox2$1E1G(jMoD&m&?lPv3maYf8Id3eMB-ky(`>rWyRs z`HypLirTxAu*Ao|Fi@JYgCa=upn8DHwIfrUh!@iG#CvRj??`!W8Uf_C!BPhq(Z99j z(0>128zC=Qoe5#P&qXY0G?Z1gOI)jny#XCsuC<|TG2hY}f?D-0Rr7MUfq=niNbP+yOKE9Yt ziMDbD<3}`S-us5>|3$tJ>s|e1w-%S(Z?D;Jo zpX>P#IL58yi)MxXe*l?4X1_(8t4I?N^$KH8{&M>$C#R_M5WX(2QM@*=)*lV48J-hXqbM43@k8~w( z*2;CVGOyIKLg0uc0k}{zkxAcAz8rt(zI(bpaUoLcuuA>vUcq{2dKmM>KO-}PCfbykcQNl%<;3g$;q;Z z?!CpiOmSl%sTob&MDM}8g>qAnc?*^~Yte%)+k)hnH3e9Dars*UlBSJfKw6?I-mCLf z7cnWt`S)q}$}6v^3{`A-7mfpvAz~uBV^EzV&0>9$7z#k~06~tP7al?YE2-8cNc)1r zeD7U+y!TdOYgtg?{jsW?yI9t;7ajtLqlRl&@||~8cMiFS{XTW!HD6_tCf{?Ha}P3+ zQih2|AYGwYS@5ih6_&y&lkD6ZZ?aR)J=gBN;rdt^rVbtBO{hX~{`u#dh!Jkv&rdwT z2CAyk)Eqs`$IUO-~)9P(|h$&+F(z=aqc?+6S+d?jvgrv4B(4A;e<7K#rk4Li-(Hu`#oUz$l$<(hQ~j%y-W9A%4v&@{PD*hkAK%* zeL$rjHEL9ifinl*+mtUl|;rmk-MW8x=fs)T1TQ+<>e|704Zr3v9GpUYX zaHd#!{(G2$7hZT_aN=Qy1wLns?*ul%@{h*G+rh?#B3`LnD8#2!TzSC-!MUOSjyme7 z;EbRDJQ&iye|%r=IWO0pA4~bT^0LePCYO6f-^c+~RD14cScOWUj<>u1l1p5lSDbrJ zd|PEffurNES+ppAybkT#1p?t3d09R+gmaSzBOt|tbJ%}_XH(eimddY<~w*Qz9#A71ajv83JIzRZIKZ(|=xdu>S0!^eYb2z>u zM<*<6L|bP&pyUPGd^jJ>ZwK6<&WC#dB+2>lGG*%Yp#ScJ;x`;OBY7X>gD`Q*rRSO| z))j9vYuRR(gXQ~R!VS~8m65;I1nz&_#~ycl@a3ec$wVEHP<-%+SpJA_!>b1XxitM@ zT;9{|cmFwnJ|Aw&`?l>m1dlxOh}`P2$$$9BBVC)<-+U*&KX2X`6Ql3960O|}x+g8c z(~!mHa_2`fuRpKFix&rtGn)jbkGd#MN0<92IPQc~w;Bt;?dkk~{wtJUp`pI0nG)h1@H}y0*IZ>;wbuyz=fwBr4d?%ksO-IZ_S|ZmjQv-? z`c)t+)$Icq7Ee|xN@TWIqz zdT=EYm!Z;j|NhpbZC_itR7|CIO|7+J3AobG4=lRWiUQ|`6X=O}k!b@54Y9#} zJ8)PhurHS{nQt>Dj~A8s)Hp4eRDfdn+U~#W78|@re>?l^vmM(Gf+6uH%I{Fx=7LLp zX$7TP)?Bx}r=#O`+oHN#9kSDF=$^EN`QJ^jB@1TRI=NMc3>jhv9(bUAJ!6Hv_Ut2e z`K1?HXT>L`&RJoffBw0hd)hJ9NR(v+x8EueY0w`vC~@aKjk@v(t zHx_Ok)8v|RKZNfm+Ar2MZJ`+2l)0%S|)w02`=F^Rsu;7wcjP60{XAC0w3 zk3Pzp?6r^EMocSEtg1rs*Ay)h>EmRSwxUL&ccb!~{qP@8+9CVzZ!PxR%k9e_$Q`f^ zQ@i!BN*#yPfO%r{>OsMVj6BqOD@Mlka-wU(8eneyE?rBGSt){ys~%rf2Foq&vS@*e zZ~5&XsrYgGgGX5Jv(Jh3^F#msaLkML+?EDrF3tM9{%BBHqVhs=i+S;7o&0BBDf2}6rg9~^t45)-G)P8H6j!Qf+SEYB zb7No0T~0EvcYB4~m#tV96sv7m1SWyV5J9D^4FtEPR!j~z2?U-lnYc1^PTSh%cOr4R zbiuspG3g7j_*_XPDpQ1osvwlD@|Gswge$x+n4TX?@ zDD*}9g*C83WQTGwnXr_wWy7l&=WmHox;>eI{bI#*E8QZKer+YsOzTv|i1YpP#Ga~v zJj+@5BxUl2pj3zZByknO1Z=yo1?HJ?iInPPc`>8gw=LAzVap|2da-0))|85oOt2JK zf`nY5@bT#ls}g!XsQ_N+6RXl!!H4OnyHNF!Ja-TwvIx0?4|- z0`Yli6b0{#K2Ht;34K!FHhdh;A+}anj9|fMzb0CEoUwKl zRm+aVNE-CVy#P%>he~KM51`5K`2MO*RPi``M@4ffj_k2gL6A89g z%4!~W&6SotXt4D?XS5?cr0*76BZ}omsMH=VitBQZqN9Fo;#v+SJY3Yt(C{R_U_yO_5U~LGm3dG)fLk+g5G3skCiM^M^ZvKfSc4O~7 z_TDwdj=hTwv4RC`pa?1gyUV=4@0mH5XNDqWk=fnn@L^}>-se8|x#!ND-#xuX8k7@x zR{RKRduv=ob?*Vc)asbdE3Xp9EBCB*l#3RhYg+FUa7~Ldv$%b})(Fu`3-fjX z$y7w@>8ZO&NRcN+CtaFHdaf2@X=hKgSfLjso2;TdS~_`H-sS@VP5XMV}2j)>|A(>(UIlCV5h_2N0>3Sd%xJizts(NX(9*Ns*cM~7iC;ye18*ObiLmqSh z5na3WeW%`h^G!2NVJ;&Tg2e9SmtWo@OaUB1s{t6s65{Pq znwUQU6o3jq0oWE)L>-_9KyeItO61Rx2Z%YE+$I1G(BnOG(7uCt`OLXE764PwgY}r= z{gqctWeaRfuMs7gLOUiiehXfQ=k(GzLry^su%zwfCFH*l4;I~d?*@MGM`sa zXCM8qh=7dEnrsJ%RPfhKYSvPOZJ6yo`_wAXd;1Z_a(#4i2HXq~v_`|u zUYcIfx~xTs#@F@{kSXHO$r?xMyI<{KCZ5yevP#jzadI=`>jZ|CO0>re3piCPt$^<> z;r32E6xf<|e|>x1M<410;<2JW;YpRgql3;mJuH3TA>kLLF)X(2_I~&by(ZwAAvVqU zpb5k}>rT4=#E&HBhVXbd5hJ+JA^@SdVnSkoK`Q|uV$ec!f~7R%^y8TqZ3hjKV-_tm=>&KX@+95HX#=d6 zb{}XfXsV3+Qrk)&81Nl(Er450fHZ4eRK7B&q3TB#H@IXw>){4hRnV5C!u(rozkh$zfYw-J4Xczu3m1GAp1Z?){||_uLGc-_iaaEM291f70K&t01;_v^fQk3` zECD{WEw=e9=i)uD{09h`4=wD36Hc&o(&SV%BCX8Ok6M3cwGjDE!tojT5(nIPE0x06+?zuF8u@I1c%1vCitzIL{b;#b-dBq`8@~O<{D8GfE$gR{W~5HZ zx<}P&c@k6o=br|`*=to9!`7ko$qcIpfZo|K_`x+!(!)v3qTOt}h09AQ=BtU!8=gP> zu(0|mr-g6T28NPd8{TwVcKnRKDV9((dQ=)WO%60jz_x8uZGjR#h&&(?Md#5IIE3KD zoJSX1e}ZQ_+kmBbn|IJfLc1x9<1x?00@}<`I(CdSuo%n$9V#}UL7=TUAy6@A0vx`T zT&;yV$Xqg6KHG3WHy`*>WuVBqF=qm{Y1$CLXqDW(4UW7cL00_~3zSO+QaUW}3 z90-D@0xD*uI zDX}DfT@k?2(+m)FO^tEz5-{bdWuXFS!?(Oyx1uP2k9Bg7lkrhX~UlU>TGX2>l?< z>AkD22+tq!*Ra;v=b6AHUnnN4*Z>fATEHqrRLOMZfe7)q`p<^t1#iKmhq;mbFU(mk z^nERb?DgbLdiaom*Tvb*dR1g=0r%B z3TP6vnIrZW*?9ye^GD`1j>S|*tw;xbd_t0pMF7P;0*FgNi|ZvSFV+e%qgGYY%rU=C zUn||Jse^<$Y6ljpb63gc^JJJ(IeD{?oLW*q4Gy zj)=JmnXk|uDrADH_N3Wp9yBGQ1}V{Gr1Mh)utI{i6yyMiN+s7<&R-}Vi&i9mm1$)X zz7PO~rcqJwC)qXtN9MyKpVB8ETSw%YzWwaD_zx8@(Ecc@>x8yLg^$|B`uHY$<@|g} z+y@81RLRdoV@euSLI$n^k6QWOr2g7ADvMy+K$P@Bc*bGQ00~dUvDwRjL?DIWa&ZV~QGJ8sy=)P4BKQCY2MxfE za#EZU6QhF}V=>zyG-Ll6COR}8OpXpPrv2%A?k(y$7W&qT;SxAeWf}#V2cU@AE*^`3 z1T--v#zGns8>X`D>5n3AlMhcRwC89KJR8{jnYGi|dT<2iwu8 zRs1^xIDin1jBd&77qwxgNxJ&7Mq+<%7_r~DRu zhbnZP#rNIkD3@2vgH&Guz$jST2fxcSXhBtB=`6shmv8Ii2Or2rnQun{00bu>v@zZJ zlYTZxZwMtffx2Wqu!DVsa?2T~O6$Gjp@q^#0{X~&IFd177! zh-$R%3V{>^PwKxMo(JzUaP5;ch$lLHg= zNQ^*5$aw2|pC6%vnX6Bi$$}G23BgaGg98Z~6p?+r#-=a?G#W|gf;q{2HFD4s<)^P{ z247alF2bizryJDVFZ3BPVcnNQOHEIK<`gi#?BIskyfVz4J zehVIu;B*=#fsBdIH3oz$pw(8O;}Lv}ML^HfseQ}Sdjw!H@v-(oVR`x9 zFgq6WiFx5Q;0WkK05<<)O$GBFyeH2K&BzI@22*ToqT?E=^BDUB8P9pR-|o|dKdQfK z8eGgLzzlxG_mc+}B`Ige`uWj50in1&82j?u<)@2GzW4<3e{!GN=;4F9m-P~$-3nFu zea>=w^|moHx~^W^?-<5QWBN%N+K49~4_$gM7OLelBJT+^9}##(zNW&&)G@@z;(;A( z#>7ShVNH*og;DvJ`eE`l=}9L81I8*ht3q0qS3w7$&>&(h4FFZdi8QCl<~}p6DUc%; z@P0DO)#5w?6W1PD<0NTzrqu|92vT|Ksi(q6s#3rCI%|g$&pFo)N2?5~g-T>&e7%@U zDK4CuJnQQPI093dD5t0^C^IOgNPJ}wW<-VjTdtdJi2h&>#cZhj9&7i)YmICW@VQomfJDF|fa0+P7@!Voavi5?9IEzD_z zz)YD=Mb*UtNJ8fk_*pE)9DpP?kzw9KC5p{%Toc*^TA3$evnH+|J^_55Hjp>3PEI6d90c&8skl~) zR?1jH^W8LRrZ@$s;OC0ZqZOH^%CTCSk>96MlVx6`R3EK^c@`i9^zf_2J-B!XQ1SXA zfZ`zn|0VS&eNCJUAViz?dz4>6UehK5GQQ88pYKE`nMZl(;k%=JG&3npE%e>zYO1eG z?6FsM;lMg2*rHm0BDSx){s!Ufv(GjVZBQ6{tW6b$3vfnA-5VdO z1h#+&WWf~QeJ8(^s@Lm=s?1W@fB*f%?YG|^2FZj0{g~$Py8PdcG?UYi+iq49 z#qUFdK+Akek*~?FQ=mmlk5)@fHV*<2lhl&KgmiQ>30~lToU2ubriEtJt%psA1~uu& zF`+gxH{$QXL`ERS!%seGJ>1Sz0ckXen4U=7jm=qT07Ml+?rTHyLj#P*u^*G+R~qY$FY(6# zY=EQ#0plR6V6XK%K(P%$j=u-346O;xgE{qpmnFzDPL(IZj{=?8e?(|L$D>iX|BkT; ze%6at0{B2^bePx}OSGnw`Kz=KbD+y5G#L2lrcuVaPc7E|*#3#G6CjMi1kggGanNHN zdv z+H{?D!VQ;QnvX=}dSu?S$UMu{$^#<4E<*X^uy=fC{E!T^{70bq0J1unS!46!L*RAo#SS*T-4lm@h_WzrYy2-b`3X+&r)|anP(rsbp9BwnjPVjeBq!tRA$i!f z00SKfq!=6kJj{a#su;8YK7@Y^Mm&)NatN?^4ge|k^{^%gA)nK_08O&+Dg1|jf#C}g$QMY zw1XDcNd#YMDgpB%q`QdMHHEd}=L3WnC_F?kC%_7S<2AAUQ;j9sFBbCf4sgu-5E+$E zTn0=@8E_5qQ(ZT}%9^}V3R)GW*}PA3GV_LtccrFP=Hq|q!vR3db;bA2z*&Apq6YzZ z?kzzd?vMLf3>x*rc*(8`yZ7<+%EJMEZ-&jZ2$VWomeT(cn} z(kgl^J2~;WPG&$$z*fLXQDqJ_qr_JiYhdJwRVX@;0F9U|phSRLE5NDyLTi?(kl+>v zC&r>x)kw>%7ZCe)d~QTIn)WLYeroUC!@LT(nG>MJ8Ycgu_>^e2IY6OTo}))%vXa21 z+Cd!Ym(NSmmszNS`3S*GDJXh%;g|BrIu-&z@T86Q0`c@sGeTZtVTSO+Y*#Ay05^ao z9!sti{+HOV!rTaH(6mF<*l^+HH-sbh*~Tg-?6mD>Vf}U2*6&w{Ap$tbcWPTTAw2ZJ zJ>lr1j}F&ge|>oJrT0wx0C)^sBy`ah@fA@)fl%k`ZoDPD^5zFcX17-d4GwFqwtV>C zgLj!qI@Ny0!<5w z$_kkVGHj>T3TU@X->*#0_f00oW=<(KN>zlq44AMP&!*&HJiy0?jY~kSgeh_aFVAObvjeQY)m% zK?I`IDO&K0w(ZQUIAX*I3s=wmGG0L=3ujS~M=fr6qJBqCv>xI32OfAZrw*+}WB1r= zKObg2t=|3Yr`)#NZd){lV`)k9?z@xQKwNm)e{77Z<7X`>;U}=41SuYV)B&wNCVs zQsS?Fv{#DmN(0HZQLL91BJ}Eti2}Pvs`nM&8wFHkyZrmSS^xf1{ch9C3!--({k1xG z>NLgol{pXFefMlmRiwy0b=|eOE}c6Ujos;wf6Pr#k={}oProg-I&q?iZfWZg_R)TX z>!ptv#dWPqam+Xdz%q`)x5Uu9gmfQCXaA2(XwCUI1TAY*Pea(RKxb zSmVTa9Pbf?RCs^xg;$Gy2>a}Ja89izGJtsMxz}v%Uw%J6Yhnio9CX-`xpmjyC_DDm z4@O#5_8)&5mmSNGZ|(jAa)672!tuwSXhQpf%dgM2`MwP{{6ntO0$pr76~rMb+S8ZI z$M8y1z;&W?)94c51Yo@97vr|wZin28tFD*l%?0Ls7H#~yp^6yx|V(y+3# zdY17}Wu&z~eEFqCW8;v#djA!xp4|K6*=J5 zdSfzZxpopS;fwE!+l$b~f@XxYDEa=UVj)Lo-|tGcA>b9FZsUDk6*0>Dw5r0XlN(b-EeE}i%}CzE4=Z>yjF%_AN;|mnJ^zRWJvCYJ0GzY zAqeebjycBWW88mke>iKeLMK^%lowxnmjU5**IifiLp<}st8K04oqv&SM{5EIMu;yo zh;(pao;N=H*4E@8L-$q$`a}PF)W)&>y&)f(_CrVD!w)~)wgb3mGXT8uiLyD-1n+(9 zHET)Zz$a(9wPpcKWcoGY`T&v`$k+im@jup}XthEs8ScFkni$8jJtnqup13^=4>mk> z#O-Og$MR>!huV9Nz4ggYa{s(454KYbXvQ1pLj3F@2j)J1ZMdrTVRy|>+#jsNA-VN(IO3QenMK|DU{}RhDmc(n%-TxHHZ=C)CcjXjXAzo-TdEdg~8R5QTg% z6UT+qPe0wp9ew;+@=I-$mAt~=1$A4vi$yt7E!=7S0h@%KcK(a`ihA|T`wxbHrIrWc zU9J9)SH*0nlg_v}EYN9w^C9)>)yp=&H|%@!DPD8s<@Wgug(g?b+atU>@V>CZa!Xl` z4LeRh<4n5;1gPj2W@Gtt&K0+X->=~FG%2yE4vf;LIh%*`^LO%CwkF?J_uN$0z82*UNQ_n89qi&LgzS$ z01W~|8tUu9FWlS~MpR?q|EJ3F8u`X+K_;=HUq2nS-XuN`V-dR204FUvsdGgWqvK&#<<VI ztk8qyCu8%!6{`97o>Xt4^|gw2q*vNXE3IT>zZpI}U$K7K$)WqyM6Bwh0=o)*kI5?5 zE2pel*K6-}J<__eaDB$wcCAHUECV;TQ30ND1hLSXLBKJVIee@E zpT>HaG~=8QlI!FJMwl&d9RB#I6J>-kp{PKEmPTQYQ8AphgzGlI8$p|ZAXI{u`((#orcHP&1w z6a1rp%11HQOJ$+r1wEXc_B!aO4B**DBquaqYk`6UIN%DMa{N)@6aDD>_3LMmj{xfG z1Gdd4?P|R-wVS6+7IM#afCo*PGD>K+5ciT$b~Gvvd*?xc>La8J_=5!ZkJJQeR`!UB zCiAcW@Wh%L^HP_Qd+L=w*hYIB6nBqGybShM(Y7#XI=lgK^cYC$vmJJ*1_GjDAAAitl&@q()Q!2bu z=dfN;tWF-vPjnvwS0ii2Bt=nr?M5_2fE&Pn>zuPx8RMg{{?-5SLw>W@1YC{G zY6NZTf~gRb5_v^{2&O(j3!vyYkDBl0Epv8uDrmUL5bXj1hj8QRJQi{YL#k`U6*L$_ zC^g5pP(xgC?!}alT1u2dsui$y6&PTeL|Bqc+)IhZ^hlE3J;(+hUU+AC*m}F2?eLp! zy2)N?5D3-DL;*;7abR-P+%(Dl`kMTc-Pj*S@zIFhVO(499*f%N?__F$MvWe8uPd*% zW~M2UyVOoUXz1%N^C0L#fNfj+epOzK(01Cj%O_CMGm1RA1uT3x1o;8N-FM$@VadDh zx@-9A$9x(<>xy5jlP?pX5kn5Tya#v?{Fo@+Y-bfswEosI@p zmN`AA%);oEo6t4V)HoO0nIJCmi$=}&!_xrB@%mYEG5#)aEWpI|`*(+JB)e1Y33&{^ z(Z(=AMixGCQn4Rj>4+dN5|f* zqJ>P@^@!)+$MUi8+rPwlQP!KCVT&=6~z}3BXm;Cg1aDxJ)0^e;hq_ zoXyD}OqCEI4o??eDBm!U*76*?!YXUpetzg1ZM2a!EF`asq}nYI7*8oL6)+?v142CiZ}mRwFam+f zlYCssfG1&U-Fc-90EfyK07qP_5Y2`%NyVn51~U&~O2oI}LX8AtYVCPnE9W-C6F(bk z!DPo6wjqcgefR-OB*vt+>gsEUza6wk*lUMP1zg+M;RGtMCR({GGS9YczUf9`ivg>K zb51!n{6RI<6y;|o#`n}RzHjgDVYAIPvvC`5yh-?%0y?fe{~y*S{>dkwwC&eibB$>O zt=i^6h!*c?FaQytuvEYN6EcIp8Tow}QUODzs~_^uc$4wNe$t6O@AS3Op&`9$Fs3J-rK>vL`&Z zmp|PDKKxvKcet06MIBnbG{w-3ET z^~g|(uSc4dk$7!&{RqaO>{5XyexUaB8s`bWY^I_-waen#hc=w56f(!PDkLbI|B4nP z8sDLN{(H%H+ld6}g%_01s6gMmrN)!;GvOEesde5Q$*u;0hE?xS9YP4d(sGOS4qK`f z479@zI|P!O7t~zJ7qe~uI_-3`I9N?ane(jreZfy=1C+SjFiKT0SeMpFvbCZNgO#=_ zoX0vM3ry>zfyI?J0Bua8gDyBPj8o|>wA!{MjV|pRztJCw)kKZSfqF@sd0JOlVO5^8 zG4Bu^NRWgJL(YeJFpdgD5aHwEDVoBmULuMB3xpgRn}ZW$nHRGowffxbNHJD~V_d(F zb0IttlFScSAt6%-0?Cbd^zem?NuiGYUF&b!J=3(?2w)noQ-y#J zhP)e=?Ay%_C!mFziUdBik(sS)_l14hFnH*wu=;Ynv(JDGS`iv8*T5Q~&%YdLT2h}b z%Le73g#!;f(EMHheenM5ShTgh_TD?}w*UW`R#VH9g@`ut6uHG;7uQhaJ^@~Fi7XqZ zdmGn}QpphpJF{~e=XfN88mC>>-()=czSAy6<(Q}_L3@*; z$`AxX2%u=k;Y3*|Owa@|cq#~gG}?l0fkYj3_8`t|Lr>K$(h2>XRa3x#hv79tXl zC!ikd|K1N*$MSKZlT3oO(v(KO{(82(Rv_hmH7l-5tw6OCx#aT8!v`_i<3Y9kS zbur(d%P&<>#)Qy!yB$Nv5>1XZ{Fan}tC6|gao*O}#|q)vbAif&pP{%c51K;UD~qRh zv?%}zLFG@^fD0AJz5X9dMWe!8i0}i*ym%{h`4D8KLT;P{BmhT{27(kJ%76VfGhYoM zyidLGW_an<*Te9kL&Av9J`TV8-S5I`0-=rzE*8d45I7Wq48HoYCY*Qab>X-p4>7ws zhDCTmG7=!zGtq76yO#MObzDzM);4s_^vFPn)*&eO>!P4Z*xX z;OX1;PQE3ej0ST4!D#{SQl7bhY25A{Y_Qj#_L=~#rWvEmwLi|@Tp{-F> zo%($L{`bEv1*AcsW#yFw4twsoXXqr&4U2^Nl{9xN3iay8cgfjjhv5nk>7h0)fEI)$ z0a{_1Wwf@uR!G%)$}Uw)vqCdlSpT1Y{`o*L-nUK_KtkH7V~DSg>rjrGu3G^i`hI!sLkoKsuu;gDs`!90gn5t}i6h<|q=zDzwbxlE zbX|Q7+c!7=ROpK?F_x$?I6x@!krzJ~)>>}Su(M%Asv@7}UM|B#O zaQj7mB%hP9`LKEAiz$N6gAv${;2R0(6?`Q4Ul5QU{m2-i95G9>UOzvYCRzdGN}u!r z14Y&rIv(e_;`wLzlH9L^wqTltv?|)1II#vLZf8KscB1mA7Fe3A2EWi=WAiMgK=PpQ zD>@njA_vR1_}4tD2!am$)Q1-N~OT1dXc*QbWTwO-MoO>i(NDxgrS2L(Pw}UV1WNA1}!R!b07c%5HJ@2h#!c4Sq@r68sZCy1ti?GV>CaS z5^|ONF+gdI1ZNCd1Vj8FA&Y4;1}!uOBIbHZ7@~pTzoF853|a_S%z6m@`25oXEdoqb zeZownE~L>cxEAJc&_d(`P=H1ZT7VuJjB7PqC)cmv<`kfXIhAyS7_p%M8u#$k$!K?~jiFaS3|3uxhIqTLMF>DR+L8O!yfCA$X1F@O-JhI+jQ-GELPGyo5T^E6tK!@H`rJ$7$hWH`iN3x3TRGX)YyYz*s zF63(EwLJ@b(EGpr>tq8hTAtL)5>Tbwt8ATxYav0pZm0q$3eko<%@FNK&SNWqV@wle zs^^CQXi;1jjmmnMMW97Re9Vx9xjSe9jH*8v-ns8yE0|lODBp4cEv_#CSA3Ue^Zg_V zjkapEB!gV0NjZoSy@ud(!Ed=&3aUVOVGi^v3Z@wew9r%l0|X&s@v-o<&C|L2$`IOl zAS~FI3hPJH!u-hb0O{8fj*G~VkMN5D#=^O!QJGIk0O`aURAR^i9}u1hNVGCvJL8xO zlNHI!u_^2$X*ql@)wB@s2yb%SJV*h*5aumRY<^7$6q-5Ww~M>|0-{9Q0R~(X#G3f; zea7-z3uZQbh_~|~fOZqFmFxdO4-=RSJ;a@d0M!<>ZT=vEHpBJCpar{} zQWb@3_pZpSiEBrL12p|UvmIaEU1dX5U9=v$TT;5ayHlh=8c7itxBS$AJ%WZYELWFXYb zdi6X6d98Tf8f#~oXB+e$d?1L6ZN!bDScPZpEg@Sjb z%jdsY4gW?6_!d~keudiNTU$aKIE%G!|Lyl3&6QQoz*We{jm2r*E^^vJB1!ZXYWZ3FF1C;dIr3rO>#v9N@(+z=bE_C|zB7Bfj6$Me|1KK+_x5{S9t@ z0n*yPE;#1==*#Xk=-i3nkDhWv$ly}1$}3lur0a#T?#+o1co>8iNRX@0VEPD=TqRTc zYy1lZ8=+fUm|aA`R{kx0KCiJzJLR|RqJpd?m6Pk6uz79`v=iVKbDe$j0irGR&H`pz z-;S}1jX9c^B6veSu$C4@IxfBVkhc{KZRih<*4gclYs|bjf?1n8U^Er4d4p*zBlGtx zAp}j%CWEJ{GZiUNRFdY8s2_^N*i`%Te)<|!?*b9Gb~XBjPsA>k^Sd%9y<_n6iP(Dd zEG1#N9!1gRL(pKE#}W{KbB9f%b7NLlr>Mn|n_Y8%oM-3K*X%>OSuKbQ#hjjg*CilW z;k3;)g*vij4_o!F9Sh?JSrqnQ!B9yUWy(9C?9J)rGbPiCHDE@+3yKWaeB$!>k(9RD;0tpHhboIMK1$+ zCp_v^)u}x&K8W0s5rhd_G4%I>QDLE?Vlrj^7*<3=_=S)YW=u3M*}W(F6t%mL5soeG z_Mbd~EgguVutqR0gIk}$Qle@KPCpfnb6a$5=X(+~qhz6l@{9V?-tX(nowy$O%CDDD zVHjlSN%z6vrsh_svk{14FqiHkFmMslNT=KfE{E@JVTu!4-}t%mxjx4P>wzH3rB~4Z z8@cLwgamr(JI2b42vEb9NfcUUoMmot%!X%KO&5R~a{D^#G3QWv(&&XW8+ti`C_VSr zXBP>LxBc2Txl1cGybKpwwo?3iH|oOmTrSoYcFBoE*Z)F8JXg9%e2DigEcs_lH#X*C zQ}m1(6@QY5n{av^yzA>alq;)zP~nF=ZT$|(tO7+)WRp(ev1;f9+{hd=211DoX1cjS zHi=CavOV^AY!&3Z5!dPB**q>ZR*4Nyt3~e`N$u8p^dM=?A^+WGw``g{{hJZ2yF{n~ zwga-8k1!z^hQ9XZ^PRwS#S%XCIHUz4Ygj@}c@78TA)3UZtqemp@)EV3U~Pp9Ms|4= z22n`A?TO=bTQ@V(8j)m)3M+MVtd>N+MT7YS%0^QGCA^EQs8)Iqg}RU~M21T{$uoWD zd3P2Zf@46P!{y8^078U7#E3gV2dZD#XiW~eVyiCU&2I6zR(r6IM<&DKBRo^-jUFsm z2jTc@3Hln%%3K4j{J`1JK10_ny?`@yIlqq_mo6Nw6ruS(mC~{DGrwiq-@ic)enFS~ zTAt%1y3_p6=BUV`3Qi^3XM^f8^TpOk&DJ_AutlD(mtkytyCJW(k;#_}aVc(bFa|BFnR`!R*fa6Bc5KL3EPKBlVq@qL?7RCQ_$c{-r ziiz35&7j*uBP+PLC{ucvhay!nL=xq)ymdHE-4`Kd_G({OxbR|pwXsA}A{#uYsQs;$ z{dWi9=s7|oJ-lQunyN;Z!7|GqxvjfIdU>k0e% zE{~i2jbSkjS2btdth-<}rvW5TX>stcv_)q7O9^0-s0;f;k=xO0`FJ^(e3=AQ#7| z@h8oxPVBkkRDoqT)I}#*L2H6(fUh=XmZhopDYm`z8K@QI1sT_xe7oF&qZwX_I+e2$ zga4MKvoCqHXJx#wN;G+kcu9FXM?tTLw#4u(NDjNsMnbs6ut03mmQzpHf&1y%XGc$? z*u`<@)X1p^VR7en_5LLcWhBqr`=z6gB!bkkh+ld&x_4E9US~Z7LHbQ6XHgQ98f;E7 zg5hT#MV1fw4uviShUL9)A}!6$Zfb>8(=q6~Mx+tG?2f5uA$TX5F&9Qr_)|i9BIZXu zaE>E)bzUl&jY}Yvc<%5D%vE-COR&Oc#W1EI9g944d=uk|{ym#CLa~VQ=X$li!8lRU zrJDmX@%Ej8GoPKVBpx~H%FL8S-uZBBYX->u{$3P4?-%ZOPTMMqUogVni{1t?5>Dlh z5NJGOcCx}#sZE@iNCirP(UGaezjGX_T_4E^QZp{@8=&-JA7enG_%Pr}_r4)8xaR8P zL^Xl)P~nBljDFGy3)W#uMmzac_Y69x3QxTe{S$1jy7k!-@9mL6k26Tvab(mM4V-(1 z<|KtYh|)O*6W^q%W%4no)Rqc_beS7PP&3S{UQNS{lR&>zg;yjwLCoOA zL($0{8=)I|%M%%x1pQ^W{26_HxC0hm1RN8HnM0)<63D3W!;f$*Q_YnDP%i|cVu|M0k5$}0+>hZ{>O98uWvJ&!=Y7;b}?ld z*XJ0Ip7H1*Nr@e`oZ`}xBj&zgBrciH2Ub~StXl4>>{jyIRSaSAM%4T1hFzvgnB zcL-RrRtTqyB&sW0CX5)zG@51Zq1}D@N(+@P+KYAxN2OF+jfr5w7?Kp)TJFZqa2Yl1s~{Yh6Y#^=vyZ%8LaY4u+}R*GhHZ{d-VI^4@>4grkIEOr z7%v$_tOxd$ha(7QHFM0Rla3Kn6kRU`OkO3W(|KbJM#9IKP!=J>#<}+b#2L&NQs|&z z_%!k<5a=y6KF%+HyUJDN_}PBacl{UqjaM5Z41+FJB*!^F&-7w9j=oVjg%)4vNTbGD z#6V}U<5F>j80ck5AGw?zXsP#Tbz_RXcee~uLtNw4|K{SEay}f?Q<*)7c}M8bS{?Y} z3DI+e*cXS2G@ z^WAN)2)k`EIZcb=6V{GWdwwz#J2JB)w4jV5Vd2yG*kZM!J0YOz(T5=1fEMuAVT8dm zr@pmIH8ETUg&TLYl(F`5LPYK1N1+A`r(NXmT0kh^s`hjY@jy+? zU08bo5`FYxF1Ta>RSx@t?Cgiu8U-dK-EH$||^hayA z^w7Todl}@7HRy4ugmy zw9RLJ{D>O`g3mD`s(V5b+el#1?w6MP#?`$Za^vbRqF5a{u2`8<+>nee21APmuG zcxDqlKl{6}nURC6^jMWM9_BO<0RO(A))_hUOROpSe9v{Qaf7@|d?X1k58)m*#UPsL z)HJAFR8nUoK<0w~S(GwQ{Xj9HAPC0~8RR7PX2_zGS?s-=)*JGF-6WCgneu@qEa7S5 z8CznH--*A!9dO^5INYL0$6r8inf)gm3GGvR&*w4GAENNUKgTbyXTiD<7CvvBZq1Me zFXX5^*3WM|WhVx|Ht58bDs7Z;bKDCoFc%Hs9>9R0q_&CF7^q8%kvIO zHi*HN(yRV5b+MU?hMUF$Z|6H%2bOzU7w_6B;xquM!A;8{m24a`m*3-#-1EWc(yWq? zNvu7pSDPX$bP-dIscGXn)b2YXV%j!PrLvtbwsd{=U?}>D$3_5_x&ZPodiWlp;`E}% zRpHI^L3 zCo9~DU?V?Y{K?c8E~4{$mTCo94z+NxjAna(nqE~vc#w_>g&FPq)1I(C+#aba;ouac*@M1+NEiIQ! zi&j@|H;2K>cDx4ydnrpuQr5wolA6AENkZ~GK!f)zdOt3u6QceIGy5rFXW@2*I9zGe zX1PQDUx^MK+O^5#fIyhU-QZDC%`|<@JL(h5Hw}>drBb4U6ZTJ@EO#+@Iu~-`<4=%A9zS$@jW1=FMpuW;)%3?#rnv>$?Rw^TN+gN&nt6v4i zz=Uy4i4rG-K$0MF=$px~RJ3R%;&o2Fa9BFu+QLD-C@3kAppzZ0vV@06&H-hq1P|Ju z#6{o!)Z_vYE_2?YP8L;>^Hvo4-ezGUS``@YS(!!oov5KRVDtQJSW^wi#nClsG+1cD zvau^6=E%B+z(HxDYj2{84e}erpRQ({28gZnII2WW+j;D&lFOfmN?9 zWs_{A(6Or^O(D>Rcw>8ADY{BVIwcY!CMg(ys;w;Ktl{xny^H>#iK`J&%V~C=fp|W- zO_b(s7)a)e3KtGUG9yt?c2#-`-$vE*^JHUPF3O>&+*Qul7-|KjP|Ms8=8BKV6+^p8 z5*4auH$@t)YRWmb77nt9^@f$bT!C8J5qF=%?Z}w5L{lK%HXJ(9gkV!uJU8F4ZZ5=1 zXXez0;R37(IYc`m`uBK;jXOHx?ZfT#nq~>D+B@}-T5gL9fO5iYD4t3u$$LgcASuA+ zgPz~@Twiusq)Pstu8UxTKmwz4ZmkffRBu2Zh5-7c*sWp9zx?P5EJO305bT>lkH1{3 z1v-pq&;EVt8eq}kFD1EBFa~fTu-)+x+oZ)(uUfF@#|c^l@maK=LumEvBi`#7C6T=( zVKr@QEXKD`0b?FX*YzGxow?F_Z_6jUA`h$qNt$wS;e{4zXRk>Z@eg?Oe9~xYWPIfh zR5PkctW=5a!7dkBVr6G97MQ}czPA(0-eSDQ(g|PIWOME^&;v4dr1$3V=)QmCa}f_< zz#9T+H!SSQn*Mq$*UWxUB98nL9d0=s=%(Qs1GjC~Sg8EHfr>mCQ*b>{sE**GeqQ7- z^Xx`NAoSFN-Hp3GM{+bD7A@BTpYzSSBxiUCK@TqPPk1}@2HqZ7?S9G)ud-aef7cMj zDPK&3)Z2>Cgznf-Ghp6WC8WY-YmgXh7W^}sCu)=ntg)iY^>Kvh@JA5A(wZbfE^Ei+ z^G5kzj%{6Tf5-doowcDWVNKF*Eo8x|xI>PBJEhzgZ6rFr&Anh;r|~x;GwUWB-J={` zq~2HmZ~z*ruBDJ^Ac=m)B0u(gVqnel#L+5>E_}&5qgoMN$4el+!GhWdixSp2ttN|o zW6UbTloh*wtu5EZF$JHtSN6+&6xY8#D9o=>%sc$6v@wwsCA@)FDUM|yBmO?y*m7>D zIqr9BGwBBEV-1pbet68bHql>UK02FN2jZim=lv25Jw4jldcnE3yDL8HPl$_1ihYQ% zcPtC|5m#Qi+RAMppw?4x6|#%+XFSABFx#NlikMA=tuV?7bjg!wGw|Db6G?eprYyW4g{yH<7|kLf|x|O7tuP%vU8Z6T^?>{VzMM#%>Ble;l+2MI)ht z#!TrSJI;C+Gq2Y3i5y~>^_&b@^f@Vc#h7jNq*n2D>K<#NQqgxV%b48^EJ<_UJrm-5 zHzxmj9HJ`3#oBOSWA+D#lDKnpep69N|1mK4({XLZDVgtC}^q7ul84dWb}ii z-0_EmgbtK+N}~KxQA$YC(8`N8PqQSyFeV8)g z`MV3vFR=vAOudURykkMMSj$#&=q}1)X3z`WDN^p6lsSyIHhDMtAqpywivX~$y-4x9 z9ym1X%WxD>zvkoJS@_IsH{$8YUj1~vVA5PCEU@P5I;BXUehu@?ph%jkk4Xw}tXL8} z8W?>&ZP~&s59F$Mt)ktpq%AYLF~syol4Vc3ku4%^<$D%+;1Ktd#Np8KK)r zo=-&Z?1sh@t=DTWd`MRJEKZ8ZP{LrX+7G6@qXgp5JhxnU^N`MB4h_jAMsKb1cO8I6TO{~)(J)fsZ7 z5i#h_st4JIZFCh!4n=J-gla#3`2a4IjN6q}*aGasr9eA@qDaTZ2#Xwj@7mebzSejs z9FR==0v(ii#u0x!lRoY$>QVU#tp}- z4w9FGT^ZRxcxG&2&iISSIN2}2*r0HJ*becwXQ77ZU;#Tx9%uq@m8BEj-T>WE!;C5c z?CHj-t2xGgrb-6fn?56e3lug;)bHU2V++5|Xd)M(xiTVI*;9$aNgYg=O9J%#nT-it z1S!yPUz(Qdl)2?~qa%QSYgNOxy$R+IWICc`DF0wUPZoEG&!!ND-n$;9RiR&@29DpK zl-Zc-WVSGFU>}(J4R5XI^(=aP@e#k~ymu;sMYfav3OX}y=07K37Yk&dg;wW;d{wp` z^6bSP&-z@U%GUS0LqR|{6SZ3kf#e8043QgcCs0|PF<;2c<<;tUgJzGl~WoddfOC z3hTtSrjA+n)#`L-hE7iy(hGA7kr4vrx5HY0DjfD4UAYpy@)h6Z{|-vq02QX+{4vL3 zL3&5E;(+_RYY2XxRzbXE1!~g!mEn;^)aUHk>|b~BnAU=}cunfq8XX&Bl{>hT`8+t@ z{p(s8Q^p+CPlI>Y(rBeaCk)I( zM`t$8^t)M9xfM==9_Ae#W_oH6adbmB`w4r87EDH~qP~&{!5E?&2<@29u^7QadL5HA znWGlo${yy2Cdkq2l*mQ(o|T>$*SAQYNR`5Bta$$D-L@@(HOc+1hJ{XJ@#!eHHkwJ} zSF7f9OZo$u!}j5_WrlqPnKzAEMv-k1DUqm`lOVvnSXo6^=@3akJ6Ns%{ZU^lG2nAs zrA*jwDol_i}Nx1>;^w2Om5ytfVK1VS-e5Ns|bGE($DAZ?dD0_skkjo z5MCB+TNEx*(O?iwoapppuIN!FkP9y=bgWaTWwQ4k6lnCrxHoEdUK-9*G|p*+ z{m+^6ZogZAp9#;oktd@D(UwqfE8s_|)4-RxP5Bd`)4>dwE2o+}x7mdJ)-Tq@ru9%bgqw$CBAl8d^?%I`@Rhc8vr9+#wSq zXOBNAX#d9I(P1XKfSm55g%Kbw@b&8o3|XHI2s-KwP`}&Cbq|ZA7?bX5um5h3W+Nat zn31QKY!vt&Fv;8%O$@YSqPUyH)EpeoGX9=KP|2OogWXeVV@vp{Jc?&q{E0>e3O!)y zD^?RHM_h6HXr?s!MS(> z`0y~>?{+f?e5FL*O0QJ6Y@$XJC|h((LwD1P`y%(UHFmy|>ok=Peq||p8s1DcRi<_c z!A&XmxoL2O{bF=o_CxA|JBUP;mPzdc-8Y+GL@ZWl=|7$0PMdZ0_KsX-G91|IfsM_4 z<@nw^iykRfa1(i^2^XxAAjjr{M0E^@gozIRm}p;?paY7h8*$A&{PiRg;?mMd!TORM zoEFZEk(*+J)MVgN$|+@#7%_~OJC!RON+3lPk~|jM8t#4RDFmLvzEIeSVFT)l*a#Zd z9k}s}OcvdQ{_}WFFscC|Uk6PUl8JaUz>Y#2ngFeERvqxflAFfByxZM-SV^%oy1=Ip zsHJH_D6UgQXps&K&Z1Th)y@(oL@-h>P*;Psq`vYu8hae;K?+6CH578w6)H|vMrkp) z_?r`CTTD6$Y$@_3@A3;`L3#}9Y*I=nEX6z^*>AG}CF2CRhWg)k03syjigMC?S4~0t47r(9?s72d5`*d z688{Z&ZQh|KV(1Ozl~;B@)Tiow~G?9?`@S5ff*2fGx?mL zs^0wR0BauWNl;1W*-(40ONXrYri`^KH0;l0?_I_Q6#z=Y1>8M2q8My?(-WecJcJf` z;{vw7%l8J`eEZYtYNbR;4+`Nnxf)l@ydW4^~=P9j5pA6R8A3qV@^ z=Ggq#18uETS}5rQJHXrtSM|}cgO9cCsE#cH$MrxFpQL)g&?ex=V!*+8cLx&&2fq%$!$JOu{|!ztuuWY{TY_e$hkHQ6CZp`0$GwwpCt3 zAYNxZNR@VKO1m;jtsbcBCv~Ijc`3mN00(6H*=^U$-xG<>3V^w=y|Bit%8-E%H6$M? zM|``xX4>Qi8K{mG5q0hEG|TVZSP;K?>0NGKBhe8%-)^mIa*?o}ZW(#PdOnx%UU<%MyPG+VN% zFYR6XKsk*|mkK||>E8gye{^_e`K7Lu)`psUO3^F7_KPwMJeN*~m(*rA1v%aRK_G3O zrv!lC?cDQq)z2H~buWt`Blm~iWSmthTCo8I_9LIHcUmIh4R^eBcYD(z0ExTo$vn`6 z$wjCWubL(ZaS>84o*2>&Yp)!{TH&zs>SN0b#=e);+>wN>Dy=KrvHuw`jdbwqzL2yJ zP*S)^yO>CwK8NEFMUAlIU!FN4Xkcn9mH1UzhuKU+`r$$?U;=2U>yOcyoQ&OQ_3LU; z3$;WFT5aw$agL0ORn<|pwZxQ{j7l*Ct4GTU_BA{*k3VKX{D&e(H8OYXb;Q-^5CezS zo!$>hZ1|l|H_O(>Oj39NZ6q2Jh3^^f;7_tBIJO`-K&$l{Wl!*l0}wpuU^T_W|IY1Q zp^@tkxWu`8AkEPmLE%q?DRu?1&PMHq{ZoYGFe55>{GJs2j`V%^+&72a3PaT3I?ZBL zD))*k{1d(jEcv1GM*? z66hTW6i(N&eO~js#V{ZE#$=HAKv4?jGVKn`_p84T`eFPUyz$zMVz6}o>SnmvZMY%% zl{u5ejw3GN=6G3vwE-f%k!F?66o=4wrVSDPsg@%?5Qe8F%Jq1e^U`peiql4zKL#0S zT5%a=66Eu~0+04Q+#gntn>3Aak1F#);A*@LV$e^29acF3v7|7HfXAs_YO+uL_?lwv zOhg&{i3~`eP1I&#g`9vJ+1}0aTwMXW2L8fUclvVZSIYjQF@KSdA+bQik6heiH~O{x zMq99dQ~M*Q$UxlA_06&)2MLSQ2vd(&nYng(4cP8JUQm64^nFq9g>QE1R(bDK7eK&; zls$%*goOkUm!?8G{d_)RlMrs4I*f>&b;H3u*QBaSJY7kyv4Vjv^_rK?oL>oe^vX4H zVeDRuyG^B@Xhd5%5mFPtVrE)UpPkn@rAj?va$Dmpn291t|C};P!ki^BU|mNRZOnB4y0Lq%v^Z;~Ui}nPafTr@a{C_iy@6r* z7O2AAolT~NW3<*>~I>KBY8bR(oq#WZ`eS_^YU`jBch5YIZ zZM1B~qCMSTqov{n-0cu9XFmfc$H)9x(p%(GOk$lyChUeRa?)ZBWJosmGBYh>_~wzh z55pSg4MuzCl_nbjB=lDO&coLn+IAM^e)MNbz^Yp7ACaJwDdm1GtFkU&#;sreAg|=c_-O&q>+=$FQ zW)FxcrCWOlQNrNF3R15{qg+x<1#1>0=@<<2k6IB!I+q%4Q!omOmvWx3ifg)I(e$Di z6}`otp<9doV%@1lJ8$3o-f*0;-IQE(rA$K|eJ0?WfK?OR2nFP@7#>$0FG&E2-0y0t z;wz#>_L-VW%zJXSiP^Gz(fK#+qK-FFaXIIy(l$& zK#VxRe~_stXF)H4l6mw5l*%VPK)2%TQ3Y5A9-hQ3hk-DVN)(*J7W0FA^r8u+oPN}Y zw;~=#M{3EIU@c5i;AUYkl-85Rl^%Y)Jnl(s0K7NoKp@en$d#qe zyJ(S;mG4Ms{;%x@;MvtT+nLk(I6fj%_-s70Ww)do3+OEESkFS71=*}Nx@5iHblDSt z`Ri~TXrlis)ptvplo1Kq<+TXpPVyNs+4@??t9}rZ> z)9U%{s}4Vw>9J(JQ`^$;^>+|`chDQ{KkyFI73|-?t^vHdzB(4ZI(rI(e3(ecsgzw` z@8jW(&?&@4uZ|XHeyIse5KprLDmVmqZkvJI#e%{1UTL1r*}AR(F8bJq>uVl_E+6AIz2OdY$(Z0Z`EH>#lj0BXVa3Z<*YnJ$Xz$CFNEyvBX=BR2IZjlt9|H;$3s6d$E$hK( zuX=gK&PlScF?eZ!$f>mdz1LCgU~swzVwtHr182~@9j5?Ux*#Q{76Uu41SYA=5LFOt z<$sv5t%bXjx=g*q=-bZwsTQ0iptHYHu|E=rrVjDDg)fS=H6RwjuginmY&}4D2RzTR z4Ne*H#y5(@cN6?bRV|xeYlf(!^(;JijeS4P&CTij+JAmHRm|M#N@646z4%xJdl|J`{q2m| zqI@Aejc(=&_fvgdH7RY9bk?57BUB9wP<_reU+4MFKR?OxlC}4oeJB-eD*EvFawX0q zQMpCj7qEMKJ9GcdF_v6IB@Eh`Z*l%qz>U&bY2UOsa6+?yxrPfUOH5vNq!DVtt#N@h z-Uz;^Iw%~rA+j=ZUZsIgnxusYEOw6qpPgj*ZM@^2tBOht-;jAbno<)S_E?1a^*MXy z$7TonU;>zNy|oFJORm-E*?XbI!GQVT^^3`KmIsh&@!pk zo)!b96_Mi5bhnQfj>A{PpOB+&gvbk{r@)JJYcIo5yiI)dApk_24fXB(Yhta3(gh{$ zx_!!=Tzg>2+tlJU0X)x;Usp@sBiC5svZ#c3)2|^aB=YW(?#aE%=G9+@DOvMLf{<+? zbpn!wi%||o36DlrfxPIN0yI|GH$nSqRmiJQ3F%l$_=We6a|m?33tK$vDYM$j+k8sWPkax5tN12c=!(DT#7G8|fGo=ZXf zgfL6|+X$>^#vULNHAYTU)p>tVGfbb6xa>0Hjf<2{hcv=22*(Cf$*eKD1L{;=_&OSf zwrw)?V6#2+Jt%_t-Vmln)DDL$RkGahM9V;4XDUT(oO3I*-Zrp}$&!n&UO34A`Xs21+3gPSHHN-| z9ulVy<4-_06FdwaABindC?+SqI*eY4^hR5BWZehCPmHh4H+ep7@aAda~}oOJxB;yZCGQX8LUW{Rm=0`d_~U6)!}NHzUx+k z$M|xb2Z(j1GLa%%}f(U|t)`rf%_KGp~*S|bJyf8Do=EcGt{{BM99~k)_+4TFiZZF%%faqp7!_lFL zHL#T{DzgxP$WyrXZ(Uc@(xM|G2ktSIkK4i80FHO^0tnvwG~~(fF@^u-Isu9|96<0w zr2fziO%YmqCDQk#j5L^u_)b(cCCU&z=|f-!3a^f4EE3Yg75M7kR8t#i28Taj8_fFg zbsNe~frdpDubV}yJ|JiG`Ot4GMxe-3pQka-;2SxSjK)ffbg`flAbP zYJup@7A4l&(DTFzxc_{bksP@3r9rtvT!EKkzy~!uZd_=}R?uu?qfO4Yrd+|!e6z!b zB;Ddr(}TF^t}YZ1hObjIvL85BqESF%pH}M_1^df2dN;HbJ0{)d;qh`Z!!l-9v33Oz z4H37aKh6$DHo}gZlAGPEPPw8#U59&1r&ozW7pG9D;%d^9PZ2qt?g8WUbZqF?FZwTc z4nWhF{kcNqu47yT%H2%>8mOF_|0m9~YtLHgsY4L4`&VxbCJ2RzkZD5#Oi(onnpvh#G#ZBc1!PFj&#abw@s%rvYifucCgY~-!Ty2AA@xM zXVGu6m4t@$86ty)5&Em^{-E4!Ba9FefF<>5(p>U*E;;`Rag>W>aFyMAwLYOB9S5KQ zz%h~U81QpK2X<72_kU*k%G_j6dZXri@<*w+>ndaT{Gg2@3NX=k*-;E$zUIxxhB+*^ zo*&j;miS>ld#nI7!j8-EPD0msqfHNnWh3$S8B1?rEId>jr&E{WnVQ6af*GNSJ=<+} zphRLAMK5}w%t}kuY+Y`PsQkU~GQIsz@Z-0$+<$?KkC1X*jy9`$;h5e<*9`k6{S)9t zH#7Y#+=V}D1^V=@b&8b-Uu|9@4w9EN$6MHzZPCe62Hk>+eIUskjq=Hw9iXiv?loF^ zHzfojB!qe^Hv4^Zrc^I+i`_D6;kf|w^Dl?s(5&6~U5cxtS|D|g*3?(_N#&F2Get;`pTKCjq4e!HL) z$;DYM`2rqTPRmlA3iePrBkX*2xP|TzTrV=lkF>0P0kM=!bIE1(GmP0Wah8ah^c<#3 zfrpXmmMvnqU=3F7{WVm)xhp_|$W0J{?0yIykKMPvp3~jKj#k{l=Xvv6@AN_`NQYs} z8C#qnk`H6AvGwr9eY(0-tj3eH-LLyK@Kce(MMnXRIPKgdolY^ zfa>eNNCZF92#Pw_RGt~2Ldaw4DqbB*-l#vbMbf2d{Q2DxnFcza_oh2)&MQI~+!hSr zMO$JbRN-tMttmg8;!CifY;eYmCt* ziR)R-Md%;+(%*-69b+i91iQNiio@fjXBg?k#>S56d+7leoky;?K1CD|9gaC75cq4LzA`n4z$w@^tLHSxR8@%r4k8^3?gv?{AK z5%AJ9P%txN&-UDZHm*mOD2tR4U2JQTj%@TbZZh)c^zj42naA!xMfQ#23FIm=7Zdq- z7>>S3VD)lNk3~p96`am19ttU;q!{H({9#L1l{bNorMQ=#HR+3G(CqM3uKC*_d9TU+ zcxeuIV(K-Y0N^vVS3SGGn5)rxv|Bs|TnSoVO!Uky2$wpo_NS zri?Uru71S_KAxI5rRpfSD7f*sS2I*YxUs0$h-w5HBuQE8g~Jr2R5!)XCqXC-$b2sz zd+F1(X!*9>p0;iilH}KqcE&6LRdYzf$zTGyw?+Tl?10_o1MlxHe-cJOn4%-rR_+GE*!N-6x%N~ z3>W3n;!%$9wI%mo12d2avm#A+v$e z$J+|SguTm>*zh1Y7{fRE?ilDGW_!xWZrbALV*er63LvGT^S~;R)$z;H17M$Awz5Hg zCUO22Lb!zk*(S%44e~gTka(mTO0g6&GkkkzfPL5n2*`wZ$CR1GH zJ0Pg)C#3Q5jBlyYjh19iUY<{1NGw!By`x`R0it;O^h=y>$rj$N$F7L7@&U7^@xF~$ zkCt%9-N@&-kzZgCdfx622xpT~Zxi^TILBXjyz#fl=No2W_Uw$?(3(M4oZb_2_y&D- z#ASHP#o6g1R?xuUk2reJP^^VWtEDPWADo1xhl$1f*!O6JQY~H8PT7w+fq$BqqC}ek zZ*6y*r(tqm?NwEcZc6I!IG1+FVg^DROWKG#n@ zmcU9i;=i4QgsJ6(gKJN|=6z{9x$&{7f5ZtUa~2{3gs1rw}b zZJX~O7GmE~208A^jD=^n?U;L!0r^(!R0Qnf@Bd*mAG^%F%! zU@4aJ4K+#BC)(cl{9floGf@G5+JWymh-?5{y`ktL5*N(B{FJUi{(Erjz(=`1aUq`# zaxaJ;}^_llFkGI+M+!o6j3(p?{BT1)Rnuq!eKI29G z{SSQssV~Vz7{X|q3Ma2!#n~&tz*6<3zbebr^5b}U8LLS@@fiSBHHLzjNam#B!I*}+ z_q)^CHTI0^0l^q^HIFP0A=jL5R{gtVOhzpM1SK>h@)^JlXwv-v$rZmX@J# z7D$GyB$^ue$-_bWN&7Zwqzb^(0HQwh5uOaM@k)F#DF>lDZ0d98-k_1foB=<1VWgb{FWHM*jBC_INj-% zUBufNAv~mX#8cK>_kVpQS z(1^>U#h7 zx`}PP)RF=V7Alm1M>Kizq&E2aZr-^5@AF3uy(K2#XcU!b)vs?5`svA0bjkITfL2QT zv_8MdpASUQ?+I97YhcRg*(ShYg#r}MNJ!_1`}G3ekd-^>zJj(QreQ_cyJ)bV%A9=Y zK>re1qEa=VpDN%I08T;qI=TZAY#WmtzA$H!P1J&sXO>^vEBBF42jHXk3GHQ?3)$G< zeOiXfFaY~ty5a}w6{LC1-xh;rzsOMWO_uw`K#Ffs!6o1f9JIk2WiTbpCXQ9HlCOUn zM`@}1m#(e3u$A#5@DR%%32iAh2kxrsiU(Q&?B&zHgGk{z(A&Qu#$6 zVeVJQ)a#hCASC{ zC&B~dzCTS@(J-w@U0Gy8@@W&KxSw#?-r|_hL$3oTx zxT(nwb(5Nx5i0JcY4)-#2;KjuK9pnNEKm$JKZ1oETM>r19$0O=+R30|LT+0Sc%9OxH;*lVkAjJa^~lO{^P(x?O>S;xF?>6yJ( zt%hU40}DUXRdKO=Skw#D^$3-MXB#S@So#n(fxprHzcPVJ1HUC z3^~4^%rmAbpn;3LFuIz*Y^^J!;JVn5MwkWRG^v6|Rh+umSay#V8GoSx%e?dpc<2{a;K#-2WcKdH0+5v%FjyYP-0n`}S1ym;DqJm}u(Vclt; zZ)kd5($>D9y6F~EDNP&ejX)q`8)wqt16Cd+b^R6trw+Wh0wnKDw`m1_M3tjhkrQNK zNBJNcgf3M7Iw)&e^D~#lP1c$5JpLA>QVHTPVEkUl#kq`7Eb+gJ4FNMTYancKl;&vU zi5*}J&Jw+YF3c-^x&X?atSr(vqdviI{{bpNC0^^;JOoJywRcM6&w*M61Jz|9b#G~I z9@tBY%&5ZV7bwI;B}cAnz51uR(%Ioueyi6iCD7JkEz0c~Fl9ThrmQzpcBR&QFqvae zQRm&(P#RT3{RfPg-y5j}#$FrU0T<0h^5mghja;FS%dXPzwuXgLtSZOC)84NJVwV(Y zWJK#dGA})Ms4ie5V0hUZhED#rH7g_jEPqu%Q0-T&jFTyKVQrnbQf(|p0#x{FtqMV&d)Xy_9YLx4I#AVc$;c^3IMnYh}J5xywr2gs-}p(YDKcV4s*K zD8p}_%F(C8O5Bfh*SN|qhb8vg!iL!B#hq!>D8^u$%=|I?=;JTZ8R83K^KiqvT_So4 ze8ZHKl;!GoYE6}Fu<)JX-3kc0ohlyg?u}3Bj(&3@x~5+$w%omqQW8#*?_YaAs-kz{UbJp3L(lx3EiHd~1#ZnOhMv6mIz$4%M#5C8(B1OKxeo0P;{jj= zBfD>N80Jid&*H?$$;q2e;$37;kB^T%eoW-;z>9IIV!erri*sb&rhT5@sz033)>NH8 z#9tE5D$j9$hFr-vkNPhxEOf=?9aIER^JSf%xWyLt@@`dB-|>NM^#|Hystiw0Pn*eQ zR_mH#K|wFN>z{*Jj3{?1dkqn`4+>S&HMbs9auNU`r#@{z8RCm^ zzyi-igokZtK1)LV`WH-?p1HgdL>S=sHx%S5E*lISO36UUh`{v&b*&H(aC`tBeu1bl z92uKZGFL{@$(^xGDiAns4jXLy%|He?9VLW{vPJmK9Pm9*5Eo1j-@8hx*US9F#x^AT zY6E;PusbzyouptM`}Hzz$jDWga(u7nGgX#!iqWu*e7%e?JiKm1KFRC(IO!={21@v3 nUoS%j8(c1qeLg85;;737DRkljnH28l2tY`pk literal 0 HcmV?d00001 diff --git a/old-versions/V0.3/assets/images/Dev-process.png b/old-versions/V0.3/assets/images/Dev-process.png new file mode 100644 index 0000000000000000000000000000000000000000..468dd9a11aabf4fbb00c9038bb9c92de5171004a GIT binary patch literal 23251 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 literal 0 HcmV?d00001 diff --git a/old-versions/V0.3/assets/images/DevOps-vs-DevSecOps.png b/old-versions/V0.3/assets/images/DevOps-vs-DevSecOps.png new file mode 100644 index 0000000000000000000000000000000000000000..61aabf6017677788e2706cec7f123ccdf3047689 GIT binary patch literal 110261 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%0AWpU$Q&KPsKs`E&dX(0F;t`zVFhuUI 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

%K%lv#C(o;sJAg_)I&B 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 literal 0 HcmV?d00001 diff --git a/old-versions/V0.3/assets/images/DevSecOps.png b/old-versions/V0.3/assets/images/DevSecOps.png new file mode 100644 index 0000000000000000000000000000000000000000..5f7f78f3e1c36c14643a42cc7192b2d4a542e699 GIT binary patch literal 30721 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

>0%%@GGK>-plL(`m0%s5?mZ)B6zC(|e-UE!0?Y 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⁡vD##=r&V};SeiH1tb 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 A7XSbN literal 0 HcmV?d00001 diff --git a/old-versions/V0.3/assets/images/Pipeline-view.png b/old-versions/V0.3/assets/images/Pipeline-view.png new file mode 100644 index 0000000000000000000000000000000000000000..0a95d8d9746313899df3f040e256816471eba38b GIT binary patch literal 8017024 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�wE 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