{"id":1198,"date":"2026-10-03T06:50:19","date_gmt":"2026-10-03T06:50:19","guid":{"rendered":"https:\/\/www.devopsschool.com\/tutorials\/?p=1198"},"modified":"2026-10-03T06:50:21","modified_gmt":"2026-10-03T06:50:21","slug":"owasp-dependency-check-complete-hands-on-lab-guide","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/tutorials\/owasp-dependency-check-complete-hands-on-lab-guide\/","title":{"rendered":"OWASP Dependency-Check &#8211; Complete Hands-On Lab Guide:"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Complete Hands-On Lab Guide: Fundamentals -&gt; Basic -&gt; Intermediate -&gt; Advanced<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Generation \/ verification date:<\/strong>&nbsp;2026-10-03<br><strong>Primary scanner:<\/strong>&nbsp;OWASP Dependency-Check 13.0.0<br><strong>Primary build ecosystem:<\/strong>&nbsp;Java + Maven<br><strong>Capstone:<\/strong>&nbsp;real intentionally vulnerable GitHub training repository<br><strong>Audience:<\/strong>&nbsp;developers, DevOps engineers, DevSecOps engineers, application security engineers, security champions, trainers<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Safety boundary:<\/strong>&nbsp;The labs intentionally use known-vulnerable dependency versions so students can observe real scanner findings. Do not deploy the vulnerable lab applications, expose them to untrusted input, or reproduce exploit payloads. This guide teaches identification, analysis, prioritization, remediation, reporting, and secure integration &#8211; not exploitation.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Learning Path<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>Fundamentals\n  -&gt; Understand Dependencies\n  -&gt; Identify Dependencies\n  -&gt; Scan Dependencies\n  -&gt; Find Vulnerabilities\n  -&gt; Interpret CVE \/ CWE \/ CVSS \/ CPE\n  -&gt; Analyze Risk with NVD \/ EPSS \/ KEV\n  -&gt; Generate Reports\n  -&gt; Manage Dependencies\n  -&gt; Handle False Positives\n  -&gt; Remediate\n  -&gt; Integrate into Build and CI\/CD\n  -&gt; Apply Security Gates\n  -&gt; Generate SBOMs\n  -&gt; Add Supply-Chain Context\n  -&gt; Work with VEX \/ Provenance \/ Reachability\n  -&gt; Complete End-to-End Capstone\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">LAB ENVIRONMENT AND VERSION SNAPSHOT<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Verified Tooling Snapshot &#8211; 2026-10-03<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Tool \/ Integration<\/th><th class=\"has-text-align-right\" data-align=\"right\">Verified version or current interface used in this guide<\/th><th class=\"has-text-align-left\" data-align=\"left\">Purpose<\/th><\/tr><\/thead><tbody><tr><td>OWASP Dependency-Check<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>13.0.0<\/strong><\/td><td>Primary SCA vulnerability scanner<\/td><\/tr><tr><td>Dependency-Check Maven plugin<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>13.0.0<\/strong><\/td><td>Build and CI integration<\/td><\/tr><tr><td>Dependency-Check Gradle plugin<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>13.0.0<\/strong><\/td><td>Referenced for Gradle users<\/td><\/tr><tr><td>Dependency-Check Docker image<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>owasp\/dependency-check:13.0.0<\/code><\/td><td>Reproducible CLI path<\/td><\/tr><tr><td>NVD integration<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>NVD API 2.0<\/strong><\/td><td>Vulnerability source used by Dependency-Check<\/td><\/tr><tr><td>Maven Versions Plugin<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>2.22.0<\/strong><\/td><td>Find and apply dependency updates<\/td><\/tr><tr><td>Syft<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>1.52.0<\/strong><\/td><td>CycloneDX \/ SPDX SBOM generation and license inventory<\/td><\/tr><tr><td>Grype<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>0.119.0<\/strong><\/td><td>Complementary SBOM vulnerability scan<\/td><\/tr><tr><td>vexctl<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>0.4.4<\/strong><\/td><td>OpenVEX create \/ validate workflow<\/td><\/tr><tr><td>CycloneDX<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>1.7<\/strong>&nbsp;current specification referenced<\/td><td>SBOM \/ VEX-capable standard<\/td><\/tr><tr><td>SPDX<\/td><td class=\"has-text-align-right\" data-align=\"right\"><strong>3.0.1<\/strong>&nbsp;current specification; Syft lab emits SPDX JSON supported by Syft<\/td><td>SBOM \/ software metadata standard<\/td><\/tr><tr><td>GitHub Actions checkout<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>actions\/checkout@v6<\/code><\/td><td>CI checkout<\/td><\/tr><tr><td>GitHub setup-java<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>actions\/setup-java@v4<\/code><\/td><td>CI JDK setup<\/td><\/tr><tr><td>GitHub artifact upload<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>actions\/upload-artifact@v4<\/code><\/td><td>Preserve evidence<\/td><\/tr><tr><td>GitHub SARIF upload<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>github\/codeql-action\/upload-sarif@v4<\/code><\/td><td>Publish SARIF to code scanning<\/td><\/tr><tr><td>GitHub artifact attestation<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>actions\/attest@v4<\/code><\/td><td>Provenance \/ attestation lab<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Important current Dependency-Check facts<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Dependency-Check 13.0.0 is the current release used by this manual.<\/li>\n\n\n\n<li>The Maven plugin requires Maven 3.8.1+ and Java 11+; the labs use JDK 17 for a stable classroom baseline.<\/li>\n\n\n\n<li>The first vulnerability-data population is much slower than later incremental updates. For operational CI, OWASP strongly recommends mirroring NVD data rather than depending on every build to populate directly from NVD.<\/li>\n\n\n\n<li>An NVD API key is strongly recommended for direct NVD API access. In CI, use the plugin setting\u00a0<code>nvdApiKeyEnvironmentVariable<\/code>; do not put the secret directly on a debug-logged command line.<\/li>\n\n\n\n<li>Current Dependency-Check report formats are: HTML, XML, CSV, JSON, JUNIT, SARIF, JENKINS, GITLAB, and ALL.<\/li>\n\n\n\n<li>The CISA Known Exploited Vulnerabilities (KEV) updater\/analyzer is enabled by default in current Dependency-Check configuration.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Workstation Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use macOS, Linux, Windows with WSL, or a training VM. Verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git --version\njava -version\nmvn -version\ncurl --version\njq --version\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Recommended classroom baseline:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Git<\/li>\n\n\n\n<li>JDK 17<\/li>\n\n\n\n<li>Maven 3.9.x (minimum required by Dependency-Check Maven plugin is 3.8.1)<\/li>\n\n\n\n<li><code>curl<\/code><\/li>\n\n\n\n<li><code>jq<\/code><\/li>\n\n\n\n<li>A browser for HTML reports<\/li>\n\n\n\n<li>Docker optional<\/li>\n\n\n\n<li>Syft and Grype for SBOM labs<\/li>\n\n\n\n<li><code>vexctl<\/code>\u00a0for VEX lab<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Install Dependency-Check CLI &#8211; macOS Homebrew option<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>brew update\nbrew install dependency-check\ndependency-check --version\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Install \/ run Dependency-Check &#8211; pinned Docker option<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p \"$HOME\/OWASP-Dependency-Check\/data\" odc-reports\n\ndocker pull owasp\/dependency-check:13.0.0\n\ndocker run --rm   --volume \"$(pwd)\":\/src   --volume \"$HOME\/OWASP-Dependency-Check\/data\":\/usr\/share\/dependency-check\/data   --volume \"$(pwd)\/odc-reports\":\/report   owasp\/dependency-check:13.0.0   --version\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Optional NVD API key<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Request a key from NVD, then expose only the variable name to Maven:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export NVD_API_KEY='REPLACE_WITH_YOUR_KEY'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do not commit this value.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Install complementary tools<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">macOS Homebrew:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>brew install syft\nbrew tap anchore\/grype\nbrew install grype\nbrew install vexctl\n\nsyft version\ngrype version\nvexctl version\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Official Anchore installer alternative:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -sSfL https:\/\/raw.githubusercontent.com\/anchore\/syft\/main\/install.sh | sudo sh -s -- -b \/usr\/local\/bin\ncurl -sSfL https:\/\/raw.githubusercontent.com\/anchore\/grype\/main\/install.sh | sudo sh -s -- -b \/usr\/local\/bin\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Shared Lab Project<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The first modules progressively build this safe local project. It contains a vulnerable dependency but the application only logs a fixed string. Do not feed it untrusted input.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create the project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p sca-lab\/src\/main\/java\/lab\ncd sca-lab\n\ncat &gt; pom.xml &lt;&lt;'EOF'\n&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"\n         xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\n  &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n  &lt;groupId&gt;com.example&lt;\/groupId&gt;\n  &lt;artifactId&gt;sca-lab&lt;\/artifactId&gt;\n  &lt;version&gt;1.0.0&lt;\/version&gt;\n\n  &lt;properties&gt;\n    &lt;maven.compiler.release&gt;11&lt;\/maven.compiler.release&gt;\n    &lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;\n    &lt;log4j.version&gt;2.14.1&lt;\/log4j.version&gt;\n  &lt;\/properties&gt;\n\n  &lt;dependencies&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;org.apache.logging.log4j&lt;\/groupId&gt;\n      &lt;artifactId&gt;log4j-core&lt;\/artifactId&gt;\n      &lt;version&gt;${log4j.version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n  &lt;\/dependencies&gt;\n\n  &lt;build&gt;\n    &lt;plugins&gt;\n      &lt;plugin&gt;\n        &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\n        &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\n        &lt;version&gt;3.15.0&lt;\/version&gt;\n        &lt;configuration&gt;\n          &lt;release&gt;11&lt;\/release&gt;\n        &lt;\/configuration&gt;\n      &lt;\/plugin&gt;\n    &lt;\/plugins&gt;\n  &lt;\/build&gt;\n&lt;\/project&gt;\nEOF\n\ncat &gt; src\/main\/java\/lab\/App.java &lt;&lt;'EOF'\npackage lab;\n\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\npublic class App {\n    private static final Logger LOG = LogManager.getLogger(App.class);\n\n    public static void main(String&#91;] args) {\n        LOG.info(\"SCA lab started\");\n    }\n}\nEOF\n\nmvn -B clean package\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the build succeeds, continue.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 1 &#8211; SCA FUNDAMENTALS<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">1. Open-Source Software (OSS)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open-source software is software whose source is available under a license that permits specified forms of use, modification, and redistribution. In modern applications, OSS commonly arrives through package managers rather than by copying source code manually.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this project, Apache Log4j is an OSS dependency resolved from Maven repositories.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">SCA starts with inventory. You cannot reason about vulnerabilities, licenses, or maintenance state until you know which third-party components and versions are present.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Identify the Log4j dependency declared in&nbsp;<code>pom.xml<\/code>, resolve it with Maven, and locate the downloaded package and metadata on disk.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Start in the shared&nbsp;<code>sca-lab<\/code>&nbsp;directory. The initial&nbsp;<code>pom.xml<\/code>&nbsp;already declares&nbsp;<code>log4j-core:2.14.1<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not discuss Log4Shell in depth yet. The learning goal is simply: &#8220;this application depends on external OSS, with an exact identity and version.&#8221;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open\u00a0<code>pom.xml<\/code>\u00a0and locate the\u00a0<code>log4j-core<\/code>\u00a0dependency.<\/li>\n\n\n\n<li>Ask Maven to resolve and list dependencies.<\/li>\n\n\n\n<li>Locate the downloaded JAR and its POM in the local Maven repository.<\/li>\n\n\n\n<li>Inspect the package metadata and project URL\/license metadata in the dependency POM.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Maven coordinates give a reproducible identity: group ID + artifact ID + version. The local repository proves where Maven materialized that external component on this workstation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -n -A4 -B2 'log4j-core' pom.xml\nmvn -B dependency:list\nfind \"$HOME\/.m2\/repository\/org\/apache\/logging\/log4j\/log4j-core\/2.14.1\" -maxdepth 1 -type f -print\ngrep -E '&lt;name&gt;|&lt;url&gt;|&lt;license&gt;|&lt;artifactId&gt;|&lt;version&gt;'   \"$HOME\/.m2\/repository\/org\/apache\/logging\/log4j\/log4j-core\/2.14.1\/log4j-core-2.14.1.pom\" | head -30\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] The following files have been resolved:\n&#91;INFO]    org.apache.logging.log4j:log4j-core:jar:2.14.1:compile\n...\n~\/.m2\/repository\/org\/apache\/logging\/log4j\/log4j-core\/2.14.1\/log4j-core-2.14.1.jar\n~\/.m2\/repository\/org\/apache\/logging\/log4j\/log4j-core\/2.14.1\/log4j-core-2.14.1.pom\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the exact GAV&nbsp;<code>org.apache.logging.log4j:log4j-core:2.14.1<\/code>, the JAR location, and metadata that points to the upstream project. The local Maven cache is not the package &#8220;owner&#8221;; it is only your resolved copy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Choose one additional dependency already present transitively, locate its JAR under&nbsp;<code>~\/.m2\/repository<\/code>, and write down its group, artifact, version, upstream URL, and license metadata.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can identify at least one OSS component by exact coordinates, version, local artifact path, upstream metadata, and license metadata.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SCA begins with component identity and version.<\/li>\n\n\n\n<li>Package-manager metadata is a primary inventory source.<\/li>\n\n\n\n<li>Local presence does not imply your organization authored the package.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">2. Third-Party Dependencies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A third-party dependency is code your project obtains from another project\/vendor. It can be open source or proprietary. Package managers make adding one easy, which is why dependency governance matters.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Every added dependency expands the software you must track for vulnerabilities, licenses, provenance, maintenance, and transitive dependencies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add Apache HttpClient as a second direct dependency, confirm its version, build the project, and scan the resulting dependency list.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Continue in&nbsp;<code>sca-lab<\/code>. We will insert&nbsp;<code>org.apache.httpcomponents:httpclient:4.5.13<\/code>&nbsp;as a direct Maven dependency.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The point is not that HttpClient 4.5.13 is the &#8220;recommended&#8221; version. It is used here to make dependency-tree behavior easy to observe. Later labs teach updates.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Insert HttpClient into the\u00a0<code>dependencies<\/code>\u00a0block.<\/li>\n\n\n\n<li>Build the project.<\/li>\n\n\n\n<li>List dependencies.<\/li>\n\n\n\n<li>Copy runtime dependencies into\u00a0<code>target\/dependency<\/code>\u00a0so the CLI can scan a concrete directory.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A direct dependency is one explicitly requested by the application. Maven will also resolve any dependencies required by that component.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>python3 - &lt;&lt;'PY2'\nfrom pathlib import Path\np = Path('pom.xml')\ns = p.read_text()\nneedle = '  &lt;\/dependencies&gt;'\nblock = \"\"\"    &lt;dependency&gt;\n      &lt;groupId&gt;org.apache.httpcomponents&lt;\/groupId&gt;\n      &lt;artifactId&gt;httpclient&lt;\/artifactId&gt;\n      &lt;version&gt;4.5.13&lt;\/version&gt;\n    &lt;\/dependency&gt;\n\"\"\"\nif 'httpclient&lt;\/artifactId&gt;' not in s:\n    s = s.replace(needle, block + needle)\np.write_text(s)\nPY2\n\nmvn -B clean package\nmvn -B dependency:list\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\nls -1 target\/dependency | head -30\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] BUILD SUCCESS\n...\nhttpclient-4.5.13.jar\nhttpcore-....jar\ncommons-codec-....jar\ncommons-logging-....jar\nlog4j-api-2.14.1.jar\nlog4j-core-2.14.1.jar\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm that&nbsp;<code>httpclient-4.5.13.jar<\/code>&nbsp;appears and that additional JARs appeared even though you did not explicitly add them. Those additional JARs set up the next lab on transitive dependencies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Add one harmless library of your choice, run&nbsp;<code>mvn dependency:list<\/code>, then remove the dependency and prove it disappears after&nbsp;<code>mvn clean package<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The project builds, the new dependency is visible with its exact version, and you can distinguish the explicit POM entry from files Maven resolved on its behalf.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A single dependency declaration can pull in multiple components.<\/li>\n\n\n\n<li>SCA scope is larger than the lines manually added to a manifest.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">3. Direct vs Transitive Dependencies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A direct dependency appears explicitly in your project manifest. A transitive dependency is required by another dependency and is brought in automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Application\n  -&gt; httpclient (direct)\n       -&gt; httpcore (transitive)\n       -&gt; commons-logging (transitive)\n       -&gt; commons-codec (transitive)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A vulnerability may exist in a library your team never typed into&nbsp;<code>pom.xml<\/code>. SCA must therefore inspect the resolved dependency graph, not only direct declarations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use Maven&#8217;s dependency tree to prove which components are direct and which are transitive.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The shared project must contain both&nbsp;<code>log4j-core<\/code>&nbsp;and&nbsp;<code>httpclient<\/code>&nbsp;direct dependencies from Topics 1-2.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ask students to predict the tree before running the command. This quickly exposes the common misconception that &#8220;if it is not in my POM, it is not my dependency.&#8221;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Print the dependency tree.<\/li>\n\n\n\n<li>Filter the HttpClient branch.<\/li>\n\n\n\n<li>Compare indentation depth.<\/li>\n\n\n\n<li>Compare the tree with direct declarations in\u00a0<code>pom.xml<\/code>.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Maven tree indentation encodes dependency relationships. The first level under the project is direct; deeper levels are transitive unless separately declared.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn -B dependency:tree\nmvn -B dependency:tree -Dincludes=org.apache.httpcomponents:httpclient,org.apache.httpcomponents:httpcore,commons-logging:commons-logging,commons-codec:commons-codec\ngrep -n '&lt;dependency&gt;' pom.xml\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>com.example:sca-lab:jar:1.0.0\n+- org.apache.logging.log4j:log4j-core:jar:2.14.1:compile\n|  \\- org.apache.logging.log4j:log4j-api:jar:2.14.1:compile\n\\- org.apache.httpcomponents:httpclient:jar:4.5.13:compile\n   +- org.apache.httpcomponents:httpcore:jar:...:compile\n   +- commons-logging:commons-logging:jar:...:compile\n   \\- commons-codec:commons-codec:jar:...:compile\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Your exact transitive versions may differ if upstream metadata changes, but the hierarchy should show HttpClient below the application and several dependencies below HttpClient.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Choose one transitive dependency and find which direct dependency introduced it. Then write the path in&nbsp;<code>Application -&gt; Direct -&gt; Transitive<\/code>&nbsp;form.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can produce a dependency path for at least one transitive component and explain why removing the parent dependency would affect the child.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Transitive dependencies are part of your risk surface.<\/li>\n\n\n\n<li>Dependency paths matter when deciding how to remediate a finding.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">4. Dependency Trees<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A dependency tree is the resolved graph produced by a package\/build tool. It shows hierarchy, versions, scopes, and often conflict resolution.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When Dependency-Check flags a component, the dependency tree answers an operational question: &#8220;How did this component get into our build?&#8221;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Generate full and filtered trees, save them as evidence, and map a Dependency-Check finding back to its dependency path.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create&nbsp;<code>evidence\/<\/code>&nbsp;in the shared project. Topic 6 will generate the first Dependency-Check report; for now save the tree so it can be compared later.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Keep tree output as evidence before remediation. It becomes extremely useful when demonstrating that an upgrade or exclusion removed a vulnerable transitive dependency.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate a complete dependency tree and save it.<\/li>\n\n\n\n<li>Produce a verbose tree to expose omitted\/conflict-resolved versions where Maven reports them.<\/li>\n\n\n\n<li>Search for Log4j and HttpClient.<\/li>\n\n\n\n<li>After Topic 6, return and map report dependencies to the paths recorded here.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The tree is build-tool truth about resolution. Dependency-Check report identity is scanner truth about what it analyzed. Comparing both helps detect missing coverage or unexpected components.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\nmvn dependency:tree | tee evidence\/dependency-tree-before.txt\nmvn dependency:tree -Dverbose | tee evidence\/dependency-tree-verbose-before.txt\ngrep -E 'log4j|httpclient|httpcore|commons-codec|commons-logging' evidence\/dependency-tree-before.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] com.example:sca-lab:jar:1.0.0\n&#91;INFO] +- org.apache.logging.log4j:log4j-core:jar:2.14.1:compile\n&#91;INFO] |  \\- org.apache.logging.log4j:log4j-api:jar:2.14.1:compile\n&#91;INFO] \\- org.apache.httpcomponents:httpclient:jar:4.5.13:compile\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm the saved file is non-empty, records exact versions, and distinguishes direct from transitive indentation. Later, the same file becomes part of the before\/after comparison.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Select any component from&nbsp;<code>target\/dependency<\/code>, find it in the tree, and record its complete path from the application root.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For a component selected from disk, you can show exactly which direct dependency or application declaration caused it to be present.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Trees explain dependency introduction paths.<\/li>\n\n\n\n<li>Save before\/after trees as remediation evidence.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">5. Dependency Management<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency management means controlling which packages and versions enter a build. Activities include adding, removing, updating, centralizing versions, resolving conflicts, and keeping repeatable manifests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Maven does not provide a universal native lockfile equivalent to&nbsp;<code>package-lock.json<\/code>. Teams commonly pin explicit versions, use&nbsp;<code>dependencyManagement<\/code>, BOMs, repository controls, and reproducible build practices.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Uncontrolled version drift makes findings difficult to reproduce and remediation difficult to prove.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Centralize selected versions in Maven properties, demonstrate an update, demonstrate removal, and verify resolution each time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Continue with&nbsp;<code>sca-lab<\/code>. Make a backup before changing the POM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Avoid saying &#8220;latest is always safest.&#8221; Updating is a change that must be tested. Security remediation should use a vetted fixed version compatible with the application.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Back up the manifest.<\/li>\n\n\n\n<li>Move HttpClient&#8217;s version into a property.<\/li>\n\n\n\n<li>Display available dependency updates using the current Versions Maven Plugin.<\/li>\n\n\n\n<li>Temporarily remove HttpClient and prove its branch disappears.<\/li>\n\n\n\n<li>Restore the POM for later labs.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Version properties centralize decisions.&nbsp;<code>display-dependency-updates<\/code>&nbsp;reports newer releases but does not prove compatibility, maintenance quality, or security by itself.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>cp pom.xml evidence\/pom-topic5-before.xml\n\nmvn org.codehaus.mojo:versions-maven-plugin:2.22.0:display-dependency-updates\n\ncp pom.xml \/tmp\/sca-lab-pom.xml\npython3 - &lt;&lt;'PY2'\nfrom pathlib import Path\np=Path('pom.xml')\ns=p.read_text()\nstart=s.index('    &lt;dependency&gt;\n      &lt;groupId&gt;org.apache.httpcomponents&lt;\/groupId&gt;')\nend=s.index('    &lt;\/dependency&gt;', start)+len('    &lt;\/dependency&gt;\n')\np.write_text(s&#91;:start]+s&#91;end:])\nPY2\nmvn -B dependency:tree | tee evidence\/tree-without-httpclient.txt\ncp \/tmp\/sca-lab-pom.xml pom.xml\nmvn -B dependency:tree | tee evidence\/tree-restored.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] The following dependencies in Dependencies have newer versions:\n...\n&#91;INFO] BUILD SUCCESS\n\n# When removed, the httpclient branch is absent.\n# After restore, it is present again.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Look for the difference between &#8220;update available&#8221; and &#8220;update approved.&#8221; Also verify that removing a direct dependency removes its transitive branch unless another dependency still requires those components.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Pick one dependency, identify an available update, record the current and candidate versions, and list one compatibility test you would run before accepting it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can add\/remove\/update a dependency deliberately, confirm the resulting tree, and explain why dependency management is more than blindly selecting the newest version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Pin and review dependency versions deliberately.<\/li>\n\n\n\n<li>Build-tool resolution evidence should accompany dependency changes.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 2 &#8211; VULNERABILITY FUNDAMENTALS<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">6. Vulnerable Dependencies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A vulnerable dependency is a component\/version associated with one or more publicly disclosed vulnerabilities. Dependency-Check attempts to identify the component (often using evidence mapped to CPEs) and then associates known vulnerabilities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The practical SCA job is not merely &#8220;a CVE exists.&#8221; You need the affected component, version, severity, evidence, dependency path, and an actionable remediation path.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run the first real Dependency-Check scan against the Maven project and generate all supported report formats. Then locate Log4j 2.14.1 and its vulnerabilities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create&nbsp;<code>reports\/before<\/code>. If you have an NVD API key, keep it in&nbsp;<code>NVD_API_KEY<\/code>. The command intentionally sets&nbsp;<code>failBuildOnCVSS=11<\/code>&nbsp;so discovery succeeds even with critical findings; CVSS maximum is 10.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The first data population can be much slower than later runs. For classroom scale this is acceptable; for CI\/enterprise use, teach the NVD-mirror pattern in Module 7.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Run Dependency-Check 13.0.0 through the Maven plugin.<\/li>\n\n\n\n<li>Open the HTML report.<\/li>\n\n\n\n<li>Find\u00a0<code>log4j-core-2.14.1<\/code>.<\/li>\n\n\n\n<li>Record at least one CVE, its severity\/CVSS, CPE\/GAV evidence, and references.<\/li>\n\n\n\n<li>Save the report as baseline evidence.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check does not patch anything. Its job here is detection and reporting. Remediation is a deliberate dependency update followed by a re-scan.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p reports\/before\n\nmvn -B org.owasp:dependency-check-maven:13.0.0:check   -Dformat=ALL   -Dodc.outputDirectory=reports\/before   -DfailBuildOnCVSS=11   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n\nfind reports\/before -maxdepth 1 -type f -print | sort\njq '&#91;.dependencies&#91;].vulnerabilities&#91;]?] | length' reports\/before\/dependency-check-report.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] Analysis Started\n...\n&#91;INFO] Analysis Complete\n&#91;INFO] BUILD SUCCESS\n\nreports\/before\/dependency-check-report.html\nreports\/before\/dependency-check-report.json\nreports\/before\/dependency-check-report.xml\nreports\/before\/dependency-check-report.csv\nreports\/before\/dependency-check-report.sarif\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Open the HTML report and verify the scanner analyzed the expected Maven dependencies. For Log4j Core 2.14.1, current vulnerability data should include the well-known Log4Shell family, including CVE-2021-44228. Do not treat the total finding count as a constant; NVD records and analyzer logic can change.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Choose one vulnerable component and create a four-column note: component\/version, CVE, CVSS\/severity, candidate remediation. Do not yet apply the change.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You have a real generated Dependency-Check baseline report and can trace at least one finding to a concrete dependency\/version and remediation candidate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Scanner findings must map to real component versions.<\/li>\n\n\n\n<li>Baseline reports are evidence; preserve them before remediation.<\/li>\n\n\n\n<li>Counts are data-driven, not values to pre-fill in a training manual.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">7. CVE<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CVE is a public identifier for a specific disclosed vulnerability, such as&nbsp;<code>CVE-2021-44228<\/code>. The CVE identifier is a stable handle; richer analysis comes from records and references maintained by sources such as NVD and the CNA\/vendor.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CVE IDs let developers, scanners, advisories, ticketing systems, and external intelligence refer to the same vulnerability.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Extract a CVE from the Dependency-Check JSON report, then verify the same CVE using NVD&#8217;s API 2.0 and authoritative references.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Topic 6 must have generated&nbsp;<code>reports\/before\/dependency-check-report.json<\/code>.&nbsp;<code>curl<\/code>&nbsp;and&nbsp;<code>jq<\/code>&nbsp;are required.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Use Log4Shell because it is real, well documented, and expected for the intentionally vulnerable Log4j version. Do not demonstrate exploitation.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Search the report for\u00a0<code>CVE-2021-44228<\/code>.<\/li>\n\n\n\n<li>Query NVD API 2.0 by CVE ID.<\/li>\n\n\n\n<li>Inspect descriptions, metrics, weaknesses, configurations\/affected products, and references.<\/li>\n\n\n\n<li>Compare scanner data with NVD data rather than assuming the report is the sole authority.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check consumes vulnerability data and produces a useful local association. NVD remains an authoritative vulnerability enrichment source, while upstream vendor advisories are important for exact fix guidance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -n 'CVE-2021-44228' reports\/before\/dependency-check-report.json | head\n\ncurl -s 'https:\/\/services.nvd.nist.gov\/rest\/json\/cves\/2.0?cveId=CVE-2021-44228'   | jq '.vulnerabilities&#91;0].cve | {id, published, lastModified, descriptions, metrics, weaknesses, references}'   &gt; evidence\/CVE-2021-44228-nvd.json\n\njq '.id, .published, .lastModified' evidence\/CVE-2021-44228-nvd.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"CVE-2021-44228\"\n\"2021-12-10T...\"\n\"...\"\n\n# The full saved object contains descriptions, metrics, weaknesses and references.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the CVE ID matches in both places. Review NVD references and affected-product data; do not infer a fixed version from CVSS alone.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Repeat the process for a second CVE in your generated report. Record one NVD reference and one upstream\/vendor reference where available.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Two scanner CVEs have been independently verified against current authoritative data, with references recorded.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CVE is an identifier, not a risk score.<\/li>\n\n\n\n<li>Verify important findings against authoritative records and vendor guidance.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">8. CWE<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CWE (Common Weakness Enumeration) describes classes of software weaknesses. A CVE is a specific vulnerability instance; a CWE is a category describing the underlying weakness pattern.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CWE helps teams group recurring defect patterns and connect dependency findings to broader secure-development learning.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Locate CWE information associated with CVE-2021-44228 in NVD\/Dependency-Check data and compare CVE vs CWE.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the saved NVD object from Topic 7 and the Dependency-Check JSON baseline.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A vulnerability can have more than one weakness mapping, and mappings can change as records are enriched. Teach students to read the current data rather than memorizing one number.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Extract the NVD weakness array.<\/li>\n\n\n\n<li>Search the Dependency-Check report around the CVE for\u00a0<code>cwes<\/code>.<\/li>\n\n\n\n<li>Write a one-line distinction between the specific CVE and the weakness class(es).<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The CVE answers &#8220;which disclosed vulnerability?&#8221; CWE answers &#8220;what kind of weakness?&#8221; They are related but not interchangeable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>jq '.weaknesses' evidence\/CVE-2021-44228-nvd.json\njq '.. | objects | select(.name? == \"CVE-2021-44228\") | {name,cwes}'   reports\/before\/dependency-check-report.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;\n  {\n    \"source\": \"...\",\n    \"type\": \"...\",\n    \"description\": &#91;\n      {\"lang\":\"en\",\"value\":\"CWE-...\"}\n    ]\n  }\n]\n\n# Dependency-Check may expose a cwes array for the vulnerability.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Look for one or more CWE identifiers. Current NVD data for Log4Shell has accumulated multiple weakness mappings over time; treat the record as data, not a single timeless textbook label.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Pick another CVE from the report, record its CWE mapping if available, and explain in one sentence why two CVEs may share a CWE.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can distinguish a vulnerability instance from a weakness category and retrieve current mappings rather than guessing them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CVE = specific disclosed vulnerability.<\/li>\n\n\n\n<li>CWE = weakness category\/classification.<\/li>\n\n\n\n<li>Mappings can be multiple and evolve.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">9. CVSS<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CVSS expresses technical severity using a score and vector. It is not a complete business-risk decision. This lab focuses on reading the score, severity, and vector &#8211; not manually calculating CVSS.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A security gate often starts from CVSS, but prioritization should later add exploitation evidence, reachability\/usage, exposure, and business context.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Extract CVSS data for two findings and compare their base scores\/vectors.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use&nbsp;<code>reports\/before\/dependency-check-report.json<\/code>&nbsp;and NVD API data. Log4Shell currently has an NVD CVSS v3.1 base score of 10.0 with vector&nbsp;<code>CVSS:3.1\/AV:N\/AC:L\/PR:N\/UI:N\/S:C\/C:H\/I:H\/A:H<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Students should read vector dimensions at a high level. Do not turn this into a CVSS calculator exercise.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Extract\u00a0<code>severity<\/code>,\u00a0<code>cvssv3<\/code>, and\u00a0<code>cvssv4<\/code>\u00a0fields when present.<\/li>\n\n\n\n<li>Select two findings with different scores.<\/li>\n\n\n\n<li>Compare attack vector, privileges required, user interaction, and impacts.<\/li>\n\n\n\n<li>Record which is technically more severe without claiming it must be fixed first in every business context.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">CVSS helps normalize technical severity. It does not tell you whether vulnerable code is reachable or whether the asset is internet-exposed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>jq '&#91;.dependencies&#91;].vulnerabilities&#91;]? | {name,severity,cvssv3,cvssv4}]'   reports\/before\/dependency-check-report.json   &gt; evidence\/cvss-findings.json\n\njq '.&#91;] | select(.name==\"CVE-2021-44228\")' evidence\/cvss-findings.json\njq '&#91;.&#91;] | select(.cvssv3.baseScore? != null)] | sort_by(.cvssv3.baseScore) | &#91;.&#91;0], .&#91;-1]]'   evidence\/cvss-findings.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"name\": \"CVE-2021-44228\",\n  \"severity\": \"CRITICAL\",\n  \"cvssv3\": {\n    \"baseScore\": 10.0,\n    \"attackVector\": \"NETWORK\",\n    \"attackComplexity\": \"LOW\",\n    \"privilegesRequired\": \"NONE\",\n    \"userInteraction\": \"NONE\",\n    \"...\": \"...\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Note that the report&nbsp;<code>severity<\/code>&nbsp;and&nbsp;<code>cvssv3.baseSeverity<\/code>&nbsp;fields may differ in source semantics for some records. Use the source and vector shown in the report\/NVD, not just a color badge.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Pick two current findings and write a two-row comparison with CVE, CVSS version, base score, vector, and severity. Do not add your own composite score.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can read and compare CVSS values and explain why CVSS is an input to prioritization rather than the entire prioritization decision.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CVSS measures technical severity, not complete organizational risk.<\/li>\n\n\n\n<li>Preserve the vector\/source when documenting a score.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">10. CPE<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CPE (Common Platform Enumeration) is a standardized naming scheme used to identify products\/platforms. Dependency-Check analyzes evidence from a dependency and tries to identify one or more matching CPEs before associating NVD vulnerabilities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Incorrect product identification can produce false positives or false negatives. OWASP explicitly recommends checking whether the identified CPE is correct when reviewing reports.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inspect the CPE and evidence shown for Log4j, then trace the relationship&nbsp;<code>dependency -&gt; CPE -&gt; vulnerability<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the HTML and JSON reports from Topic 6.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Emphasize CPE confidence\/evidence. A CVE match is only as useful as the component identification behind it.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the HTML report and expand\u00a0<code>log4j-core<\/code>.<\/li>\n\n\n\n<li>Locate the CPE\/evidence section.<\/li>\n\n\n\n<li>Extract CPEs from JSON.<\/li>\n\n\n\n<li>Compare the product identity in the CPE with the Maven GAV.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Package coordinates (GAV\/PURL) and CPE are different identity systems. Dependency-Check uses collected evidence to bridge package identity to vulnerability applicability data.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>jq '.dependencies&#91;]   | select(.fileName | test(\"log4j-core\"))   | {fileName,packages,vulnerabilityIds,vulnerabilities}'   reports\/before\/dependency-check-report.json &gt; evidence\/log4j-dependency.json\n\njq '.. | .cpe? \/\/ empty' evidence\/log4j-dependency.json | head -30\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"cpe:2.3:a:apache:log4j:2.14.1:...\"\n...\n\n# Exact representation can vary by report schema and analyzer evidence.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The CPE vendor\/product\/version should logically correspond to the dependency you intended to scan. If it names an unrelated product, treat that as a likely identification problem requiring review\/suppression or hints rather than blindly accepting the CVE.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Select a second dependency. Verify whether Dependency-Check assigned a CPE and whether that CPE appears semantically correct.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can explain and inspect the chain: concrete dependency evidence -&gt; product identity\/CPE -&gt; matched vulnerabilities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Validate component identity before trusting a vulnerability association.<\/li>\n\n\n\n<li>CPE is one important bridge between dependency evidence and NVD applicability.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">11. NVD<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The U.S. National Vulnerability Database enriches CVE records with metadata such as CVSS, weakness information, references, and CPE-based applicability. Current Dependency-Check uses NVD API 2.0 for direct API updates and maintains a local vulnerability database\/cache.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Scanner quality depends on current vulnerability data. CI reliability also depends on how that data is updated and cached.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inspect Dependency-Check&#8217;s update behavior, query NVD API 2.0 directly, and practice the update-only\/purge workflow.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An NVD API key is recommended for direct API use. Do not expose it in logs. The lab uses&nbsp;<code>nvdApiKeyEnvironmentVariable<\/code>&nbsp;for Maven.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For a single classroom workstation, direct updates are fine. For operational CI, use an NVD mirror\/cache and update it separately from application builds.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Run Dependency-Check\u00a0<code>update-only<\/code>.<\/li>\n\n\n\n<li>Observe data-source timestamps in the report JSON.<\/li>\n\n\n\n<li>Query the NVD 2.0 endpoint directly for a known CVE.<\/li>\n\n\n\n<li>Learn\u00a0<code>purge<\/code>\u00a0only as a troubleshooting\/reset action, not something to run on every build.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check stores data locally so every scan does not download the full NVD corpus. Current configuration also updates other sources such as KEV and hosted suppressions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn -B org.owasp:dependency-check-maven:13.0.0:update-only   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n\njq '.scanInfo.dataSource' reports\/before\/dependency-check-report.json\n\ncurl -s 'https:\/\/services.nvd.nist.gov\/rest\/json\/cves\/2.0?cveId=CVE-2021-44228'   | jq '.totalResults, .vulnerabilities&#91;0].cve.id'\n\n<em># Troubleshooting\/reset only - do not make this a normal CI step:<\/em>\n<em># mvn org.owasp:dependency-check-maven:13.0.0:purge<\/em>\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] Checking for updates\n&#91;INFO] ...\n1\n\"CVE-2021-44228\"\n\n# Data-source timestamps are visible in the generated report metadata.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the report records when vulnerability data was checked\/updated. A successful scan against stale cached data is not equivalent to a current scan; monitor update health in CI.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Document how your organization would separate &#8220;vulnerability data refresh&#8221; from &#8220;application scan&#8221; so NVD availability is not a single-build bottleneck.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can query NVD API 2.0 directly, explain Dependency-Check&#8217;s local update\/cache role, and describe why a mirror\/cache is recommended for operational CI.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Current Dependency-Check integrates with NVD API 2.0.<\/li>\n\n\n\n<li>Data freshness and update reliability are part of SCA operations.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">12. EPSS<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">EPSS (Exploit Prediction Scoring System) estimates the probability that a published CVE will be exploited in the wild during the next 30 days. It complements CVSS rather than replacing it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Dependency-Check does not directly provide current EPSS as a primary report signal.<\/strong>&nbsp;In this lab we enrich a Dependency-Check CVE using FIRST&#8217;s authoritative EPSS API.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A high-severity vulnerability with very low exploitation likelihood can deserve different operational treatment than a heavily exploited issue, depending on exposure and business context.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Take a CVE detected by Dependency-Check, fetch its current EPSS probability and percentile from FIRST, then review it beside CVSS and dependency context.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Requires&nbsp;<code>curl<\/code>,&nbsp;<code>jq<\/code>, and at least one CVE from Topic 6.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">EPSS changes over time. Never hardcode an EPSS value in the lab answer key. Fetch it when the student performs the exercise.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Query FIRST for CVE-2021-44228.<\/li>\n\n\n\n<li>Save the response with the lab evidence.<\/li>\n\n\n\n<li>Record CVSS and EPSS side by side.<\/li>\n\n\n\n<li>Add only contextual facts: direct\/transitive, runtime use, environment exposure. Do not invent a combined score.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">CVSS and EPSS answer different questions. CVSS expresses technical severity; EPSS predicts near-term exploitation probability based on the EPSS model. Context determines action.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -s 'https:\/\/api.first.org\/data\/v1\/epss?cve=CVE-2021-44228'   | tee evidence\/CVE-2021-44228-epss.json   | jq '.data&#91;0]'\n\njq -r '.data&#91;0] | \"CVE=\\(.cve) EPSS=\\(.epss) percentile=\\(.percentile)\"'   evidence\/CVE-2021-44228-epss.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"cve\": \"CVE-2021-44228\",\n  \"epss\": \"&lt;current probability returned by FIRST&gt;\",\n  \"percentile\": \"&lt;current percentile returned by FIRST&gt;\",\n  \"date\": \"&lt;current model date&gt;\"\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm the response date\/model data is current at execution time. Treat&nbsp;<code>epss<\/code>&nbsp;as a probability value and&nbsp;<code>percentile<\/code>&nbsp;as relative position in the scored CVE population.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Query EPSS for two CVEs from your report and compare: CVSS, EPSS, direct\/transitive status, and runtime context. State which one you would investigate first and why, without creating a proprietary score.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Your prioritization note clearly distinguishes CVSS, EPSS, and application context and cites live FIRST data.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>EPSS is dynamic; fetch it at decision time.<\/li>\n\n\n\n<li>Combine signals conceptually, not by inventing an unsupported formula.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">13. Known Exploited Vulnerabilities (KEV)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CISA&#8217;s Known Exploited Vulnerabilities catalog contains vulnerabilities for which there is evidence of exploitation in the wild. Current Dependency-Check includes a KEV update\/analyzer and uses CISA&#8217;s JSON feed by default.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">KEV status is a strong prioritization signal because it represents observed exploitation, but it still does not eliminate the need to check whether the affected component and vulnerable condition are actually present in your environment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Verify whether a Dependency-Check CVE is in CISA KEV using both the scanner context and the authoritative CISA JSON catalog.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use CVE-2021-44228 as the primary demonstration. It is in CISA KEV. The CISA feed URL is also the default current Dependency-Check KEV URL.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not create a homegrown numeric risk score. The exercise is a signal comparison, not a scoring formula.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Query the CISA KEV JSON feed for CVE-2021-44228.<\/li>\n\n\n\n<li>Save the matching entry.<\/li>\n\n\n\n<li>Inspect Dependency-Check report details for KEV context where shown.<\/li>\n\n\n\n<li>Compare two hypothetical decision rows: High CVSS\/not KEV vs lower CVSS\/KEV. Do not declare a universal winner; explain why KEV changes urgency.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">KEV is evidence of real-world exploitation. A moderate\/lower technical severity can still become operationally urgent when exploitation is confirmed and the organization is exposed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -sL 'https:\/\/www.cisa.gov\/sites\/default\/files\/feeds\/known_exploited_vulnerabilities.json'   | jq '.vulnerabilities&#91;] | select(.cveID==\"CVE-2021-44228\")'   | tee evidence\/CVE-2021-44228-kev.json\n\njq '{cveID,vendorProject,product,vulnerabilityName,dateAdded,dueDate,knownRansomwareCampaignUse}'   evidence\/CVE-2021-44228-kev.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability data changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"cveID\": \"CVE-2021-44228\",\n  \"vendorProject\": \"Apache\",\n  \"product\": \"Log4j2\",\n  \"vulnerabilityName\": \"...\",\n  \"dateAdded\": \"...\",\n  \"dueDate\": \"...\",\n  \"knownRansomwareCampaignUse\": \"...\"\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A non-empty object proves KEV membership at execution time. If you query another CVE and&nbsp;<code>jq<\/code>&nbsp;emits nothing, verify spelling and current catalog status before concluding it is not in KEV.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Choose one CVE from your report that is not in KEV and compare it to the KEV finding using a table with: CVSS, KEV yes\/no, EPSS, dependency path, runtime usage, exposure. Do not calculate a composite score.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can independently verify KEV membership and explain why observed exploitation materially changes prioritization without pretending KEV alone decides business risk.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>KEV is an observed-exploitation signal.<\/li>\n\n\n\n<li>Dependency-Check now consumes KEV data, but authoritative CISA verification remains useful.<\/li>\n\n\n\n<li>Prioritization stays contextual.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 3 &#8211; SBOM<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">14. Software Bill of Materials (SBOM)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An SBOM is a machine-readable inventory of software components and related metadata. It lets teams answer &#8220;what components are in this artifact\/application?&#8221; independently of a one-time vulnerability scan.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Dependency-Check does not directly replace a general-purpose SBOM generator.<\/strong>&nbsp;For SBOM creation this lab uses Syft; Dependency-Check remains the central vulnerability scanner.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An SBOM allows teams to re-evaluate existing software when new vulnerabilities appear, even if the application was built weeks or months ago. It also supports supplier transparency and compliance workflows.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Generate an SBOM from the resolved JAR directory, inspect component names\/versions\/PURLs\/licenses, then connect the inventory back to Dependency-Check findings.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">From&nbsp;<code>sca-lab<\/code>, refresh&nbsp;<code>target\/dependency<\/code>&nbsp;and ensure Syft is installed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not imply that generating an SBOM proves an application is secure. An SBOM is inventory\/evidence; vulnerability interpretation is a separate process.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Copy resolved Maven dependencies into a concrete directory.<\/li>\n\n\n\n<li>Generate a Syft native JSON inventory plus CycloneDX and SPDX SBOMs.<\/li>\n\n\n\n<li>Count components.<\/li>\n\n\n\n<li>Find Log4j in the SBOM.<\/li>\n\n\n\n<li>Match its version\/PURL to the Dependency-Check report.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The same component can be represented by Maven GAV, PURL, CPE, CycloneDX component objects, or SPDX package objects. A mature program maintains the ability to reconcile these identities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p reports\/sbom\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\n\nsyft scan dir:target\/dependency   -o syft-json=reports\/sbom\/sbom.syft.json   -o cyclonedx-json=reports\/sbom\/sbom.cdx.json   -o spdx-json=reports\/sbom\/sbom.spdx.json\n\njq '.artifacts | length' reports\/sbom\/sbom.syft.json\njq '.components&#91;] | select(.name | test(\"log4j\"; \"i\")) | {name,version,purl,licenses}'   reports\/sbom\/sbom.cdx.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;component count&gt;\n{\n  \"name\": \"log4j-core\",\n  \"version\": \"2.14.1\",\n  \"purl\": \"pkg:maven\/org.apache.logging.log4j\/log4j-core@2.14.1\",\n  \"licenses\": &#91; ... ]\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm the vulnerable version is present in both the SBOM and Dependency-Check baseline. If a component is present in one inventory and unexpectedly absent in the other, investigate scan scope\/analyzer coverage.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Select three SBOM components and map each to the dependency tree. Mark each as direct or transitive.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You have machine-readable SBOM artifacts and can reconcile at least three components with the Maven dependency graph.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SBOM = reusable component inventory.<\/li>\n\n\n\n<li>SCA findings become more operationally useful when tied to stable component identities such as PURLs.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">15. CycloneDX<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CycloneDX is a BOM standard designed for software supply-chain use cases. Current CycloneDX 1.7 supports rich component, dependency, vulnerability, service, and VEX-related data structures.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CycloneDX is widely consumed by vulnerability-management and supply-chain tools, making it a practical interchange format for SBOM workflows.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Generate CycloneDX JSON, inspect specification metadata and component objects, and validate that dependency versions are represented.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Syft must be installed and&nbsp;<code>target\/dependency<\/code>&nbsp;must contain resolved JARs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The exact CycloneDX spec version emitted by Syft can be controlled by its output capabilities. Inspect&nbsp;<code>specVersion<\/code>&nbsp;rather than assuming it.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate CycloneDX JSON.<\/li>\n\n\n\n<li>Inspect\u00a0<code>bomFormat<\/code>,\u00a0<code>specVersion<\/code>, and component count.<\/li>\n\n\n\n<li>Extract name\/version\/PURL\/license fields.<\/li>\n\n\n\n<li>Save a compact component inventory for review.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">CycloneDX uses component objects and Package URLs to make dependencies portable across tools. The BOM itself is not a vulnerability verdict.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>syft scan dir:target\/dependency -o cyclonedx-json=reports\/sbom\/sbom.cdx.json\n\njq '{bomFormat,specVersion,serialNumber,version,componentCount:(.components|length)}'   reports\/sbom\/sbom.cdx.json\n\njq -r '.components&#91;] | &#91;.name,.version,(.purl \/\/ \"\"),((.licenses \/\/ &#91;])|tostring)] | @tsv'   reports\/sbom\/sbom.cdx.json   &gt; evidence\/cyclonedx-components.tsv\n\nhead -20 evidence\/cyclonedx-components.tsv\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"bomFormat\": \"CycloneDX\",\n  \"specVersion\": \"&lt;version emitted by Syft&gt;\",\n  \"serialNumber\": \"urn:uuid:...\",\n  \"version\": 1,\n  \"componentCount\": &lt;number&gt;\n}\nlog4j-core    2.14.1    pkg:maven\/...\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Verify&nbsp;<code>bomFormat<\/code>&nbsp;is CycloneDX and the application dependencies are represented with versions. Record the actual&nbsp;<code>specVersion<\/code>&nbsp;produced on your machine.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Find&nbsp;<code>log4j-core<\/code>,&nbsp;<code>httpclient<\/code>, and one transitive dependency in the CycloneDX file and record their PURLs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can generate and read a CycloneDX SBOM and identify component identity\/version information without a graphical UI.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CycloneDX is a portable supply-chain inventory format.<\/li>\n\n\n\n<li>Inspect the generated spec version and component identities rather than assuming them.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">16. SPDX<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">SPDX is a standard for exchanging software\/package, licensing, provenance, security, and other supply-chain metadata. The current SPDX specification is 3.0.1, while tools may emit supported earlier serializations such as SPDX 2.3 JSON depending on their implementation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Different customers and ecosystems request different SBOM standards. Teams should be able to produce and consume the format their downstream process requires.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Generate an SPDX JSON SBOM with Syft, inspect its package structures, and compare its basic organization to CycloneDX.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the same resolved dependency directory so CycloneDX and SPDX represent comparable input.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not claim one format is universally &#8220;better.&#8221; Compare what the generated artifacts actually contain and what your consumer accepts.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate SPDX JSON.<\/li>\n\n\n\n<li>Inspect document\/spec metadata.<\/li>\n\n\n\n<li>Extract packages and versions.<\/li>\n\n\n\n<li>Compare one Log4j record with the CycloneDX record.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">CycloneDX typically exposes a&nbsp;<code>components<\/code>&nbsp;collection. SPDX 2.x-style JSON exposes&nbsp;<code>packages<\/code>&nbsp;and relationships. SPDX 3.x introduces a substantially expanded model; the emitted format depends on tool support.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>syft scan dir:target\/dependency -o spdx-json=reports\/sbom\/sbom.spdx.json\n\njq '{spdxVersion,dataLicense,name,packageCount:(.packages|length)}'   reports\/sbom\/sbom.spdx.json\n\njq '.packages&#91;] | select(.name | test(\"log4j\"; \"i\"))   | {name,versionInfo,licenseConcluded,licenseDeclared,externalRefs}'   reports\/sbom\/sbom.spdx.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"spdxVersion\": \"SPDX-...\",\n  \"dataLicense\": \"...\",\n  \"name\": \"...\",\n  \"packageCount\": &lt;number&gt;\n}\n{\n  \"name\": \"log4j-core\",\n  \"versionInfo\": \"2.14.1\",\n  \"licenseConcluded\": \"...\",\n  \"externalRefs\": &#91; ... ]\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm package identity and version are equivalent to the CycloneDX representation even though field names\/structure differ.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create a two-column note for one package showing the CycloneDX fields and the SPDX fields that express name, version, package identity, and license.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can generate\/read an SPDX SBOM and explain the practical structural difference from the CycloneDX file produced from the same inputs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SBOM standards are interchange formats, not vulnerability scanners.<\/li>\n\n\n\n<li>Choose\/validate formats based on consumer requirements and supported schema versions.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 4 &#8211; LICENSE &amp; COMPLIANCE<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">17. License Compliance<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dependencies carry license obligations in addition to vulnerability risk. Automated tools can inventory declared\/detected license metadata, but legal interpretation and policy decisions require an organizational compliance process.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A component can be vulnerability-free and still be unacceptable under an organization&#8217;s distribution, attribution, copyleft, commercial, or contractual policy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Extract license information from the generated SBOM and compare it with Maven POM metadata for a selected package.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Syft SBOMs from Module 3 must exist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">State clearly: this lab identifies metadata and potential review needs; it is not legal advice and does not make final compatibility determinations.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Inspect license metadata for all Syft artifacts.<\/li>\n\n\n\n<li>Filter the Log4j component.<\/li>\n\n\n\n<li>Inspect the upstream Maven POM license block as a second source.<\/li>\n\n\n\n<li>Record discrepancies\/unknowns instead of silently treating them as permissive.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">License scanners rely on metadata\/files and can be incomplete. Compliance workflows need evidence, policy, and human\/legal review for ambiguous cases.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>jq -r '.artifacts&#91;] | &#91;.name,.version,((.licenses \/\/ &#91;])|tostring)] | @tsv'   reports\/sbom\/sbom.syft.json   | tee evidence\/licenses.tsv\n\ngrep -n -A12 '&lt;licenses&gt;'   \"$HOME\/.m2\/repository\/org\/apache\/logging\/log4j\/log4j-core\/2.14.1\/log4j-core-2.14.1.pom\"\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>log4j-core    2.14.1    &#91;...license metadata...]\nhttpclient      4.5.13    &#91;...license metadata...]\n...\n&lt;licenses&gt;\n  &lt;license&gt;\n    ...\n  &lt;\/license&gt;\n&lt;\/licenses&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Flag unknown, multiple, or ambiguous licenses for review. Do not convert &#8220;no detected license&#8221; into &#8220;public domain&#8221; or &#8220;no obligations.&#8221;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Select five dependencies and classify their detected license status as&nbsp;<code>identified<\/code>,&nbsp;<code>multiple\/complex<\/code>, or&nbsp;<code>unknown\/review required<\/code>. Do not make legal compatibility conclusions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A license inventory exists, and ambiguous metadata is routed to review rather than silently accepted.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>License visibility is part of SCA.<\/li>\n\n\n\n<li>Automated detection is evidence, not final legal advice.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">18. Open-Source License Types<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Common license families include permissive licenses such as MIT, Apache License 2.0 (SPDX: Apache-2.0), and BSD; stronger copyleft licenses such as GPL; library-oriented copyleft such as LGPL; file-level copyleft such as MPL; and public-domain\/equivalent mechanisms such as CC0\/Unlicense depending on jurisdiction\/policy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is a practical identification lab, not a legal course.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Different license types can trigger different notice, source-distribution, modification, linking, patent, and redistribution considerations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inventory the licenses actually present in the lab dependencies, normalize obvious SPDX identifiers where the tool provides them, and flag anything unknown.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use&nbsp;<code>reports\/sbom\/sbom.syft.json<\/code>&nbsp;and&nbsp;<code>reports\/sbom\/sbom.spdx.json<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not tell students that all licenses in the same broad family have identical obligations. The goal is recognition and escalation.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>List unique detected license values.<\/li>\n\n\n\n<li>Compare them with SPDX license expressions where available.<\/li>\n\n\n\n<li>Build a small recognition table for MIT, Apache-2.0, BSD, GPL, LGPL, MPL, and public-domain\/equivalent concepts.<\/li>\n\n\n\n<li>Mark which of those are actually found in this project.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">SPDX identifiers improve machine readability, but a scanner may produce declared text, detected text, SPDX expressions, or unknown values depending on evidence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>jq -r '.artifacts&#91;] | (.licenses \/\/ &#91;])&#91;]? | (.spdxExpression \/\/ .value \/\/ \"UNKNOWN\")'   reports\/sbom\/sbom.syft.json   | sort -u\n\njq -r '.packages&#91;] | &#91;.name,.versionInfo,(.licenseDeclared \/\/ \"NOASSERTION\")] | @tsv'   reports\/sbom\/sbom.spdx.json   | head -30\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Apache-2.0\n...\n\npackage-name    version    Apache-2.0\npackage-name    version    NOASSERTION\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Look for SPDX-style expressions and&nbsp;<code>NOASSERTION<\/code>\/unknown cases. Unknown is a review state, not a license type.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create a seven-row table (MIT, Apache-2.0, BSD, GPL, LGPL, MPL, public-domain\/equivalent) with one-sentence practical characteristics and whether your lab inventory contains an example.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can recognize major license families, retrieve license metadata from real components, and know when to escalate uncertainty.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>License family recognition helps triage compliance review.<\/li>\n\n\n\n<li>Never equate automated detection with legal approval.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">19. License Risk &amp; License Conflicts<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">License risk is the possibility that dependency obligations conflict with project distribution\/business requirements or organizational policy. The workflow is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Dependency -&gt; Detected\/Declared License -&gt; Project Distribution Model -&gt; Policy\/Compatibility Review\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A technical tool can surface evidence; it cannot replace legal\/compliance interpretation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Teams need a repeatable way to stop problematic dependency choices before release, just as they gate severe vulnerabilities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a simple policy-review file, feed the lab license inventory into it, and flag components for review without issuing legal conclusions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create an example project policy that treats unknown licenses and strong-copyleft licenses as&nbsp;<code>REVIEW_REQUIRED<\/code>&nbsp;for this fictional training organization. This is a workflow example, not a legal rule.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Make the distinction explicit: a policy flag is not a statement that a license is &#8220;bad&#8221; or legally incompatible.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate the current license inventory.<\/li>\n\n\n\n<li>Create a training policy list.<\/li>\n\n\n\n<li>Search inventory for terms that trigger review.<\/li>\n\n\n\n<li>Record why a human review is required.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Organizations often express license acceptance rules in dedicated governance tools. Here we model the decision path with a simple file so students understand detection vs policy vs legal decision.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; evidence\/license-review-policy.txt &lt;&lt;'EOF'\nTRAINING POLICY ONLY - NOT LEGAL ADVICE\nREVIEW_REQUIRED_IF: UNKNOWN\nREVIEW_REQUIRED_IF: NOASSERTION\nREVIEW_REQUIRED_IF: GPL\nREVIEW_REQUIRED_IF: AGPL\nREVIEW_REQUIRED_IF: LGPL\nEOF\n\ngrep -Ei 'UNKNOWN|NOASSERTION|GPL|AGPL|LGPL' evidence\/licenses.tsv || true\ncat evidence\/license-review-policy.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>TRAINING POLICY ONLY - NOT LEGAL ADVICE\nREVIEW_REQUIRED_IF: UNKNOWN\n...\n\n# Matching dependencies, if any, are candidates for review; no automatic legal verdict is produced.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm that the policy only creates a review queue. Check the project&#8217;s own license\/distribution context before any compatibility conclusion.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Invent a fictional dependency with a detected GPL-family license in a proprietary distribution scenario. Describe the questions you would send to legal\/compliance rather than deciding compatibility yourself.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can separate three layers: technical license detection, organizational policy flagging, and legal\/compliance decision-making.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>License policy is organizational context, not universal law.<\/li>\n\n\n\n<li>Unknown\/ambiguous license data should be visible and reviewable.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 5 &#8211; DEPENDENCY SECURITY<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">20. Dependency Vulnerability Scanning<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency vulnerability scanning identifies known vulnerabilities associated with software components. This is the core OWASP Dependency-Check lab: scan a concrete directory, scan a Maven project, generate multiple reports, and review remediation candidates.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A mature SCA practice can scan both build metadata and produced\/resolved artifacts. Comparing scopes helps detect blind spots.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run both the Dependency-Check CLI\/Docker directory scan and Maven project scan, then compare their component\/finding coverage.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure&nbsp;<code>target\/dependency<\/code>&nbsp;exists. Choose local CLI or Docker; both use current 13.0.0 syntax. Preserve a persistent data directory for Docker.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The Docker scan of JARs and the Maven plugin scan of the project are intentionally two views. Finding counts may not be identical because analyzers\/evidence differ.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Resolve\/copy dependencies.<\/li>\n\n\n\n<li>Scan the directory with current CLI\/Docker syntax.<\/li>\n\n\n\n<li>Scan the project with the Maven plugin.<\/li>\n\n\n\n<li>Generate HTML + JSON + SARIF.<\/li>\n\n\n\n<li>Review component, vulnerability, CPE, CVSS, KEV, and references.<\/li>\n\n\n\n<li>Identify a candidate remediation version from upstream\/current package data.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Scanning is useful only when it ends in a review\/remediation workflow. A generated report sitting unread is not a security control.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\nmkdir -p odc-reports\/directory\n\ndocker run --rm   --volume \"$(pwd)\/target\/dependency\":\/src:ro   --volume \"$HOME\/OWASP-Dependency-Check\/data\":\/usr\/share\/dependency-check\/data   --volume \"$(pwd)\/odc-reports\/directory\":\/report   owasp\/dependency-check:13.0.0   --project \"SCA Directory Scan\"   --scan \/src   --out \/report   --format HTML   --format JSON   --format SARIF   --prettyPrint   --failOnCVSS 11\n\nmvn -B org.owasp:dependency-check-maven:13.0.0:check   -Dformat=HTML,JSON,SARIF   -Dodc.outputDirectory=reports\/project-scan   -DfailBuildOnCVSS=11   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Directory scan output directory:\ndependency-check-report.html\ndependency-check-report.json\ndependency-check-report.sarif\n\n# Maven scan output directory:\ndependency-check-report.html\ndependency-check-report.json\ndependency-check-report.sarif\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Compare dependency counts and vulnerability counts using&nbsp;<code>jq<\/code>. Investigate differences rather than treating them as scanner errors automatically.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Run both methods on the same lab state. Record: number of dependencies analyzed, number with vulnerabilities, highest observed severity, and one remediation candidate for each scan.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can perform repeatable CLI\/directory and build-tool\/project scans, generate reports, and turn at least one finding into a remediation plan.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Scan scope matters.<\/li>\n\n\n\n<li>Multiple report formats support different consumers.<\/li>\n\n\n\n<li>Findings need ownership and remediation, not just generation.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">21. Dependency Version Management &#8211; Before\/After Remediation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The safest proof that an upgrade addressed a known vulnerable dependency is a controlled before\/after workflow: preserve the baseline, update to a vetted version, rebuild, re-scan, and compare.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Security remediation must be demonstrable. Merely changing a version string is insufficient if the resolved graph still contains a vulnerable version or the build breaks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Upgrade the intentionally vulnerable Log4j 2.14.1 to the current Log4j 2.26.1 release verified for this guide, rebuild, re-run Dependency-Check, and compare findings.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure&nbsp;<code>reports\/before<\/code>&nbsp;exists. Make a Git commit or backup before modification. Apache&#8217;s current Log4j release stream should be re-checked whenever this manual is reused later.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Avoid teaching the historical &#8220;2.17.1 is always the final safe version&#8221; shortcut. New vulnerabilities and fixes have appeared since Log4Shell. Use current vendor guidance and a currently supported release line.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Preserve the before POM and reports.<\/li>\n\n\n\n<li>Replace the Log4j version property.<\/li>\n\n\n\n<li>Build and generate a new tree.<\/li>\n\n\n\n<li>Re-run Dependency-Check into a separate\u00a0<code>reports\/after<\/code>\u00a0directory.<\/li>\n\n\n\n<li>Prove\u00a0<code>2.14.1<\/code>\u00a0is absent from the resolved tree.<\/li>\n\n\n\n<li>Compare the specific CVE and overall counts without assuming they go to zero.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">An upgrade can remove old CVEs and still introduce\/retain other findings. Success means the targeted vulnerable version and targeted vulnerability condition are remediated and the application remains compatible.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>cp pom.xml evidence\/pom-before-remediation.xml\n\npython3 - &lt;&lt;'PY2'\nfrom pathlib import Path\np=Path('pom.xml')\ns=p.read_text()\ns=s.replace('&lt;log4j.version&gt;2.14.1&lt;\/log4j.version&gt;',\n            '&lt;log4j.version&gt;2.26.1&lt;\/log4j.version&gt;')\np.write_text(s)\nPY2\n\nmvn -B clean package\nmvn dependency:tree | tee evidence\/dependency-tree-after.txt\nmkdir -p reports\/after\nmvn -B org.owasp:dependency-check-maven:13.0.0:check   -Dformat=ALL   -Dodc.outputDirectory=reports\/after   -DfailBuildOnCVSS=11   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n\ngrep -n 'log4j.*2.14.1' evidence\/dependency-tree-after.txt || true\ngrep -n 'CVE-2021-44228' reports\/after\/dependency-check-report.json || true\n\nprintf 'before vulnerabilities: '\njq '&#91;.dependencies&#91;].vulnerabilities&#91;]?] | length' reports\/before\/dependency-check-report.json\nprintf 'after vulnerabilities: '\njq '&#91;.dependencies&#91;].vulnerabilities&#91;]?] | length' reports\/after\/dependency-check-report.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] BUILD SUCCESS\n...\n# No resolved Log4j 2.14.1 line should remain.\n# The targeted CVE should no longer be associated with the upgraded Log4j dependency.\nbefore vulnerabilities: &lt;measured value&gt;\nafter vulnerabilities:  &lt;measured value&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not expect the entire report to become empty. Focus first on the targeted component\/version\/CVE, then review any remaining or newly discovered findings.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Choose one additional outdated direct dependency. Use vendor\/repository information plus the Versions Maven Plugin to propose and test an upgrade, then scan again.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The application builds, the targeted old version is absent, the targeted vulnerability is no longer reported for that component, and before\/after evidence is preserved.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Remediation is a verified state transition, not an edit.<\/li>\n\n\n\n<li>Re-scan after every dependency security change.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">22. Outdated &amp; Abandoned Dependencies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An outdated dependency has a newer release. An abandoned\/unmaintained dependency is a broader maintenance-risk judgment based on signals such as release activity, unresolved security issues, maintainer status, archived repositories, or explicit deprecation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vulnerability scanning alone cannot prove that a package is healthy or maintained.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A package can have no known CVEs today yet still be risky because nobody is maintaining it, security fixes are unlikely, or the ecosystem has moved to a replacement.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">List available Maven updates, inspect project\/repository metadata, and create a maintenance-review checklist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the current Maven Versions Plugin 2.22.0. Internet access is required to resolve newer versions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Teach &#8220;outdated&#8221; and &#8220;abandoned&#8221; as separate labels. Newer release availability is machine-detectable; abandonment usually needs contextual evidence.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Display dependency updates.<\/li>\n\n\n\n<li>Save the result.<\/li>\n\n\n\n<li>Inspect upstream project URL\/SCM metadata for one dependency.<\/li>\n\n\n\n<li>Review official release\/repository activity manually.<\/li>\n\n\n\n<li>Mark the dependency\u00a0<code>maintained<\/code>,\u00a0<code>uncertain<\/code>, or\u00a0<code>review required<\/code>\u00a0with evidence.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not automate a conclusion from &#8220;last release date&#8221; alone. Stable libraries may legitimately release infrequently.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn org.codehaus.mojo:versions-maven-plugin:2.22.0:display-dependency-updates   | tee evidence\/dependency-updates.txt\n\ngrep -E 'newer versions|-&gt;|log4j|httpclient' evidence\/dependency-updates.txt || true\n\n<em># Inspect metadata already downloaded by Maven:<\/em>\ngrep -E '&lt;url&gt;|&lt;connection&gt;|&lt;developerConnection&gt;|&lt;tag&gt;'   \"$HOME\/.m2\/repository\/org\/apache\/httpcomponents\/httpclient\/4.5.13\/httpclient-4.5.13.pom\"   | head -30\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] The following dependencies in Dependencies have newer versions:\n&#91;INFO]   group:artifact ........................ old -&gt; new\n...\n\n&lt;url&gt;...&lt;\/url&gt;\n&lt;connection&gt;scm:git:...&lt;\/connection&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Separate findings into: vulnerable, outdated, and maintenance concern. One component can have any combination of those states.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Pick one dependency with an available major-version upgrade. Review its upstream project status and answer: maintained? supported release line? migration cost? security reason to move?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Your maintenance review includes evidence and does not label a component abandoned solely because it is old.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&#8220;No CVE&#8221; does not mean &#8220;low maintenance risk.&#8221;<\/li>\n\n\n\n<li>Update detection and maintainer-health review are complementary practices.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 6 &#8211; SUPPLY CHAIN SECURITY<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">23. Malicious Packages &amp; Supply-Chain Attacks<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">SCA often focuses on known vulnerable packages, but a dependency can also be malicious from the start, become compromised, or receive a malicious update. Dependency-Check is not a malware-detector or complete package-trust system.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A newly published malicious package may have no CVE and therefore evade vulnerability-only workflows.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use a controlled, non-malicious exercise to practice verifying exact package coordinates, repository source, hashes, and unexpected dependency changes. We do not install look-alike or known malicious packages.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the already downloaded Maven artifacts only. No malicious package is downloaded or executed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The exercise should teach defensive verification, not how to publish or weaponize malicious packages.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Record hashes for resolved JARs.<\/li>\n\n\n\n<li>Record exact GAV\/PURL identities.<\/li>\n\n\n\n<li>Change nothing, regenerate the inventory, and compare hashes.<\/li>\n\n\n\n<li>Discuss which supply-chain attack classes a CVE scanner would not necessarily detect.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Hashes prove byte identity at a point in time; repository controls\/signatures\/provenance add stronger source assurance. A matching hash does not prove the software was benign in the first place.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>find target\/dependency -name '*.jar' -type f -print | sort | while IFS= read -r file; do\n  if command -v sha256sum &gt;\/dev\/null 2&gt;&amp;1; then\n    sha256sum \"$file\"\n  else\n    shasum -a 256 \"$file\"\n  fi\ndone | tee evidence\/dependency-sha256.txt\n\nsyft scan dir:target\/dependency -o syft-json=evidence\/supply-chain-inventory.json\njq -r '.artifacts&#91;] | &#91;.name,.version,(.purl \/\/ \"\")] | @tsv'   evidence\/supply-chain-inventory.json   | sort &gt; evidence\/package-identities.tsv\n\nhead evidence\/dependency-sha256.txt\nhead evidence\/package-identities.tsv\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;sha256&gt;  target\/dependency\/package-a.jar\n&lt;sha256&gt;  target\/dependency\/package-b.jar\n...\npackage-a    version    pkg:maven\/...\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Look for unexpected packages, version changes, repository\/source changes, or byte changes between controlled builds. None of those automatically proves maliciousness, but they are investigation triggers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Write three examples of supply-chain compromise that a CVE-based scanner could miss initially: malicious new package, compromised maintainer release, and build-system tampering. For each, name one additional control.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can explain Dependency-Check&#8217;s boundary and produce integrity\/inventory evidence without downloading malware.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Vulnerability scanning is not malware detection.<\/li>\n\n\n\n<li>Exact identity, provenance, repository governance, and integrity controls complement SCA.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">24. Software Supply Chain Security<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Software supply-chain security protects the end-to-end path from developer\/source through dependency resolution, build, artifact creation, distribution, and deployment.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Developer\n  -&gt; Source Code\n  -&gt; Dependencies\n  -&gt; Package Repository\n  -&gt; Build System\n  -&gt; CI\/CD\n  -&gt; Artifact\n  -&gt; Deployment\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">SCA is one control in a larger chain. A perfect dependency-vulnerability report cannot detect a stolen signing key, compromised build runner, malicious source commit, or altered artifact after scanning.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Map the lab&#8217;s current controls to each supply-chain stage and identify gaps.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the dependency tree, Dependency-Check report, SBOM, hashes, and Git metadata already generated.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Keep the model concrete: ask &#8220;what evidence\/control do we have at this stage?&#8221; instead of listing security buzzwords.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Record current Git commit.<\/li>\n\n\n\n<li>Record dependency inventory and scan report.<\/li>\n\n\n\n<li>Record artifact hash.<\/li>\n\n\n\n<li>Record SBOM.<\/li>\n\n\n\n<li>Map each artifact\/evidence item to the supply-chain stage it protects or observes.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">SCA primarily addresses dependency inventory, known vulnerabilities, and some license visibility. Provenance\/attestation and build integrity operate at different stages.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/supply-chain\n\ngit rev-parse HEAD 2&gt;\/dev\/null | tee evidence\/supply-chain\/source-commit.txt || true\ncp evidence\/dependency-tree-after.txt evidence\/supply-chain\/ 2&gt;\/dev\/null || true\ncp reports\/after\/dependency-check-report.json evidence\/supply-chain\/ 2&gt;\/dev\/null || true\ncp reports\/sbom\/sbom.cdx.json evidence\/supply-chain\/ 2&gt;\/dev\/null || true\nfind target -maxdepth 1 -name '*.jar' -type f -exec shasum -a 256 {} \\;   | tee evidence\/supply-chain\/artifact-sha256.txt\n\nfind evidence\/supply-chain -type f -maxdepth 1 -print\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>evidence\/supply-chain\/source-commit.txt\nevidence\/supply-chain\/dependency-tree-after.txt\nevidence\/supply-chain\/dependency-check-report.json\nevidence\/supply-chain\/sbom.cdx.json\nevidence\/supply-chain\/artifact-sha256.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Identify at least one gap at each stage. Examples: developer identity, branch protection, repository allowlist, runner hardening, artifact signing, attestation verification, deployment policy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create a stage\/control\/evidence\/gap table for the eight stages in the model.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Your table clearly shows where Dependency-Check fits and where different supply-chain controls are needed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SCA is dependency-focused; supply-chain security is end-to-end.<\/li>\n\n\n\n<li>Evidence should follow the artifact from source to deployment.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 7 &#8211; SCA + DEVSECOPS<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">25. SCA in CI\/CD Pipelines<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CI\/CD integration makes SCA repeatable on changes rather than dependent on a person remembering to scan. The pipeline should build, scan, retain reports, and optionally publish SARIF\/security results.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Fast feedback prevents vulnerable dependency changes from quietly reaching later environments and creates auditable evidence for every build.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a current GitHub Actions workflow using checkout v6, setup-java v4, Dependency-Check Maven plugin 13.0.0, upload-artifact v4, and CodeQL SARIF upload v4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The repository needs GitHub Actions enabled. Add an NVD API key as a GitHub Actions secret named&nbsp;<code>NVD_API_KEY<\/code>&nbsp;if using direct NVD access. For production-scale use, prefer an internal NVD mirror\/cache.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The workflow uses an example CVSS threshold of 7.0 only to demonstrate a gate. Organizations must set policy based on their context.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create\u00a0<code>.github\/workflows\/sca.yml<\/code>.<\/li>\n\n\n\n<li>Build on push and pull request.<\/li>\n\n\n\n<li>Run Dependency-Check.<\/li>\n\n\n\n<li>Preserve HTML\/JSON\/SARIF even if the gate fails.<\/li>\n\n\n\n<li>Upload SARIF to GitHub code scanning when permissions allow.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The scanner step may fail intentionally when findings meet the threshold.&nbsp;<code>if: always()<\/code>&nbsp;on evidence steps ensures reports are preserved for investigation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p .github\/workflows\ncat &gt; .github\/workflows\/sca.yml &lt;&lt;'YAML'\nname: SCA - OWASP Dependency-Check\n\non:\n  push:\n  pull_request:\n\njobs:\n  sca:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      security-events: write\n    env:\n      NVD_API_KEY: ${{ secrets.NVD_API_KEY }}\n\n    steps:\n      - name: Checkout\n        uses: actions\/checkout@v6\n\n      - name: Set up Java\n        uses: actions\/setup-java@v4\n        with:\n          distribution: temurin\n          java-version: '17'\n          cache: maven\n\n      - name: Build\n        run: mvn -B -DskipTests package\n\n      - name: OWASP Dependency-Check\n        run: &gt;-\n          mvn -B org.owasp:dependency-check-maven:13.0.0:check\n          -Dformat=HTML,JSON,SARIF\n          -Dodc.outputDirectory=target\/dependency-check\n          -DfailBuildOnCVSS=7\n          -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n\n      - name: Upload Dependency-Check reports\n        if: ${{ always() }}\n        uses: actions\/upload-artifact@v4\n        with:\n          name: dependency-check-reports\n          path: target\/dependency-check\/\n\n      - name: Upload SARIF\n        if: ${{ always() &amp;&amp; hashFiles('target\/dependency-check\/dependency-check-report.sarif') != '' }}\n        uses: github\/codeql-action\/upload-sarif@v4\n        with:\n          sarif_file: target\/dependency-check\/dependency-check-report.sarif\nYAML\n\ncat .github\/workflows\/sca.yml\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># GitHub Actions UI should show steps similar to:\nCheckout\nSet up Java\nBuild\nOWASP Dependency-Check\nUpload Dependency-Check reports\nUpload SARIF\n\n# If a finding meets the example CVSS 7 threshold, the scan step\/job is expected to fail.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm report artifacts are retained after a failing scan. If SARIF upload fails on a forked PR, review GitHub token permission restrictions rather than disabling the security gate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Run once with&nbsp;<code>failBuildOnCVSS=11<\/code>&nbsp;to observe inventory mode, then restore the example&nbsp;<code>7<\/code>&nbsp;gate and observe the policy failure on the vulnerable baseline branch.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The workflow scans every change, produces evidence, and demonstrates pass\/fail behavior without losing reports when the gate triggers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CI makes SCA repeatable and auditable.<\/li>\n\n\n\n<li>Preserve evidence even on failure.<\/li>\n\n\n\n<li>Pin scanner\/plugin versions for reproducibility.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">26. SCA Policies, Gates &amp; Remediation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An SCA policy converts findings into actions: fail, allow temporarily with a documented exception, suppress a validated false positive, or remediate. A suppression should not silently convert a real vulnerability into &#8220;safe.&#8221;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Without policy, reports accumulate but engineering behavior does not change. Exceptions also need expiration\/ownership so they do not become permanent debt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Demonstrate a CVSS build gate, inspect a temporary training suppression mechanism, then remove the exception and complete the real remediation\/re-scan workflow.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use a fresh branch or restore the vulnerable Log4j 2.14.1 baseline for the gate demonstration. Use suppression schema 1.4. The suppression below is explicitly a&nbsp;<strong>training exception demonstration<\/strong>, not a claim that Log4Shell is a false positive.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Prefer generating real false-positive rules from the HTML report&#8217;s Suppress button after validating the CPE\/CVE mismatch. The temporary rule here exists only because a deterministic false positive cannot be guaranteed in every classroom run.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Run with threshold 7 and observe failure.<\/li>\n\n\n\n<li>Create an expiring training suppression for one real finding.<\/li>\n\n\n\n<li>Re-run with the suppression to observe policy mechanics.<\/li>\n\n\n\n<li>Delete the training suppression.<\/li>\n\n\n\n<li>Apply the real dependency upgrade.<\/li>\n\n\n\n<li>Re-scan and verify the vulnerability is gone for the correct reason.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A suppression changes reporting\/policy treatment; it does not change vulnerable bytes. Remediation changes the dependency itself.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code><em># Inventory mode - never fails based on CVSS:<\/em>\nmvn -B org.owasp:dependency-check-maven:13.0.0:check   -Dformat=HTML,JSON   -Dodc.outputDirectory=reports\/policy-inventory   -DfailBuildOnCVSS=11   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n\n<em># Example gate - organization-specific policy:<\/em>\nset +e\nmvn -B org.owasp:dependency-check-maven:13.0.0:check   -Dformat=HTML,JSON   -Dodc.outputDirectory=reports\/policy-gate   -DfailBuildOnCVSS=7   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\nGATE_RC=$?\nset -e\nprintf 'gate exit code: %s\n' \"$GATE_RC\"\n\n<em># For a real false positive, use the HTML report Suppress button to generate XML.<\/em>\n<em># Current suppression schema: dependency-suppression.1.4.xsd<\/em>\n<em># Do NOT suppress CVE-2021-44228 as remediation.<\/em>\n\n<em># Example invocation once a VALIDATED suppression file exists:<\/em>\nmvn -B org.owasp:dependency-check-maven:13.0.0:check   -Dformat=HTML,JSON   -Dodc.outputDirectory=reports\/policy-with-suppressions   -DfailBuildOnCVSS=7   -DsuppressionFiles=dependency-check-suppressions.xml   -DfailBuildOnUnusedSuppressionRule=true   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gate exit code: &lt;non-zero when a CVSS &gt;= 7 finding is present&gt;\n\n# A validated suppression can remove a false-positive finding from gate evaluation.\n# An unused suppression can be configured to fail the build, helping clean stale exceptions.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For every suppression require: finding identity, justification, approver\/owner, expiration where appropriate, and evidence that the component identification or exploitability assessment is valid.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">From the HTML report, open a finding&#8217;s Suppress dialog and inspect the generated XML. Do not commit the rule unless you can justify it as a false positive or approved exception. Explain why&nbsp;<code>failBuildOnUnusedSuppressionRule=true<\/code>&nbsp;is useful.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can demonstrate inventory -&gt; gate -&gt; review -&gt; exception\/suppression mechanics -&gt; remediation -&gt; re-scan, while clearly distinguishing suppression from fixing the dependency.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Gates enforce policy; thresholds are organization-specific.<\/li>\n\n\n\n<li>Suppressions need evidence, ownership, and lifecycle management.<\/li>\n\n\n\n<li>Remediation is preferred when the vulnerability is real.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">27. SCA Reporting, Risk &amp; Compliance<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Different consumers need different report forms. HTML is human-friendly; JSON\/XML are machine-friendly; CSV supports simple analysis; SARIF integrates with code-scanning platforms; JUnit can integrate with test-style gates; SBOM files support inventory and downstream vulnerability\/compliance workflows.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A professional SCA program must preserve evidence that developers, security, DevOps, auditors, and compliance teams can independently consume.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Generate all Dependency-Check formats, generate SBOMs, produce a small metrics file, and assemble an evidence directory.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the remediated project state and keep before\/after reports separate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not fabricate summary numbers. Every metric in the evidence file must be calculated from the generated reports or left blank pending execution.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate\u00a0<code>ALL<\/code>\u00a0Dependency-Check formats.<\/li>\n\n\n\n<li>Generate CycloneDX\/SPDX SBOMs.<\/li>\n\n\n\n<li>Calculate dependency and vulnerability counts from JSON.<\/li>\n\n\n\n<li>Copy dependency tree, update report, and hashes into evidence.<\/li>\n\n\n\n<li>Define which audience consumes which artifact.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Reports are security evidence only if they are tied to a specific source revision\/build and their generation process is trustworthy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/final\nmvn -B org.owasp:dependency-check-maven:13.0.0:check   -Dformat=ALL   -Dodc.outputDirectory=evidence\/final\/dependency-check   -DfailBuildOnCVSS=11   -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n\nsyft scan dir:target\/dependency   -o cyclonedx-json=evidence\/final\/sbom.cdx.json   -o spdx-json=evidence\/final\/sbom.spdx.json\n\nREPORT=evidence\/final\/dependency-check\/dependency-check-report.json\n{\n  printf 'dependencies='; jq '&#91;.dependencies&#91;]] | length' \"$REPORT\"\n  printf 'vulnerabilities='; jq '&#91;.dependencies&#91;].vulnerabilities&#91;]?] | length' \"$REPORT\"\n  printf 'critical='; jq '&#91;.dependencies&#91;].vulnerabilities&#91;]? | select((.severity \/\/ \"\") == \"CRITICAL\")] | length' \"$REPORT\"\n  printf 'high='; jq '&#91;.dependencies&#91;].vulnerabilities&#91;]? | select((.severity \/\/ \"\") == \"HIGH\")] | length' \"$REPORT\"\n  printf 'medium='; jq '&#91;.dependencies&#91;].vulnerabilities&#91;]? | select((.severity \/\/ \"\") == \"MEDIUM\")] | length' \"$REPORT\"\n  printf 'low='; jq '&#91;.dependencies&#91;].vulnerabilities&#91;]? | select((.severity \/\/ \"\") == \"LOW\")] | length' \"$REPORT\"\n} | tee evidence\/final\/metrics.txt\n\nfind evidence\/final -type f -print | sort\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is&nbsp;<strong>representative output<\/strong>, not a claim that your machine will produce identical lines, ordering, scores, or counts. Vulnerability and package metadata changes over time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dependencies=&lt;measured&gt;\nvulnerabilities=&lt;measured&gt;\ncritical=&lt;measured&gt;\nhigh=&lt;measured&gt;\nmedium=&lt;measured&gt;\nlow=&lt;measured&gt;\n\nevidence\/final\/dependency-check\/dependency-check-report.html\n...\nevidence\/final\/sbom.cdx.json\nevidence\/final\/sbom.spdx.json\nevidence\/final\/metrics.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Validate values directly against the HTML report. If a vulnerability has an unknown\/unscored severity, do not force it into low\/medium\/high; record it separately in a real compliance process.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create an audience matrix: developer, security, DevOps, compliance. Assign HTML\/JSON\/XML\/SARIF\/SBOM\/metrics\/evidence artifacts and explain the purpose of each.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A source\/build can be accompanied by consistent, machine-readable and human-readable SCA evidence with numbers derived from real execution.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Reports serve different consumers.<\/li>\n\n\n\n<li>Evidence must be generated from the actual build, not pre-filled examples.<\/li>\n\n\n\n<li>SBOM and vulnerability reports complement each other.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 8 &#8211; ADVANCED SCA<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">28. Dependency Confusion<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency confusion happens when a build intended to resolve an internal package can instead resolve a package with the same or a confusingly similar identity from a public repository. The risk comes from repository precedence, fallback behavior, naming, and weak controls around internal namespaces.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This lab does not publish any package to a public repository. We simulate an internal component only in the local Maven repository.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Traditional SCA may identify vulnerabilities in the dependency that was resolved, but it does not by itself prove that the build resolved the intended publisher or repository. Resolution policy and provenance controls are required alongside vulnerability scanning.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a harmless local Maven artifact named like an internal package, resolve it locally, inspect Maven repository configuration, and identify controls that prevent public fallback for internal namespaces.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You need Java,&nbsp;<code>jar<\/code>, Maven, and the shared lab directory. Maven Install Plugin&nbsp;<code>3.2.0<\/code>&nbsp;is used explicitly so the lab does not depend on whatever plugin version Maven happens to select.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not create or upload a look-alike package to Maven Central, npm, PyPI, or any other public registry. The objective is defensive repository-resolution analysis.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create an empty harmless JAR.<\/li>\n\n\n\n<li>Install it under an internal-looking Maven coordinate.<\/li>\n\n\n\n<li>Resolve the exact coordinate from the local repository.<\/li>\n\n\n\n<li>Inspect effective Maven settings and known repositories.<\/li>\n\n\n\n<li>Write controls that would prevent an unintended public source from satisfying internal coordinates.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The package identity is not enough. Teams also need confidence in the repository, publisher, expected digest, and build policy that produced the dependency.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p advanced\/dependency-confusion\/empty evidence\/dependency-confusion\njar --create \\\n  --file advanced\/dependency-confusion\/payment-utils-1.0.0.jar \\\n  -C advanced\/dependency-confusion\/empty .\n\nmvn org.apache.maven.plugins:maven-install-plugin:3.2.0:install-file \\\n  -Dfile=advanced\/dependency-confusion\/payment-utils-1.0.0.jar \\\n  -DgroupId=com.acme.internal \\\n  -DartifactId=payment-utils \\\n  -Dversion=1.0.0 \\\n  -Dpackaging=jar \\\n  -DgeneratePom=true\n\nmvn org.apache.maven.plugins:maven-dependency-plugin:3.11.0:get \\\n  -Dartifact=com.acme.internal:payment-utils:1.0.0 \\\n  -Dtransitive=false\n\nmvn help:effective-settings &gt; evidence\/dependency-confusion\/effective-settings.xml\nmvn dependency:list-repositories | tee evidence\/dependency-confusion\/repositories.txt\n\nsha256sum advanced\/dependency-confusion\/payment-utils-1.0.0.jar \\\n  | tee evidence\/dependency-confusion\/payment-utils.sha256\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On macOS, if&nbsp;<code>sha256sum<\/code>&nbsp;is unavailable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>shasum -a 256 advanced\/dependency-confusion\/payment-utils-1.0.0.jar \\\n  | tee evidence\/dependency-confusion\/payment-utils.sha256\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The block below is representative only.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;INFO] Installing ...payment-utils-1.0.0.jar to ...\/.m2\/repository\/com\/acme\/internal\/payment-utils\/1.0.0\/...\n&#91;INFO] BUILD SUCCESS\n...\ncom.acme.internal:payment-utils:jar:1.0.0\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Inspect&nbsp;<code>effective-settings.xml<\/code>&nbsp;and&nbsp;<code>repositories.txt<\/code>&nbsp;for mirrors, internal repository managers, public repositories, and unexpected fallback paths. In production, internal coordinates should normally be governed by a controlled repository\/proxy policy instead of trusting whichever repository answers first.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Write a one-page defensive resolution policy containing at least: reserved internal namespace, controlled repository manager, public repository allowlist, exact versioning\/lock strategy where available, provenance or digest validation, and CI monitoring for unexpected package sources.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can demonstrate that&nbsp;<code>com.acme.internal:payment-utils:1.0.0<\/code>&nbsp;was created and resolved locally, identify the repository configuration that controls resolution, and explain how a production build should prevent public fallback for internal identities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Dependency confusion is primarily a resolution and provenance problem.<\/li>\n\n\n\n<li>Never publish a malicious look-alike package for training.<\/li>\n\n\n\n<li>SCA must be complemented by repository and provenance controls.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">29. Typosquatting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Typosquatting uses a package name that visually resembles a legitimate package: one character changed, omitted, repeated, or substituted. A developer can accidentally add the wrong dependency even when the package itself has no known CVE yet.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A vulnerability scanner cannot guarantee that a newly published look-alike package is legitimate. Package identity review is therefore part of software supply-chain hygiene.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Compare an approved coordinate with a deliberately fake look-alike string, build a tiny coordinate allowlist check, and avoid installing the fake package.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No network or package installation is required for the look-alike example.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The second coordinate below is only a text string for comparison. Do not search for, install, or execute an unknown look-alike package.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create an approved package list.<\/li>\n\n\n\n<li>Create a requested package list containing a look-alike.<\/li>\n\n\n\n<li>Compare the two lists.<\/li>\n\n\n\n<li>Fail the simple policy check when a coordinate is not approved.<\/li>\n\n\n\n<li>Relate this to dependency-review controls in CI.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">An allowlist does not solve every software supply-chain problem, but it makes the identity check explicit and gives students a safe way to see the risk.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p advanced\/typosquatting evidence\/typosquatting\n\ncat &gt; advanced\/typosquatting\/approved.txt &lt;&lt;'LIST'\norg.apache.logging.log4j:log4j-core\norg.apache.logging.log4j:log4j-api\nLIST\n\ncat &gt; advanced\/typosquatting\/requested.txt &lt;&lt;'LIST'\norg.apache.logging.log4j:log4j-core\norg.apache.logging.log4j:log4j-c0re\nLIST\n\nprintf '%s\\n' '--- approved' '+++ requested'\ndiff -u advanced\/typosquatting\/approved.txt advanced\/typosquatting\/requested.txt || true\n\nwhile IFS= read -r coordinate; do\n  if grep -Fxq \"$coordinate\" advanced\/typosquatting\/approved.txt; then\n    printf 'APPROVED %s\\n' \"$coordinate\"\n  else\n    printf 'REVIEW   %s\\n' \"$coordinate\"\n  fi\ndone &lt; advanced\/typosquatting\/requested.txt \\\n  | tee evidence\/typosquatting\/package-review.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>APPROVED org.apache.logging.log4j:log4j-core\nREVIEW   org.apache.logging.log4j:log4j-c0re\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Look for single-character substitutions such as&nbsp;<code>0<\/code>&nbsp;versus&nbsp;<code>o<\/code>, inserted separators, changed organization\/group names, or unexpected publishers. The check is about identity, not vulnerability score.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Export the actual Maven dependency list from the lab project and compare every direct coordinate with a short approved direct-dependency file that you create yourself. Do not approve transitive packages automatically; record which direct package introduced them.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn dependency:list -DexcludeTransitive=true \\\n  | tee evidence\/typosquatting\/direct-dependencies.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The safe look-alike is flagged for review without installing or executing it, and you can explain why zero known CVEs would not prove package legitimacy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Name similarity is a supply-chain signal, not a CVE signal.<\/li>\n\n\n\n<li>Validate publisher\/group, repository, version, and provenance.<\/li>\n\n\n\n<li>Do not install suspicious packages merely to test them.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">30. Package Hijacking<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Package hijacking occurs when an attacker gains control of a legitimate package identity or release path, for example through a maintainer account compromise, stolen publishing token, abandoned package transfer, or compromised CI release credential.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The coordinate can be legitimate while a new release is not. A CVE database may not know about the compromise when the malicious release first appears.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inspect package metadata for repository\/maintainer clues, record the exact artifact digest we received, and create a release-review checklist that would detect unexpected ownership or source changes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use&nbsp;<code>log4j-core<\/code>&nbsp;already downloaded by Maven. No malicious version is used.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">This is a monitoring and integrity lab. We do not simulate account compromise or publish any release.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Locate the local JAR and POM.<\/li>\n\n\n\n<li>Record the exact SHA-256 digest.<\/li>\n\n\n\n<li>Inspect POM metadata such as project URL and SCM fields when present.<\/li>\n\n\n\n<li>Record the approved source\/repository expectation.<\/li>\n\n\n\n<li>Define alerts for publisher, repository, signing, or release-process changes.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Version pins help reproducibility but do not prove publisher integrity. Digests and attestations bind the bytes; provenance binds the artifact to a build\/source claim.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/package-hijacking\n\nLOG4J_JAR=\"$HOME\/.m2\/repository\/org\/apache\/logging\/log4j\/log4j-core\/2.14.1\/log4j-core-2.14.1.jar\"\nLOG4J_POM=\"$HOME\/.m2\/repository\/org\/apache\/logging\/log4j\/log4j-core\/2.14.1\/log4j-core-2.14.1.pom\"\n\nls -l \"$LOG4J_JAR\" \"$LOG4J_POM\"\n\nif command -v sha256sum &gt;\/dev\/null 2&gt;&amp;1; then\n  sha256sum \"$LOG4J_JAR\" | tee evidence\/package-hijacking\/log4j-core-2.14.1.sha256\nelse\n  shasum -a 256 \"$LOG4J_JAR\" | tee evidence\/package-hijacking\/log4j-core-2.14.1.sha256\nfi\n\ngrep -E '&lt;url&gt;|&lt;scm&gt;|&lt;connection&gt;|&lt;developerConnection&gt;|&lt;tag&gt;' \"$LOG4J_POM\" \\\n  | head -n 30 \\\n  | tee evidence\/package-hijacking\/pom-source-metadata.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Representative only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;64-hex-digest&gt;  ...\/log4j-core-2.14.1.jar\n&lt;url&gt;...&lt;\/url&gt;\n&lt;scm&gt;...&lt;\/scm&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The exact metadata varies by POM and version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Compare the expected group\/artifact, source repository, project URL, release process, and digest with organizational records. Unexpected ownership, repository migration, sudden unsigned releases, or a new publication path deserve review even if a vulnerability scanner is clean.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create&nbsp;<code>evidence\/package-hijacking\/release-review.md<\/code>&nbsp;with the fields: package, approved registry, approved source repository, maintainers\/owner source, expected signing\/provenance mechanism, exact version, digest, release date, and reviewer decision.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You have an integrity record for the exact artifact and can list controls that reduce package-hijack risk: MFA, protected publisher tokens, least-privilege CI credentials, signed\/provenanced releases, repository proxying\/quarantine, and change monitoring.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A legitimate package name does not guarantee a legitimate new release.<\/li>\n\n\n\n<li>Digest and provenance checks complement SCA.<\/li>\n\n\n\n<li>Monitor publisher and release-path changes.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">31. Package Provenance<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Package provenance answers: Where did this artifact come from, what source\/build produced it, and can we verify that claim? At minimum, record package repository, version, source metadata, and integrity digest. Stronger workflows add signed build attestations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check finds known vulnerable components; it is not a general build-provenance verifier. Provenance adds confidence that scanned and deployed bytes came from an expected build process.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Record local package provenance evidence and review a current GitHub Actions attestation pattern for a built JAR and its SBOM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the shared Maven project. GitHub artifact attestations require a GitHub-hosted workflow context and appropriate repository permissions; the local portion of the lab works without GitHub.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Treat an attestation as a signed claim whose subject digest must match the artifact you verify. It does not automatically make unsafe source code safe.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Build the lab JAR.<\/li>\n\n\n\n<li>Generate an SBOM.<\/li>\n\n\n\n<li>Hash the JAR and SBOM locally.<\/li>\n\n\n\n<li>Record source revision if the project is in Git.<\/li>\n\n\n\n<li>Inspect the GitHub Actions attestation example.<\/li>\n\n\n\n<li>If using GitHub, generate and verify attestations in your own repository.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The local evidence gives you reproducible identifiers. GitHub&#8217;s&nbsp;<code>actions\/attest@v4<\/code>&nbsp;can create build provenance and SBOM attestations for workflow-produced subjects.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/provenance\nmvn -B package -DskipTests\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\nsyft scan dir:target\/dependency \\\n  -o cyclonedx-json=evidence\/provenance\/sbom.cdx.json\n\nARTIFACT=target\/sca-lab-1.0.0.jar\nif command -v sha256sum &gt;\/dev\/null 2&gt;&amp;1; then\n  sha256sum \"$ARTIFACT\" evidence\/provenance\/sbom.cdx.json \\\n    | tee evidence\/provenance\/sha256.txt\nelse\n  shasum -a 256 \"$ARTIFACT\" evidence\/provenance\/sbom.cdx.json \\\n    | tee evidence\/provenance\/sha256.txt\nfi\n\ngit rev-parse HEAD 2&gt;\/dev\/null | tee evidence\/provenance\/source-commit.txt || true\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Current GitHub Actions pattern for an SBOM attestation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>permissions:\n  id-token: write\n  contents: read\n  attestations: write\n\nsteps:\n  - uses: actions\/checkout@v6\n\n  <em># Build the artifact and generate a JSON SBOM before this step.<\/em>\n\n  - name: Attest artifact and SBOM\n    uses: actions\/attest@v4\n    with:\n      subject-path: 'target\/sca-lab-1.0.0.jar'\n      sbom-path: 'evidence\/provenance\/sbom.cdx.json'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After the GitHub workflow creates the attestation, verify the downloaded artifact using GitHub CLI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gh attestation verify target\/sca-lab-1.0.0.jar --repo OWNER\/REPOSITORY\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Local output contains real SHA-256 digests calculated from your files. The GitHub verification command, when run against a successfully attested artifact from your repository, should report a verified attestation for the artifact digest.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm that the attestation subject digest matches the exact artifact being verified and that repository\/workflow\/source identity is the one your policy expects. Do not treat a matching filename as proof.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Add an&nbsp;<code>evidence\/provenance\/provenance-record.md<\/code>&nbsp;containing source commit, artifact path, artifact SHA-256, SBOM SHA-256, package manager, repository source, and attestation verification result if GitHub was used.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can tie a build artifact and SBOM to exact digests and explain how signed attestations strengthen that chain of evidence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Provenance identifies the expected origin\/build of an artifact.<\/li>\n\n\n\n<li>A digest identifies exact bytes; an attestation makes a verifiable claim about them.<\/li>\n\n\n\n<li>Dependency-Check complements provenance; it does not replace it.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">32. VEX<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">VEX, Vulnerability Exploitability eXchange, communicates the status of a vulnerability in the context of a specific product. Common lifecycle states include&nbsp;<code>under_investigation<\/code>,&nbsp;<code>affected<\/code>,&nbsp;<code>not_affected<\/code>, and&nbsp;<code>fixed<\/code>, depending on the VEX format and statement semantics.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An SBOM says what components are present. VEX communicates a vulnerability impact assessment for the product using those components.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A component can be present while the vulnerable behavior is not exploitable in a particular product. That conclusion must be evidence-based. VEX provides a machine-readable way to communicate the assessment without deleting the component from the SBOM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use current&nbsp;<code>vexctl<\/code>&nbsp;to create an OpenVEX&nbsp;<code>under_investigation<\/code>&nbsp;statement for the real Log4Shell finding used earlier in the lab, then validate and inspect the document.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Install&nbsp;<code>vexctl<\/code>&nbsp;0.4.4 or a later explicitly reviewed version. On Homebrew systems:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>brew install vexctl\nvexctl version\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check does not directly provide a complete VEX authoring\/consumption workflow.&nbsp;<code>vexctl<\/code>&nbsp;is the complementary tool in this lab.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Do not mark a real application&nbsp;<code>not_affected<\/code>&nbsp;just to silence a scanner. A&nbsp;<code>not_affected<\/code>&nbsp;statement needs a defensible justification or impact statement under OpenVEX rules.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create an\u00a0<code>under_investigation<\/code>\u00a0statement.<\/li>\n\n\n\n<li>Validate it strictly.<\/li>\n\n\n\n<li>Inspect product, vulnerability, status, author\/timestamp metadata.<\/li>\n\n\n\n<li>Explain what evidence would be required before publishing a later\u00a0<code>not_affected<\/code>,\u00a0<code>affected<\/code>, or\u00a0<code>fixed<\/code>\u00a0status.<\/li>\n\n\n\n<li>Explain how a consumer can understand the status lifecycle without deleting the component from the SBOM.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The lab uses the real&nbsp;<code>CVE-2021-44228<\/code>&nbsp;finding and starts with the neutral&nbsp;<code>under_investigation<\/code>&nbsp;state so no unsupported&nbsp;<code>not_affected<\/code>&nbsp;claim is made. In production, the product PURL and vulnerability identifier must refer to the exact product\/component context you assessed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/vex\n\nvexctl create \\\n  --product='pkg:maven\/com.example\/sca-lab@1.0.0' \\\n  --vuln='CVE-2021-44228' \\\n  --status='under_investigation' \\\n  &gt; evidence\/vex\/under-investigation.vex.json\n\nvexctl validate --strict evidence\/vex\/under-investigation.vex.json\njq '.statements&#91;] | {vulnerability, products, status}' \\\n  evidence\/vex\/under-investigation.vex.json\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>CVE-2021-44228<\/code>&nbsp;is the real Log4j finding used in the earlier vulnerable-version lab. The initial&nbsp;<code>under_investigation<\/code>&nbsp;state does not make an unsupported claim that the application is unaffected. If a later assessment concludes&nbsp;<code>not_affected<\/code>, OpenVEX requires the appropriate evidence-backed justification or impact statement; if remediation removes\/fixes the condition, publish a subsequent status for the correctly versioned remediated product.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><code>vexctl validate --strict<\/code>&nbsp;should exit successfully for valid documents.&nbsp;<code>jq<\/code>&nbsp;should show an OpenVEX document containing the product PURL, vulnerability identifier, timestamp, and selected status.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Check that status is tied to the correct product and vulnerability, the document is valid, and any&nbsp;<code>not_affected<\/code>&nbsp;statement has evidence plus a valid justification\/impact explanation. A VEX assertion is not a substitute for investigation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Take one real finding from your Dependency-Check report and draft, but do not automatically approve, a VEX investigation record containing: product, CVE, initial status&nbsp;<code>under_investigation<\/code>, evidence owner, reachability observations, environment assumptions, and next decision date.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can distinguish SBOM inventory from VEX exploitability\/status communication and validate a machine-readable OpenVEX document.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SBOM answers &#8220;what is present&#8221;; VEX communicates vulnerability status in product context.<\/li>\n\n\n\n<li><code>not_affected<\/code>\u00a0requires evidence, not convenience.<\/li>\n\n\n\n<li>Dependency-Check remains the finder; VEX is complementary assessment metadata.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">33. Reachability Analysis<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There is a major difference between &#8220;the dependency exists&#8221; and &#8220;the vulnerable code path is actually reachable from this application.&#8221; True reachability analysis usually requires source\/bytecode call-graph analysis, runtime evidence, or specialized SAST\/SCA capabilities.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">OWASP Dependency-Check does not provide true code-level reachability analysis. It detects known vulnerabilities in identified dependencies; it should not be described as proving exploitability or call-path reachability.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Presence-based findings are intentionally conservative. Reachability evidence can help prioritize work or support a VEX assessment, but it must not be confused with a dependency simply appearing in the graph.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use simple source and bytecode inspection to demonstrate usage evidence for Log4j versus another dependency. This is a teaching approximation, not a full reachability engine.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the shared lab project in which&nbsp;<code>App.java<\/code>&nbsp;uses Log4j. If&nbsp;<code>httpclient<\/code>&nbsp;is present in the POM but not called by the source, it provides a useful contrast.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Be precise with wording:&nbsp;<code>grep<\/code>&nbsp;and&nbsp;<code>jdeps<\/code>&nbsp;can provide evidence of references\/dependencies, but they do not prove whether every vulnerable method is reachable under all runtime paths.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Confirm both dependencies exist in the Maven tree.<\/li>\n\n\n\n<li>Search source for Log4j and HttpClient usage.<\/li>\n\n\n\n<li>Build the application.<\/li>\n\n\n\n<li>Copy runtime dependencies.<\/li>\n\n\n\n<li>Run\u00a0<code>jdeps<\/code>\u00a0against the JAR.<\/li>\n\n\n\n<li>Compare package presence with source\/bytecode references.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">This exercise teaches why an SCA finding is not the same thing as a proven exploitable call path.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/reachability\n\nmvn dependency:tree | tee evidence\/reachability\/dependency-tree.txt\n\ngrep -RniE 'log4j|LogManager|Logger' src || true\ngrep -RniE 'HttpClient|HttpClients|org\\.apache\\.http' src || true\n\nmvn -B package -DskipTests\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\n\njdeps -verbose:class \\\n  --class-path 'target\/dependency\/*' \\\n  target\/sca-lab-1.0.0.jar \\\n  | tee evidence\/reachability\/jdeps.txt\n\ngrep -Ei 'log4j|httpclient|httpcore' evidence\/reachability\/jdeps.txt || true\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Your output should show the dependency tree contains the declared packages. Source or&nbsp;<code>jdeps<\/code>&nbsp;output may show references to Log4j because the sample application uses it. If HttpClient is not referenced by the compiled application, it may not appear in class-level reference output even though Maven resolved it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Exact lines depend on the current source and compiler.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Separate these statements:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Dependency present             -&gt; established by package manager \/ SBOM \/ SCA\nClass referenced               -&gt; partial static evidence\nVulnerable method reachable    -&gt; requires stronger reachability analysis\nRuntime exploitable            -&gt; additionally depends on configuration, input, environment, defenses, and exploit preconditions\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For one actual Dependency-Check finding, create&nbsp;<code>evidence\/reachability\/assessment.md<\/code>&nbsp;and record: component presence, direct\/transitive path, source references found, bytecode references found, vulnerable API\/method from authoritative advisory, environment assumptions, and whether further specialist reachability analysis is required.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can show a dependency can exist without proving its vulnerable code path is reachable, and you do not attribute code-level reachability capability to Dependency-Check.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Dependency presence is not the same as vulnerable-code reachability.<\/li>\n\n\n\n<li><code>jdeps<\/code>\/source search are teaching evidence, not a full reachability engine.<\/li>\n\n\n\n<li>Use specialized analysis plus context before making exploitability claims.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">34. Vulnerability Prioritization<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Prioritization is the process of deciding what to investigate and remediate first. No single number is sufficient. Useful signals include CVSS, EPSS, CISA KEV status, dependency path\/usage, internet exposure, environment, business importance, exploit preconditions, and whether a supported fix exists.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Do not add these signals together into an invented score unless your organization has a formally defined and validated method. This lab keeps the signals visible and separate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A very high CVSS finding may be unreachable or isolated in a non-production tool, while a lower-scored vulnerability known to be exploited can deserve urgent attention. Context changes action.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Build a prioritization worksheet directly from Dependency-Check results, enrich selected CVEs with live EPSS and KEV data, and document contextual decisions without creating a proprietary score.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the JSON Dependency-Check report generated earlier,&nbsp;<code>curl<\/code>,&nbsp;<code>jq<\/code>, FIRST EPSS API, and the official CISA KEV JSON feed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Priority and severity are not synonyms. Preserve the authoritative source values and capture the decision separately.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Export findings from the real report.<\/li>\n\n\n\n<li>Choose two real CVEs from the report if available.<\/li>\n\n\n\n<li>Fetch current EPSS data for each.<\/li>\n\n\n\n<li>Check each against current CISA KEV.<\/li>\n\n\n\n<li>Add direct\/transitive, usage, exposure, environment, business, and fix-availability context.<\/li>\n\n\n\n<li>Record the remediation decision without calculating a made-up composite score.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">CVSS describes vulnerability severity characteristics. EPSS estimates exploitation probability over the next 30 days. KEV indicates evidence of known exploitation. Application context tells you whether and how the component affects your system.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/prioritization\nREPORT=evidence\/final\/dependency-check\/dependency-check-report.json\n\njq -r '\n  &#91;.dependencies&#91;] as $d\n   | ($d.vulnerabilities \/\/ &#91;])&#91;]\n   | &#91;$d.fileName,\n      .name,\n      (.severity \/\/ \"UNSCORED\"),\n      (.cvssv3.baseScore \/\/ .cvssv4.baseScore \/\/ \"\")]\n   | @tsv]\n  | .&#91;]' \"$REPORT\" \\\n  | tee evidence\/prioritization\/findings.tsv\n\n<em># Replace with a REAL CVE selected from findings.tsv.<\/em>\nCVE=CVE-2021-44228\n\ncurl -fsS \"https:\/\/api.first.org\/data\/v1\/epss?cve=${CVE}\" \\\n  | tee \"evidence\/prioritization\/${CVE}-epss.json\" \\\n  | jq '.data&#91;] | {cve, epss, percentile, date}'\n\ncurl -fsS \\\n  https:\/\/www.cisa.gov\/sites\/default\/files\/feeds\/known_exploited_vulnerabilities.json \\\n  -o evidence\/prioritization\/cisa-kev.json\n\njq --arg cve \"$CVE\" \\\n  '.vulnerabilities&#91;] | select(.cveID == $cve) |\n   {cveID, vendorProject, product, vulnerabilityName, dateAdded, dueDate, requiredAction}' \\\n  evidence\/prioritization\/cisa-kev.json\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create the worksheet:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; evidence\/prioritization\/worksheet.tsv &lt;&lt;'TSV'\nCVE\tCVSS\tEPSS\tEPSS_percentile\tKEV\tdirect_or_transitive\tused_or_unknown\tenvironment\texposure\tbusiness_context\tfix_available\tdecision\tevidence\nTSV\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The EPSS command returns the current API value at execution time. The KEV command returns an object only if the selected CVE is present in the current catalog. Do not copy a numeric EPSS value from this manual because it can change daily.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For&nbsp;<code>CVE-2021-44228<\/code>, the authoritative sources should identify the real Log4j vulnerability; current metadata is retrieved during the lab rather than fabricated here.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Compare signals without collapsing them:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Finding A: High CVSS + not in KEV + low\/unknown usage context\nFinding B: Lower CVSS + in KEV + exposed\/used context\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use actual findings if your scan contains such a pair. If it does not, treat the lines above only as an unlabeled decision scenario &#8211; do not invent CVE IDs or scores to force the comparison.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Complete at least two rows in&nbsp;<code>worksheet.tsv<\/code>&nbsp;using only measured or verified values. Add a short paragraph explaining why your remediation order follows from the evidence and organizational context.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Every priority decision can be traced to real scanner output, current external intelligence, and explicit application\/business context. No proprietary score was invented.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CVSS, EPSS, KEV, and application context answer different questions.<\/li>\n\n\n\n<li>Known exploitation can materially change urgency.<\/li>\n\n\n\n<li>Prioritization is contextual and evidence-based.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">35. SBOM Vulnerability Management<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An SBOM is useful beyond build time. Stored SBOMs can be re-scanned as new vulnerability intelligence appears, even when an application is not rebuilt that day.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A component that was clean on release day can receive a CVE later. Keeping a build-specific SBOM makes historical inventory searchable and enables continuous vulnerability management.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Generate a CycloneDX SBOM, scan that SBOM with the complementary Grype scanner, store hashes and vulnerability output, remediate a dependency, regenerate the SBOM, and compare the two inventories.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use Syft 1.52.0 and Grype 0.119.0, or later versions that you have explicitly revalidated. Dependency-Check remains the primary scanner in this course; Grype is used here because it supports scanning a stored SBOM directly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The result sets from two scanners need not be identical because data sources, matching logic, package identity, and update timing differ. Treat differences as investigation inputs, not proof that one tool is automatically wrong.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Copy resolved dependencies.<\/li>\n\n\n\n<li>Generate a build-specific CycloneDX SBOM.<\/li>\n\n\n\n<li>Hash and archive it.<\/li>\n\n\n\n<li>Scan the stored SBOM with Grype.<\/li>\n\n\n\n<li>Remediate\/update the project.<\/li>\n\n\n\n<li>Generate a new SBOM.<\/li>\n\n\n\n<li>Diff component versions and re-scan.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">This creates the full inventory -&gt; intelligence -&gt; remediation -&gt; updated inventory loop.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Before remediation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/sbom-vuln\/before evidence\/sbom-vuln\/after\nrm -rf target\/dependency\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\n\nsyft scan dir:target\/dependency \\\n  -o cyclonedx-json=evidence\/sbom-vuln\/before\/sbom.cdx.json\n\ngrype sbom:evidence\/sbom-vuln\/before\/sbom.cdx.json \\\n  -o json \\\n  &gt; evidence\/sbom-vuln\/before\/grype.json\n\njq -r '.components&#91;] | &#91;.group, .name, .version] | @tsv' \\\n  evidence\/sbom-vuln\/before\/sbom.cdx.json \\\n  | sort \\\n  &gt; evidence\/sbom-vuln\/before\/components.tsv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After your approved dependency remediation\/update:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>rm -rf target\/dependency\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\n\nsyft scan dir:target\/dependency \\\n  -o cyclonedx-json=evidence\/sbom-vuln\/after\/sbom.cdx.json\n\ngrype sbom:evidence\/sbom-vuln\/after\/sbom.cdx.json \\\n  -o json \\\n  &gt; evidence\/sbom-vuln\/after\/grype.json\n\njq -r '.components&#91;] | &#91;.group, .name, .version] | @tsv' \\\n  evidence\/sbom-vuln\/after\/sbom.cdx.json \\\n  | sort \\\n  &gt; evidence\/sbom-vuln\/after\/components.tsv\n\ndiff -u \\\n  evidence\/sbom-vuln\/before\/components.tsv \\\n  evidence\/sbom-vuln\/after\/components.tsv || true\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Hash evidence:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if command -v sha256sum &gt;\/dev\/null 2&gt;&amp;1; then\n  sha256sum evidence\/sbom-vuln\/*\/sbom.cdx.json \\\n    | tee evidence\/sbom-vuln\/sbom-hashes.txt\nelse\n  shasum -a 256 evidence\/sbom-vuln\/*\/sbom.cdx.json \\\n    | tee evidence\/sbom-vuln\/sbom-hashes.txt\nfi\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You should have two SBOMs with real component\/version lists, two Grype result files, a component diff, and cryptographic hashes. Exact vulnerabilities and counts depend on the dependencies and intelligence databases at execution time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm that the remediated component version changed in the&nbsp;<code>components.tsv<\/code>&nbsp;diff and that the SBOM scan result reflects current vulnerability intelligence. If a finding remains, investigate whether another dependency path\/version still introduces it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Pretend the source repository is temporarily unavailable. Using only&nbsp;<code>before\/sbom.cdx.json<\/code>, answer: Which Log4j\/Jackson\/HttpClient versions were shipped, and what does the current SBOM vulnerability scan report for them today?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can perform vulnerability reassessment from a stored SBOM, regenerate inventory after remediation, and preserve verifiable before\/after evidence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SBOMs enable vulnerability reassessment after release.<\/li>\n\n\n\n<li>Re-scan stored inventories when intelligence changes.<\/li>\n\n\n\n<li>Regenerate and archive SBOMs after remediation.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">36. SCA vs Software Supply Chain Security<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">SCA is a dependency-focused security discipline. Software supply-chain security is broader and includes source integrity, repository controls, dependency resolution, build isolation, provenance, signing\/attestation, CI\/CD identity, artifact distribution, and deployment controls.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check is valuable, but treating one scanner as the entire supply-chain program leaves major risks uncovered.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Map every artifact created in this course to either SCA, broader supply-chain security, or both, and place Dependency-Check in the end-to-end model.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the&nbsp;<code>evidence\/<\/code>&nbsp;directory produced by previous labs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The goal is not to diminish SCA; it is to define its boundary accurately so controls can be layered correctly.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Review the comparison table.<\/li>\n\n\n\n<li>Inventory evidence files created so far.<\/li>\n\n\n\n<li>Classify each control\/artifact.<\/li>\n\n\n\n<li>Identify gaps not covered by Dependency-Check.<\/li>\n\n\n\n<li>Draw the complete supply-chain flow.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A mature program keeps vulnerability\/component analysis strong while adding integrity and trust controls around the rest of the lifecycle.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p evidence\/sca-vs-supply-chain\nfind evidence -type f -print | sort \\\n  | tee evidence\/sca-vs-supply-chain\/evidence-inventory.txt\n\ncat &gt; evidence\/sca-vs-supply-chain\/control-map.tsv &lt;&lt;'TSV'\nartifact_or_control\tSCA\tSupply_Chain\twhy\nDependency-Check vulnerability report\tyes\tyes\tKnown-vulnerability component analysis\nDependency tree\tyes\tyes\tDependency inventory\/path\nSBOM\tyes\tyes\tComponent inventory and exchange\nLicense inventory\tyes\tyes\tDependency governance\nRepository resolution policy\tno\tyes\tControls dependency origin\nPackage digest\tpartial\tyes\tExact artifact integrity\nBuild provenance attestation\tno\tyes\tBuild\/source origin claim\nCI identity and permissions\tno\tyes\tPipeline trust boundary\nVEX\tcomplementary\tyes\tProduct vulnerability status communication\nReachability analysis\tcomplementary\tyes\tExploitability\/context evidence\nTSV\n\ncolumn -t -s $'\\t' evidence\/sca-vs-supply-chain\/control-map.tsv 2&gt;\/dev\/null \\\n  || cat evidence\/sca-vs-supply-chain\/control-map.tsv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Practical comparison:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">SCA<\/th><th class=\"has-text-align-left\" data-align=\"left\">Software Supply Chain Security<\/th><\/tr><\/thead><tbody><tr><td>Dependency-focused<\/td><td>End-to-end lifecycle<\/td><\/tr><tr><td>Known vulnerability detection<\/td><td>Vulnerability + integrity + trust controls<\/td><\/tr><tr><td>Dependency inventory<\/td><td>Source\/build\/artifact provenance<\/td><\/tr><tr><td>License visibility<\/td><td>Publisher\/repository governance<\/td><\/tr><tr><td>SBOM creation\/consumption<\/td><td>SBOM + attestations\/signing<\/td><\/tr><tr><td>Direct\/transitive dependency risk<\/td><td>Build system and CI\/CD identity risk<\/td><\/tr><tr><td>Version\/remediation workflow<\/td><td>Release\/distribution\/deployment integrity<\/td><\/tr><tr><td>Component intelligence<\/td><td>Package origin and tamper resistance<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The control map should clearly show which artifacts belong to SCA and which require broader supply-chain controls. There is intentional overlap: an SBOM is useful to both.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check belongs primarily in the SCA\/known-vulnerability component-analysis layer. It does not prove publisher identity, build integrity, package provenance, or code-level reachability.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Add three missing supply-chain controls to&nbsp;<code>control-map.tsv<\/code>&nbsp;for your organization. For each, name the pipeline stage, owner, evidence artifact, and failure\/exception process.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can explain exactly what Dependency-Check covers and identify the additional controls required for an end-to-end supply-chain security program.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SCA is essential but narrower than supply-chain security.<\/li>\n\n\n\n<li>Dependency-Check is a component\/vulnerability tool, not an end-to-end trust platform.<\/li>\n\n\n\n<li>Layer inventory, vulnerability, provenance, build integrity, and deployment controls.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">37. SCA Integration with DevSecOps<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What You Need to Know<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">DevSecOps makes security checks repeatable parts of delivery rather than one-off manual activities. For SCA, the useful pattern is dependency resolution -&gt; scan -&gt; analysis -&gt; SBOM -&gt; gate -&gt; evidence -&gt; remediation -&gt; re-scan.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Why It Matters in SCA<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A scan that only runs during training quickly becomes stale. Automation makes the same control run on pull requests, merges, releases, and scheduled reassessments.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. What We Will Do in the Lab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run the complete local workflow through one script, preserve evidence, and map it to the GitHub Actions workflow from Topic 25.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Lab Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use the shared Maven project,&nbsp;<code>mvn<\/code>,&nbsp;<code>jq<\/code>, Syft, and the Dependency-Check Maven plugin 13.0.0. Set&nbsp;<code>NVD_API_KEY<\/code>&nbsp;when available.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Step-by-Step Lab<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The sample gate of CVSS 7.0 is a teaching policy, not an industry-standard universal threshold. Organizations must define their own policy and exception process.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Build and resolve dependencies.<\/li>\n\n\n\n<li>Generate dependency tree and Dependency-Check reports.<\/li>\n\n\n\n<li>Generate SBOM.<\/li>\n\n\n\n<li>Extract findings\/metrics.<\/li>\n\n\n\n<li>Apply a security gate.<\/li>\n\n\n\n<li>Remediate and re-run when the gate fails.<\/li>\n\n\n\n<li>Preserve source\/build\/evidence identity.<\/li>\n\n\n\n<li>Run the equivalent sequence in CI.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udca1 Explanation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">This is the final integrated workflow before the capstone uses a separate real training repository.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Commands<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Create an end-to-end local driver:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; run-sca.sh &lt;&lt;'SCRIPT'\n<em>#!\/usr\/bin\/env bash<\/em>\nset -euo pipefail\n\nOUT=\"evidence\/devsecops\/$(date -u +%Y%m%dT%H%M%SZ)\"\nmkdir -p \"$OUT\/dependency-check\" \"$OUT\/sbom\"\n\nmvn -B package -DskipTests\nmvn -B dependency:tree | tee \"$OUT\/dependency-tree.txt\"\nrm -rf target\/dependency\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\n\nmvn -B org.owasp:dependency-check-maven:13.0.0:check \\\n  -Dformat=HTML,JSON,SARIF \\\n  -Dodc.outputDirectory=\"$OUT\/dependency-check\" \\\n  -DfailBuildOnCVSS=11 \\\n  ${NVD_API_KEY:+-DnvdApiKeyEnvironmentVariable=NVD_API_KEY}\n\nsyft scan dir:target\/dependency \\\n  -o cyclonedx-json=\"$OUT\/sbom\/sbom.cdx.json\" \\\n  -o spdx-json=\"$OUT\/sbom\/sbom.spdx.json\"\n\nREPORT=\"$OUT\/dependency-check\/dependency-check-report.json\"\njq '{\n  dependencies: (.dependencies | length),\n  vulnerabilities: (&#91;.dependencies&#91;].vulnerabilities&#91;]?] | length),\n  critical: (&#91;.dependencies&#91;].vulnerabilities&#91;]? | select(.severity == \"CRITICAL\")] | length),\n  high: (&#91;.dependencies&#91;].vulnerabilities&#91;]? | select(.severity == \"HIGH\")] | length),\n  medium: (&#91;.dependencies&#91;].vulnerabilities&#91;]? | select(.severity == \"MEDIUM\")] | length),\n  low: (&#91;.dependencies&#91;].vulnerabilities&#91;]? | select(.severity == \"LOW\")] | length)\n}' \"$REPORT\" | tee \"$OUT\/metrics.json\"\n\nprintf '%s\\n' \"$OUT\"\nSCRIPT\n\nchmod +x run-sca.sh\n.\/run-sca.sh\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then run the explicit teaching gate against the same project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn -B org.owasp:dependency-check-maven:13.0.0:check \\\n  -Dformat=HTML,JSON,SARIF \\\n  -Dodc.outputDirectory=evidence\/devsecops\/gate \\\n  -DfailBuildOnCVSS=7.0 \\\n  -DnvdApiKeyEnvironmentVariable=NVD_API_KEY\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you do not have an NVD API key, omit the last property for a learning run. For repeated\/CI operation, follow OWASP guidance to use a supported NVD API configuration or internal NVD mirror rather than repeatedly forcing cold public updates.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7. Expected Output<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The first script creates timestamped dependency tree, HTML\/JSON\/SARIF reports, CycloneDX\/SPDX SBOMs, and measured metrics. The gate command exits according to the actual findings at the selected threshold.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A failure is a successful demonstration of the gate when a real finding meets\/exceeds policy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">8. What to Look For<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Trace one finding through the complete flow:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Developer\n  -&gt; Git\/GitHub\n  -&gt; Build\n  -&gt; Dependency Resolution\n  -&gt; SCA\n  -&gt; Vulnerability Analysis\n  -&gt; SBOM\n  -&gt; Security Gate\n  -&gt; Report\/Evidence\n  -&gt; Remediation\n  -&gt; Re-scan\n  -&gt; Deployment decision\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Make sure the CI artifact paths and local evidence paths refer to the same logical outputs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">9. Practical Exercise<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Break the gate intentionally using the known vulnerable training version from earlier, capture the failing evidence, remediate to an approved fixed\/current version, run the workflow again, and document the before\/after decision. Never introduce a fake vulnerability merely to make a gate fail.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">10. Expected Result<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Success Criteria<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You can run SCA locally and in CI, preserve evidence, enforce a policy threshold, remediate a real dependency finding, and verify the result with a new scan\/SBOM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">11. Key Takeaway<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Automate the same evidence-producing workflow used during investigation.<\/li>\n\n\n\n<li>Gates should be policy-driven, reviewable, and repeatable.<\/li>\n\n\n\n<li>Re-scan after every remediation or approved exception.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">MODULE 9 &#8211; FINAL CAPSTONE<\/h1>\n\n\n\n<h1 class=\"wp-block-heading\">Complete End-to-End SCA Security Lab<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Objective<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This capstone combines dependency discovery, dependency trees, OWASP Dependency-Check, CVE\/CWE\/CVSS\/CPE analysis, NVD verification, EPSS, KEV, outdated dependency review, license review, SBOM generation, remediation, re-scanning, policy gates, CI\/CD, and final security evidence.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The target is the public educational repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;github.com\/hv-oblikas\/vulnerable-demo-app\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It is intentionally vulnerable and explicitly marked for security testing only.&nbsp;<strong>Do not deploy it, expose it to the Internet, or execute exploit examples from its source\/README.<\/strong>&nbsp;This capstone only resolves dependencies and analyzes security metadata.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Required:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Git\nJava 11+ (Java 17 recommended for this lab)\nMaven 3.8.1+\ncurl\njq\nOWASP Dependency-Check Maven Plugin 13.0.0\nSyft 1.52.0 or later explicitly revalidated version\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Useful\/optional:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NVD API key in NVD_API_KEY\nGrype 0.119.0 for complementary SBOM scanning\nGitHub repository for CI\/CD exercise\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify tools before starting:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git --version\njava -version\nmvn -version\njq --version\ncurl --version | head -n 1\nsyft version\ngrype version\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 1 &#8211; Clone and Pin the Real Training Project<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Clone the project, record the exact commit, and create an evidence directory outside the Java subproject.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone --depth 1 https:\/\/github.com\/hv-oblikas\/vulnerable-demo-app.git\ncd vulnerable-demo-app\n\nmkdir -p capstone-evidence\/{before,after,investigation,ci,final}\ngit rev-parse HEAD | tee capstone-evidence\/source-commit.txt\ngit status --short | tee capstone-evidence\/source-status-before.txt\n\nsed -n '1,220p' README.md | tee capstone-evidence\/repository-readme-extract.txt\ncd java\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm the README identifies the repository as intentionally vulnerable\/security-testing-only and that&nbsp;<code>source-commit.txt<\/code>&nbsp;contains a real Git commit SHA.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The training source is pinned to a specific revision and no application\/exploit payload has been executed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 2 &#8211; Identify Direct Dependencies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inspect the Maven manifest and extract declared dependencies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>cp pom.xml ..\/capstone-evidence\/before\/pom.xml\ncat pom.xml | tee ..\/capstone-evidence\/before\/pom-reviewed.xml\n\nmvn -B dependency:list -DexcludeTransitive=true \\\n  | tee ..\/capstone-evidence\/before\/direct-dependencies.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Look for the exact group, artifact, and version of every direct dependency. At the 2026-10-03 research snapshot, this repository intentionally declared vulnerable Java packages including Log4j, Jackson Databind, and Commons IO. Always trust the POM you actually cloned over a cached tutorial description.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can identify every direct Maven dependency and its version from the real cloned revision.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 3 &#8211; Generate and Read the Dependency Tree<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn -B dependency:tree \\\n  | tee ..\/capstone-evidence\/before\/dependency-tree.txt\n\nmvn -B dependency:tree -Dverbose \\\n  | tee ..\/capstone-evidence\/before\/dependency-tree-verbose.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Mark each direct dependency and any transitive dependencies. Record which parent introduces each transitive package.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create&nbsp;<code>..\/capstone-evidence\/investigation\/dependency-paths.md<\/code>&nbsp;with at least three examples in this form:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Application\n  -&gt; direct dependency\n     -&gt; transitive dependency\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If a dependency has no transitive child in this exact POM, say so rather than inventing one.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can explain the difference between a package listed directly in&nbsp;<code>pom.xml<\/code>&nbsp;and one resolved transitively.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 4 &#8211; Resolve and Copy the Actual Dependency Artifacts<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>rm -rf target\/dependency\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\nfind target\/dependency -maxdepth 1 -type f -print | sort \\\n  | tee ..\/capstone-evidence\/before\/resolved-artifacts.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The files in&nbsp;<code>target\/dependency<\/code>&nbsp;are the actual JARs used for SBOM\/license\/integrity exercises. Compare their versions with the dependency tree.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The resolved artifacts are present locally and match the package-manager view.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 5 &#8211; Run the Initial OWASP Dependency-Check Scan<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The first NVD data population can take substantial time. An NVD API key helps but is not a substitute for an organizational NVD mirror\/cache strategy in CI. Do not repeatedly delete the local Dependency-Check data cache between exercises.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>NVD_ARGS=()\nif &#91; -n \"${NVD_API_KEY:-}\" ]; then\n  NVD_ARGS+=(\"-DnvdApiKeyEnvironmentVariable=NVD_API_KEY\")\nfi\n\nmvn -B org.owasp:dependency-check-maven:13.0.0:check \\\n  -Dformat=ALL \\\n  -Dodc.outputDirectory=..\/capstone-evidence\/before\/dependency-check \\\n  -DfailBuildOnCVSS=11 \\\n  \"${NVD_ARGS&#91;@]}\"\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udccb Expected Output<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Do not expect exact vulnerability counts from this manual. A successful non-gating scan should create multiple reports, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>..\/capstone-evidence\/before\/dependency-check\/dependency-check-report.html\n..\/capstone-evidence\/before\/dependency-check\/dependency-check-report.json\n..\/capstone-evidence\/before\/dependency-check\/dependency-check-report.xml\n..\/capstone-evidence\/before\/dependency-check\/dependency-check-report.csv\n..\/capstone-evidence\/before\/dependency-check\/dependency-check-report.sarif\n...\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">List what your run actually generated:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>find ..\/capstone-evidence\/before\/dependency-check -maxdepth 1 -type f -print | sort\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open the HTML report in a browser and identify dependencies with findings. Verify the project\/dependency names instead of scanning only the CVE column.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dependency-Check completed, current vulnerability data was used, and machine-readable plus human-readable evidence exists.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 6 &#8211; Extract Real Findings from JSON<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>REPORT=..\/capstone-evidence\/before\/dependency-check\/dependency-check-report.json\n\njq -r '\n  .dependencies&#91;] as $d\n  | ($d.vulnerabilities \/\/ &#91;])&#91;]\n  | &#91;$d.fileName,\n     .name,\n     (.severity \/\/ \"UNSCORED\"),\n     (.cvssv3.baseScore \/\/ .cvssv4.baseScore \/\/ \"\"),\n     ((.cwes \/\/ &#91;]) | join(\",\"))]\n  | @tsv' \"$REPORT\" \\\n  | tee ..\/capstone-evidence\/before\/findings.tsv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If a field is absent in the current report schema, inspect the JSON rather than guessing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>jq '.dependencies&#91;] | select(.vulnerabilities != null) | .vulnerabilities&#91;0]' \"$REPORT\" | head -n 120\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Every CVE, score, severity, and CWE recorded in your notes must come from generated evidence or an authoritative source.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>findings.tsv<\/code>&nbsp;contains real scan findings from your run, not copied example counts.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 7 &#8211; Investigate a Real CVE<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use a real CVE that appears in your report. If&nbsp;<code>CVE-2021-44228<\/code>&nbsp;is present for the pinned training revision, it is a useful investigation target.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>CVE=CVE-2021-44228\n\ngrep -F \"$CVE\" ..\/capstone-evidence\/before\/findings.tsv \\\n  | tee ..\/capstone-evidence\/investigation\/${CVE}-dependency-check.txt\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If your cloned revision no longer contains that finding, choose a CVE that actually appears in&nbsp;<code>findings.tsv<\/code>&nbsp;and update&nbsp;<code>CVE<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Record dependency\/version, direct\/transitive path, severity, score, and references from the HTML\/JSON report.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You are investigating a CVE produced by your actual scan.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 8 &#8211; Verify CVE\/CWE\/CVSS\/CPE in NVD<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsS \\\n  \"https:\/\/services.nvd.nist.gov\/rest\/json\/cves\/2.0?cveId=${CVE}\" \\\n  -o \"..\/capstone-evidence\/investigation\/${CVE}-nvd.json\"\n\njq '.vulnerabilities&#91;0].cve |\n  {id,\n   sourceIdentifier,\n   published,\n   lastModified,\n   metrics,\n   weaknesses,\n   configurations,\n   references}' \\\n  \"..\/capstone-evidence\/investigation\/${CVE}-nvd.json\" \\\n  &gt; \"..\/capstone-evidence\/investigation\/${CVE}-nvd-summary.json\"\n\njq . \"..\/capstone-evidence\/investigation\/${CVE}-nvd-summary.json\" | head -n 220\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Identify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CVE ID\nCWE(s), when NVD provides them\nCVSS version\/score\/vector\nCPE configuration\/ranges\npublished\/last-modified dates\nreferences\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do not assume every CVE has every field or that every data provider agrees on every metric.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can trace the scanner finding to current authoritative NVD metadata and explain dependency -&gt; CPE identification -&gt; CVE association.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 9 &#8211; Fetch Current EPSS<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsS \"https:\/\/api.first.org\/data\/v1\/epss?cve=${CVE}\" \\\n  -o \"..\/capstone-evidence\/investigation\/${CVE}-epss.json\"\n\njq '.data&#91;] | {cve, epss, percentile, date}' \\\n  \"..\/capstone-evidence\/investigation\/${CVE}-epss.json\"\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Record the EPSS score, percentile, and date exactly as returned at execution time. Do not use a stale value from slides or a prior lab run.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The finding now has a current exploitation-probability signal alongside CVSS.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 10 &#8211; Check CISA KEV<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsS \\\n  https:\/\/www.cisa.gov\/sites\/default\/files\/feeds\/known_exploited_vulnerabilities.json \\\n  -o ..\/capstone-evidence\/investigation\/cisa-kev.json\n\njq --arg cve \"$CVE\" '\n  .vulnerabilities&#91;]\n  | select(.cveID == $cve)\n  | {cveID,\n     vendorProject,\n     product,\n     vulnerabilityName,\n     dateAdded,\n     dueDate,\n     requiredAction,\n     knownRansomwareCampaignUse}' \\\n  ..\/capstone-evidence\/investigation\/cisa-kev.json \\\n  | tee \"..\/capstone-evidence\/investigation\/${CVE}-kev.json\"\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An empty result means the CVE was not found in the current downloaded KEV catalog at that moment. A returned object means CISA currently lists it as known exploited. Preserve the catalog file\/date with the evidence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">KEV status is based on the official current catalog, not memory.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 11 &#8211; Identify Outdated Dependencies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn -B -Dstyle.color=never \\\n  org.codehaus.mojo:versions-maven-plugin:2.22.0:display-dependency-updates \\\n  | tee ..\/capstone-evidence\/before\/dependency-updates.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For each direct dependency, compare installed version with the versions currently offered by Maven repositories. Review release notes\/vendor support before selecting an upgrade. &#8220;Latest&#8221; and &#8220;compatible\/supported&#8221; are not always the same thing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create&nbsp;<code>..\/capstone-evidence\/investigation\/outdated-review.tsv<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package\tcurrent_version\tcandidate_version\tmaintenance_status\trelease_notes_reviewed\tdecision\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Populate it from actual command\/source evidence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can distinguish a known-vulnerable package from a merely old package and can identify maintenance risk that CVE scanning alone may miss.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 12 &#8211; Review License Information<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>syft scan dir:target\/dependency \\\n  -o cyclonedx-json=..\/capstone-evidence\/before\/sbom.cdx.json \\\n  -o spdx-json=..\/capstone-evidence\/before\/sbom.spdx.json\n\njq -r '\n  .components&#91;]\n  | &#91;.group,\n     .name,\n     .version,\n     ((.licenses \/\/ &#91;])\n       | map(.license.id \/\/ .license.name \/\/ .expression \/\/ \"UNKNOWN\")\n       | join(\",\"))]\n  | @tsv' ..\/capstone-evidence\/before\/sbom.cdx.json \\\n  | tee ..\/capstone-evidence\/before\/licenses.tsv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the generated CycloneDX representation differs, inspect one component and adapt the query to the real document:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>jq '.components&#91;0]' ..\/capstone-evidence\/before\/sbom.cdx.json\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Record detected licenses and unknowns. Technical detection is not legal advice. Escalate unclear or incompatible licensing to the organization&#8217;s legal\/compliance process.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You have machine-generated license evidence tied to the same resolved dependency set.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 13 &#8211; Generate and Inspect CycloneDX SBOM<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>jq '{bomFormat, specVersion, serialNumber, metadata, componentCount: (.components | length)}' \\\n  ..\/capstone-evidence\/before\/sbom.cdx.json\n\njq -r '.components&#91;] | &#91;.type, .group, .name, .version, (.purl \/\/ \"\")] | @tsv' \\\n  ..\/capstone-evidence\/before\/sbom.cdx.json \\\n  | tee ..\/capstone-evidence\/before\/cyclonedx-components.tsv\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm CycloneDX document format\/spec version and the component PURLs\/versions that represent the build inventory.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can locate a vulnerable component and its exact version\/PURL in the CycloneDX SBOM.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 14 &#8211; Generate and Inspect SPDX SBOM<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The SPDX file was generated in Step 12.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>jq '{spdxVersion, dataLicense, SPDXID, name, documentNamespace}' \\\n  ..\/capstone-evidence\/before\/sbom.spdx.json\n\njq -r '\n  .packages&#91;]?\n  | &#91;.name,\n     (.versionInfo \/\/ \"\"),\n     (.licenseDeclared \/\/ \"\"),\n     (.licenseConcluded \/\/ \"\")]\n  | @tsv' ..\/capstone-evidence\/before\/sbom.spdx.json \\\n  | tee ..\/capstone-evidence\/before\/spdx-packages.tsv\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Compare at least three packages between CycloneDX and SPDX. Focus on package identity\/version\/license representation rather than declaring one format &#8220;better.&#8221;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can read package\/version\/license data from both standards.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 15 &#8211; Create a Prioritization Record<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; ..\/capstone-evidence\/investigation\/prioritization.tsv &lt;&lt;'TSV'\nCVE\tcomponent\tversion\tCVSS\tCVSS_vector\tEPSS\tEPSS_date\tKEV\tdirect_or_transitive\tusage\tenvironment_exposure\tbusiness_context\tfix_available\tdecision\tevidence\nTSV\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Fill at least three real rows from your evidence. Keep CVSS, EPSS, and KEV separate. Add dependency usage and environment\/business context manually from what you actually know.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No invented combined risk score should appear.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Each remediation decision is traceable to evidence and context.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 16 &#8211; Remediate the Vulnerable Dependencies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The repository README may contain old &#8220;safe version&#8221; suggestions. Do not assume those are the best versions in October 2026. Use current package-manager\/vendor information and test compatibility.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">First preserve the original POM and review available releases:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cp pom.xml ..\/capstone-evidence\/before\/pom-pre-remediation.xml\n\nmvn -B -Dstyle.color=never \\\n  org.codehaus.mojo:versions-maven-plugin:2.22.0:display-dependency-updates \\\n  | tee ..\/capstone-evidence\/before\/dependency-updates-review.txt\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For this isolated training project, update release dependencies to the latest releases Maven currently resolves:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mvn -B \\\n  org.codehaus.mojo:versions-maven-plugin:2.22.0:use-latest-releases\n\ngit diff -- pom.xml \\\n  | tee ..\/capstone-evidence\/after\/pom-remediation.diff\ncp pom.xml ..\/capstone-evidence\/after\/pom.xml\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Review the changed versions before proceeding:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -nE '&lt;artifactId&gt;|&lt;version&gt;' pom.xml \\\n  | tee ..\/capstone-evidence\/after\/dependency-version-review.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Do not equate &#8220;automatically changed&#8221; with &#8220;approved.&#8221; In a real application, run unit\/integration\/regression tests and review breaking changes. For this SCA capstone, the objective is to replace intentionally vulnerable dependencies with currently resolved releases and prove the vulnerability result changed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The POM diff contains real dependency version changes selected from current Maven repository data.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 17 &#8211; Re-resolve, Rebuild the Inventory, and Re-scan<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>rm -rf target\/dependency\nmvn -B dependency:tree \\\n  | tee ..\/capstone-evidence\/after\/dependency-tree.txt\nmvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\n\nmvn -B org.owasp:dependency-check-maven:13.0.0:check \\\n  -Dformat=ALL \\\n  -Dodc.outputDirectory=..\/capstone-evidence\/after\/dependency-check \\\n  -DfailBuildOnCVSS=11 \\\n  \"${NVD_ARGS&#91;@]}\"\n\nsyft scan dir:target\/dependency \\\n  -o cyclonedx-json=..\/capstone-evidence\/after\/sbom.cdx.json \\\n  -o spdx-json=..\/capstone-evidence\/after\/sbom.spdx.json\n\nmvn -B -Dstyle.color=never \\\n  org.codehaus.mojo:versions-maven-plugin:2.22.0:display-dependency-updates \\\n  | tee ..\/capstone-evidence\/after\/dependency-updates.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm the old vulnerable package versions no longer appear in the after dependency tree\/SBOM unless another dependency still introduces them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Fresh Dependency-Check and SBOM evidence exists for the remediated dependency set.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 18 &#8211; Measure Before vs After from Real Reports<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a small metrics helper. It intentionally does not invent an &#8220;outdated&#8221; count because Maven&#8217;s text update output can vary; record that count only after reviewing the actual update reports.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; ..\/capstone-evidence\/final\/report-metrics.sh &lt;&lt;'SCRIPT'\n<em>#!\/usr\/bin\/env bash<\/em>\nset -euo pipefail\n\nreport=\"$1\"\n\njq -r '\n  def vulns: &#91;.dependencies&#91;].vulnerabilities&#91;]?];\n  &#91;\n    (.dependencies | length),\n    (vulns | length),\n    (&#91;vulns&#91;] | select((.severity \/\/ \"\") == \"CRITICAL\")] | length),\n    (&#91;vulns&#91;] | select((.severity \/\/ \"\") == \"HIGH\")] | length),\n    (&#91;vulns&#91;] | select((.severity \/\/ \"\") == \"MEDIUM\")] | length),\n    (&#91;vulns&#91;] | select((.severity \/\/ \"\") == \"LOW\")] | length)\n  ] | @tsv' \"$report\"\nSCRIPT\nchmod +x ..\/capstone-evidence\/final\/report-metrics.sh\n\n..\/capstone-evidence\/final\/report-metrics.sh \\\n  ..\/capstone-evidence\/before\/dependency-check\/dependency-check-report.json \\\n  | tee ..\/capstone-evidence\/final\/metrics-before.tsv\n\n..\/capstone-evidence\/final\/report-metrics.sh \\\n  ..\/capstone-evidence\/after\/dependency-check\/dependency-check-report.json \\\n  | tee ..\/capstone-evidence\/final\/metrics-after.tsv\n\nprintf '%s\\n' 'dependencies vulnerabilities critical high medium low'\nprintf 'before: '; cat ..\/capstone-evidence\/final\/metrics-before.tsv\nprintf 'after:  '; cat ..\/capstone-evidence\/final\/metrics-after.tsv\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open both HTML reports and validate the calculated counts. Record any unscored\/unknown-severity finding separately if present.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before\/after numbers come from the generated reports on your machine.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 19 &#8211; Fill the Required Before vs After Table<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not pre-fill this table with example numbers. Copy the values from Step 18 and your actual update\/suppression review.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Metric<\/th><th class=\"has-text-align-right\" data-align=\"right\">Before Remediation<\/th><th class=\"has-text-align-right\" data-align=\"right\">After Remediation<\/th><\/tr><\/thead><tbody><tr><td>Dependencies<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><\/tr><tr><td>Vulnerabilities<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><\/tr><tr><td>Critical<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><\/tr><tr><td>High<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><\/tr><tr><td>Medium<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><\/tr><tr><td>Low<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;measured&gt;<\/code><\/td><\/tr><tr><td>Outdated dependencies<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;count from actual dependency-updates review&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;count from actual dependency-updates review&gt;<\/code><\/td><\/tr><tr><td>Suppressed findings<\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;actual count; 0 if none&gt;<\/code><\/td><td class=\"has-text-align-right\" data-align=\"right\"><code>&lt;actual count; 0 if none&gt;<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Save the completed table as&nbsp;<code>..\/capstone-evidence\/final\/before-after.md<\/code>. Under it, list every changed dependency version and which finding(s) disappeared, remained, or changed after remediation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No number in the final table is fabricated or copied from the repository README.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 20 &#8211; Configure and Test a Security Gate<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following&nbsp;<strong>CVSS 7.0 threshold is a lab policy example<\/strong>, not a universal recommendation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>set +e\nmvn -B org.owasp:dependency-check-maven:13.0.0:check \\\n  -Dformat=HTML,JSON,SARIF \\\n  -Dodc.outputDirectory=..\/capstone-evidence\/final\/gate \\\n  -DfailBuildOnCVSS=7.0 \\\n  \"${NVD_ARGS&#91;@]}\"\nGATE_RC=$?\nset -e\n\nprintf 'Dependency-Check gate exit code: %s\\n' \"$GATE_RC\" \\\n  | tee ..\/capstone-evidence\/final\/gate-result.txt\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Interpret the result from the current findings:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>exit code 0     -&gt; no finding violated this configured threshold\nnon-zero        -&gt; one or more findings violated the policy or the scan itself failed\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Read the console\/report before assuming every non-zero exit is a vulnerability gate; operational failures can also make a build fail.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\uddea Exercise<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If the gate still fails for a real finding, investigate and remediate it or document a time-bounded, reviewed exception\/suppression only when technically justified. Re-run until the final policy result is understood.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can demonstrate a deterministic pass\/fail policy based on real scan output and distinguish remediation from suppression.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 21 &#8211; Integrate SCA into GitHub Actions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create the workflow from the repository root, not the&nbsp;<code>java<\/code>&nbsp;directory:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ..\nmkdir -p .github\/workflows\n\ncat &gt; .github\/workflows\/sca.yml &lt;&lt;'YAML'\nname: SCA Security\n\non:\n  push:\n  pull_request:\n  workflow_dispatch:\n\npermissions:\n  contents: read\n  security-events: write\n\njobs:\n  sca:\n    runs-on: ubuntu-latest\n    defaults:\n      run:\n        working-directory: java\n    env:\n      NVD_API_KEY: ${{ secrets.NVD_API_KEY }}\n\n    steps:\n      - name: Checkout\n        uses: actions\/checkout@v6\n\n      - name: Set up Java\n        uses: actions\/setup-java@v4\n        with:\n          distribution: temurin\n          java-version: '17'\n          cache: maven\n\n      - name: Resolve dependencies and capture tree\n        run: |\n          mkdir -p target\/security-evidence\n          mvn -B dependency:tree | tee target\/security-evidence\/dependency-tree.txt\n          mvn -B dependency:copy-dependencies -DoutputDirectory=target\/dependency\n\n      - name: OWASP Dependency-Check\n        shell: bash\n        run: |\n          ARGS=()\n          if &#91; -n \"${NVD_API_KEY:-}\" ]; then\n            ARGS+=(\"-DnvdApiKeyEnvironmentVariable=NVD_API_KEY\")\n          fi\n\n          mvn -B org.owasp:dependency-check-maven:13.0.0:check \\\n            -Dformat=HTML,JSON,SARIF \\\n            -Dodc.outputDirectory=target\/security-evidence\/dependency-check \\\n            -DfailBuildOnCVSS=7.0 \\\n            \"${ARGS&#91;@]}\"\n\n      - name: Install Syft\n        id: syft\n        uses: anchore\/sbom-action\/download-syft@v0\n        with:\n          syft-version: v1.52.0\n\n      - name: Generate CycloneDX SBOM\n        run: |\n          ${{ steps.syft.outputs.cmd }} scan dir:target\/dependency \\\n            -o cyclonedx-json=target\/security-evidence\/sbom.cdx.json\n\n      - name: Upload SCA evidence\n        if: always()\n        uses: actions\/upload-artifact@v4\n        with:\n          name: sca-security-evidence\n          path: |\n            java\/target\/security-evidence\n          if-no-files-found: warn\n\n      - name: Upload SARIF to GitHub code scanning\n        if: always()\n        uses: github\/codeql-action\/upload-sarif@v4\n        with:\n          sarif_file: java\/target\/security-evidence\/dependency-check\/dependency-check-report.sarif\nYAML\n\ncp .github\/workflows\/sca.yml capstone-evidence\/ci\/sca.yml\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udc68\u200d\ud83c\udfeb Trainer Note<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>actions\/checkout@v6<\/code>,&nbsp;<code>actions\/setup-java@v4<\/code>,&nbsp;<code>actions\/upload-artifact@v4<\/code>, and&nbsp;<code>github\/codeql-action\/upload-sarif@v4<\/code>&nbsp;are the verified current major action lines used in this lab snapshot. For hardened production supply-chain controls, organizations may pin third-party\/action dependencies to reviewed full commit SHAs and manage update automation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Push this workflow only to an authorized training repository. If SARIF upload is restricted by repository plan\/settings or pull-request permissions, preserve SARIF as the uploaded workflow artifact and document the platform limitation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A push\/PR runs dependency resolution -&gt; Dependency-Check -&gt; security gate -&gt; SBOM -&gt; evidence upload, and the workflow result reflects actual findings.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Step 22 &#8211; Generate the Final Security Evidence Package<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udda5\ufe0f Command<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p capstone-evidence\/final\/package\n\ncp capstone-evidence\/source-commit.txt capstone-evidence\/final\/package\/\ncp capstone-evidence\/final\/before-after.md capstone-evidence\/final\/package\/ 2&gt;\/dev\/null || true\ncp capstone-evidence\/investigation\/prioritization.tsv capstone-evidence\/final\/package\/ 2&gt;\/dev\/null || true\ncp capstone-evidence\/ci\/sca.yml capstone-evidence\/final\/package\/\ncp capstone-evidence\/before\/dependency-tree.txt capstone-evidence\/final\/package\/dependency-tree-before.txt\ncp capstone-evidence\/after\/dependency-tree.txt capstone-evidence\/final\/package\/dependency-tree-after.txt\ncp capstone-evidence\/before\/sbom.cdx.json capstone-evidence\/final\/package\/sbom-before.cdx.json\ncp capstone-evidence\/after\/sbom.cdx.json capstone-evidence\/final\/package\/sbom-after.cdx.json\ncp capstone-evidence\/before\/sbom.spdx.json capstone-evidence\/final\/package\/sbom-before.spdx.json\ncp capstone-evidence\/after\/sbom.spdx.json capstone-evidence\/final\/package\/sbom-after.spdx.json\ncp capstone-evidence\/before\/dependency-check\/dependency-check-report.json capstone-evidence\/final\/package\/dependency-check-before.json\ncp capstone-evidence\/after\/dependency-check\/dependency-check-report.json capstone-evidence\/final\/package\/dependency-check-after.json\ncp capstone-evidence\/before\/dependency-check\/dependency-check-report.html capstone-evidence\/final\/package\/dependency-check-before.html\ncp capstone-evidence\/after\/dependency-check\/dependency-check-report.html capstone-evidence\/final\/package\/dependency-check-after.html\ncp capstone-evidence\/final\/gate-result.txt capstone-evidence\/final\/package\/ 2&gt;\/dev\/null || true\n\nfind capstone-evidence\/final\/package -type f -print | sort \\\n  | tee capstone-evidence\/final\/package\/manifest.txt\n\nif command -v sha256sum &gt;\/dev\/null 2&gt;&amp;1; then\n  (cd capstone-evidence\/final\/package &amp;&amp; sha256sum * &gt; SHA256SUMS.txt)\nelse\n  (cd capstone-evidence\/final\/package &amp;&amp; shasum -a 256 * &gt; SHA256SUMS.txt)\nfi\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcbb Student Action<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add&nbsp;<code>capstone-evidence\/final\/package\/final-report.md<\/code>&nbsp;with these sections:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>1. Source repository + pinned commit\n2. Dependency inventory summary\n3. Initial vulnerabilities\n4. CVE\/CWE\/CVSS\/CPE investigation\n5. NVD verification\n6. EPSS result\/date\n7. KEV result\/date\n8. Outdated dependency review\n9. License observations\n10. CycloneDX\/SPDX observations\n11. Remediation changes\n12. Before vs after table\n13. Security gate result\n14. Suppressions\/exceptions, if any\n15. CI\/CD evidence\n16. Remaining risk and next actions\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd0d Check<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Every factual number must point to a generated file. Every live-intelligence value should include retrieval date. Every exception should have owner\/reason\/expiry. Every remediation should have before\/after dependency identity.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Success Criteria<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The final evidence package can be reviewed by a developer, AppSec engineer, DevOps engineer, or auditor without requiring you to verbally reconstruct what happened.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Capstone Completion Checklist<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A student is complete only when all applicable boxes can be checked from actual evidence:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] Cloned a real GitHub training project and recorded the exact commit.<\/li>\n\n\n\n<li>[ ] Identified direct dependencies.<\/li>\n\n\n\n<li>[ ] Generated and interpreted the dependency tree.<\/li>\n\n\n\n<li>[ ] Ran OWASP Dependency-Check 13.0.0.<\/li>\n\n\n\n<li>[ ] Generated HTML and machine-readable reports.<\/li>\n\n\n\n<li>[ ] Identified real CVEs from the scan.<\/li>\n\n\n\n<li>[ ] Reviewed CVSS severity\/vector.<\/li>\n\n\n\n<li>[ ] Reviewed CWE where available.<\/li>\n\n\n\n<li>[ ] Reviewed CPE\/configuration evidence where available.<\/li>\n\n\n\n<li>[ ] Verified selected CVEs against NVD API 2.0.<\/li>\n\n\n\n<li>[ ] Retrieved current EPSS values from FIRST.<\/li>\n\n\n\n<li>[ ] Checked selected CVEs against current CISA KEV.<\/li>\n\n\n\n<li>[ ] Identified outdated dependencies with Versions Maven Plugin 2.22.0.<\/li>\n\n\n\n<li>[ ] Reviewed dependency licenses.<\/li>\n\n\n\n<li>[ ] Generated CycloneDX SBOM.<\/li>\n\n\n\n<li>[ ] Generated SPDX SBOM.<\/li>\n\n\n\n<li>[ ] Remediated vulnerable dependency versions.<\/li>\n\n\n\n<li>[ ] Re-ran Dependency-Check.<\/li>\n\n\n\n<li>[ ] Regenerated SBOMs.<\/li>\n\n\n\n<li>[ ] Compared measured before\/after results.<\/li>\n\n\n\n<li>[ ] Configured and tested a security gate.<\/li>\n\n\n\n<li>[ ] Integrated SCA into GitHub Actions.<\/li>\n\n\n\n<li>[ ] Preserved security evidence and hashes.<\/li>\n\n\n\n<li>[ ] Documented final risk\/decisions without fabricated metrics.<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Troubleshooting Guide<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Dependency-Check First Run Is Very Slow<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Cause: initial NVD data population can be large.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Actions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>1. Keep the local Dependency-Check data cache between runs.\n2. Use an NVD API key according to your organization's secret-management policy.\n3. For CI\/enterprise use, follow OWASP guidance for an internal NVD mirror\/cache strategy.\n4. Do not launch many cold scanners against public NVD simultaneously.\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">NVD API Rate Limit \/ HTTP Errors<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not add blind high-frequency retries. Confirm network access, API key handling, proxy configuration, NVD service status, and update\/mirroring strategy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>failBuildOnCVSS<\/code>&nbsp;Makes the Lab Stop Before Reports Are Reviewed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use a non-gating threshold such as&nbsp;<code>11<\/code>&nbsp;during discovery, then run a second explicit gate with the policy threshold. Never leave&nbsp;<code>11<\/code>&nbsp;as the real production policy merely because it is convenient for training.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Dependency Has a CVE That Does Not Seem to Match<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the Dependency-Check evidence\/CPE mapping, product\/vendor identity, versions, and authoritative advisory. If it is a genuine false positive, create a narrowly scoped, documented, expiring suppression. Do not suppress a true vulnerable component because the gate is inconvenient.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">JSON Query Fails<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Report schemas evolve. Inspect the real object first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>jq 'keys' dependency-check-report.json\njq '.dependencies&#91;0]' dependency-check-report.json\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then adjust the query to the generated version instead of forcing old field assumptions.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Syft Finds Fewer\/More Components Than Maven<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Compare scan target. Scanning&nbsp;<code>target\/dependency<\/code>&nbsp;inventories resolved JARs; scanning the repository may inventory manifests, source metadata, lock files, and generated artifacts differently. Record what was scanned.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Grype and Dependency-Check Results Differ<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This can be normal. Compare vulnerability sources, component identity, CPE\/PURL matching, package type, database update timestamps, severity source, and suppression\/VEX behavior. Investigate; do not average the scanners.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">GitHub SARIF Upload Fails<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check repository permissions\/settings and whether the workflow context is allowed to write&nbsp;<code>security-events<\/code>. Preserve SARIF with&nbsp;<code>actions\/upload-artifact@v4<\/code>&nbsp;even when code-scanning upload is unavailable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Security Gate Still Fails After Upgrade<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>another vulnerable direct dependency\nold version still present transitively\nmultiple versions resolved\nnew CVEs affecting the upgraded version\nincorrect CPE match \/ false positive\nbuild or update failure rather than gate failure\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use dependency tree plus HTML\/JSON report to trace the exact path.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Trainer Debrief Questions<\/h1>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Which finding changed priority the most after EPSS\/KEV\/context review, and why?<\/li>\n\n\n\n<li>Which dependency was direct versus transitive?<\/li>\n\n\n\n<li>Did any scanner finding require CPE validation?<\/li>\n\n\n\n<li>Did remediation remove the vulnerable version from both dependency tree and SBOM?<\/li>\n\n\n\n<li>What did the security gate enforce, and what did it not prove?<\/li>\n\n\n\n<li>Which supply-chain risks remain even after a clean Dependency-Check scan?<\/li>\n\n\n\n<li>Which evidence would you retain for an audit\/release record?<\/li>\n\n\n\n<li>When would VEX be appropriate, and what evidence would be required?<\/li>\n\n\n\n<li>Why can SCA not be described as true reachability analysis?<\/li>\n\n\n\n<li>How would you make NVD data ingestion reliable at organizational CI scale?<\/li>\n<\/ol>\n\n\n\n<h1 class=\"wp-block-heading\">Final Learning Outcome<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">After completing this manual, the student should be able to move from:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>I do not know what a dependency vulnerability is.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>I can identify application dependencies,\nunderstand direct and transitive dependencies,\nrun OWASP Dependency-Check,\ninterpret CVE\/CVSS\/CPE\/CWE findings,\ninvestigate vulnerabilities,\nuse EPSS and KEV as complementary priority signals,\nreview dependency licenses,\ngenerate and inspect CycloneDX and SPDX SBOMs,\nunderstand dependency confusion, typosquatting, package hijacking and provenance,\nexplain VEX and reachability boundaries,\nremediate vulnerable dependencies,\nconfigure security gates,\nintegrate SCA into CI\/CD,\nand participate in an organization's software supply-chain security process.\n<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Verified Reference Baseline &#8211; 2026-10-03<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The commands and versions in this training guide were checked against current authoritative\/project sources at generation time. Re-validate pinned versions when reusing the guide in the future.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OWASP Dependency-Check<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project\/release\/documentation:\u00a0<a href=\"https:\/\/owasp.org\/www-project-dependency-check\/\">https:\/\/owasp.org\/www-project-dependency-check\/<\/a><\/li>\n\n\n\n<li>GitHub:\u00a0<a href=\"https:\/\/github.com\/dependency-check\/DependencyCheck\">https:\/\/github.com\/dependency-check\/DependencyCheck<\/a><\/li>\n\n\n\n<li>Maven plugin:\u00a0<a href=\"https:\/\/dependency-check.github.io\/DependencyCheck\/dependency-check-maven\/\">https:\/\/dependency-check.github.io\/DependencyCheck\/dependency-check-maven\/<\/a><\/li>\n\n\n\n<li>CLI arguments:\u00a0<a href=\"https:\/\/dependency-check.github.io\/DependencyCheck\/dependency-check-cli\/arguments.html\">https:\/\/dependency-check.github.io\/DependencyCheck\/dependency-check-cli\/arguments.html<\/a><\/li>\n\n\n\n<li>Suppression documentation:\u00a0<a href=\"https:\/\/dependency-check.github.io\/DependencyCheck\/general\/suppression.html\">https:\/\/dependency-check.github.io\/DependencyCheck\/general\/suppression.html<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Verified lab line: Dependency-Check&nbsp;<code>13.0.0<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">NVD \/ NIST<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>NVD:\u00a0<a href=\"https:\/\/nvd.nist.gov\/\">https:\/\/nvd.nist.gov\/<\/a><\/li>\n\n\n\n<li>NVD developer\/API resources:\u00a0<a href=\"https:\/\/nvd.nist.gov\/developers\">https:\/\/nvd.nist.gov\/developers<\/a><\/li>\n\n\n\n<li>CVE API 2.0 base:\u00a0<a href=\"https:\/\/services.nvd.nist.gov\/rest\/json\/cves\/2.0\">https:\/\/services.nvd.nist.gov\/rest\/json\/cves\/2.0<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">EPSS \/ FIRST<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>EPSS:\u00a0<a href=\"https:\/\/www.first.org\/epss\/\">https:\/\/www.first.org\/epss\/<\/a><\/li>\n\n\n\n<li>EPSS API:\u00a0<a href=\"https:\/\/api.first.org\/data\/v1\/epss\">https:\/\/api.first.org\/data\/v1\/epss<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">CISA KEV<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Catalog:\u00a0<a href=\"https:\/\/www.cisa.gov\/known-exploited-vulnerabilities-catalog\">https:\/\/www.cisa.gov\/known-exploited-vulnerabilities-catalog<\/a><\/li>\n\n\n\n<li>JSON feed used by lab:\u00a0<a href=\"https:\/\/www.cisa.gov\/sites\/default\/files\/feeds\/known_exploited_vulnerabilities.json\">https:\/\/www.cisa.gov\/sites\/default\/files\/feeds\/known_exploited_vulnerabilities.json<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">SBOM Standards and Tools<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CycloneDX:\u00a0<a href=\"https:\/\/cyclonedx.org\/\">https:\/\/cyclonedx.org\/<\/a><\/li>\n\n\n\n<li>SPDX:\u00a0<a href=\"https:\/\/spdx.dev\/\">https:\/\/spdx.dev\/<\/a><\/li>\n\n\n\n<li>Syft:\u00a0<a href=\"https:\/\/github.com\/anchore\/syft\">https:\/\/github.com\/anchore\/syft<\/a><\/li>\n\n\n\n<li>Grype:\u00a0<a href=\"https:\/\/github.com\/anchore\/grype\">https:\/\/github.com\/anchore\/grype<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Verified lab snapshots: Syft&nbsp;<code>1.52.0<\/code>; Grype&nbsp;<code>0.119.0<\/code>; CycloneDX current specification family&nbsp;<code>1.7<\/code>; SPDX current specification&nbsp;<code>3.0.1<\/code>&nbsp;at generation time. Generated SPDX output version is determined by the selected Syft output implementation and should be read from the actual file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Maven<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Versions Maven Plugin:\u00a0<a href=\"https:\/\/www.mojohaus.org\/versions\/versions-maven-plugin\/\">https:\/\/www.mojohaus.org\/versions\/versions-maven-plugin\/<\/a><\/li>\n\n\n\n<li>Maven Dependency Plugin:\u00a0<a href=\"https:\/\/maven.apache.org\/plugins\/maven-dependency-plugin\/\">https:\/\/maven.apache.org\/plugins\/maven-dependency-plugin\/<\/a><\/li>\n\n\n\n<li>Maven Install Plugin:\u00a0<a href=\"https:\/\/maven.apache.org\/plugins\/maven-install-plugin\/\">https:\/\/maven.apache.org\/plugins\/maven-install-plugin\/<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Verified lab snapshots: Versions Maven Plugin&nbsp;<code>2.22.0<\/code>; Maven Dependency Plugin&nbsp;<code>3.11.0<\/code>; Maven Install Plugin&nbsp;<code>3.2.0<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">VEX<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>OpenVEX\/vexctl:\u00a0<a href=\"https:\/\/github.com\/openvex\/vexctl\">https:\/\/github.com\/openvex\/vexctl<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Verified lab snapshot: vexctl&nbsp;<code>0.4.4<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">GitHub Actions<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>GitHub Actions docs:\u00a0<a href=\"https:\/\/docs.github.com\/actions\">https:\/\/docs.github.com\/actions<\/a><\/li>\n\n\n\n<li>Artifact attestations:\u00a0<a href=\"https:\/\/docs.github.com\/actions\/security-for-github-actions\/using-artifact-attestations\">https:\/\/docs.github.com\/actions\/security-for-github-actions\/using-artifact-attestations<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Verified current action lines used by this guide include&nbsp;<code>actions\/checkout@v6<\/code>,&nbsp;<code>actions\/setup-java@v4<\/code>,&nbsp;<code>actions\/upload-artifact@v4<\/code>,&nbsp;<code>github\/codeql-action\/upload-sarif@v4<\/code>, and&nbsp;<code>actions\/attest@v4<\/code>. The capstone also uses the official Anchore&nbsp;<code>anchore\/sbom-action\/download-syft@v0<\/code>&nbsp;action and pins Syft itself to&nbsp;<code>v1.52.0<\/code>&nbsp;for repeatability.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Capstone Training Repository<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/hv-oblikas\/vulnerable-demo-app\">https:\/\/github.com\/hv-oblikas\/vulnerable-demo-app<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The repository is intentionally vulnerable and states it is for security testing only. The capstone records&nbsp;<code>git rev-parse HEAD<\/code>&nbsp;so the exact source used by each student is auditable.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Final Quality Assurance Checklist<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] All 37 required topics are present as visible numbered sections.<\/li>\n\n\n\n<li>[ ] Every numbered topic has What You Need to Know, Why It Matters, Lab objective, setup, steps, commands, expected output, checks, exercise, expected result, and key takeaway.<\/li>\n\n\n\n<li>[ ] Fundamental -> basic -> intermediate -> advanced progression is preserved.<\/li>\n\n\n\n<li>[ ] OWASP Dependency-Check remains the central SCA scanner.<\/li>\n\n\n\n<li>[ ] Complementary tools are explicitly identified rather than misattributed to Dependency-Check.<\/li>\n\n\n\n<li>[ ] CVE, CWE, CVSS, CPE, NVD, EPSS, and KEV are all practiced.<\/li>\n\n\n\n<li>[ ] CycloneDX and SPDX SBOMs are generated and inspected.<\/li>\n\n\n\n<li>[ ] License\/compliance workflows are practical and clearly separated from legal advice.<\/li>\n\n\n\n<li>[ ] Dependency confusion, typosquatting, package hijacking, provenance, VEX, reachability, and prioritization are covered safely.<\/li>\n\n\n\n<li>[ ] CI\/CD, gates, suppressions, remediation, and re-scan are demonstrated.<\/li>\n\n\n\n<li>[ ] Report formats and security evidence are generated.<\/li>\n\n\n\n<li>[ ] The capstone uses a real GitHub training project.<\/li>\n\n\n\n<li>[ ] No exploit payload execution is required.<\/li>\n\n\n\n<li>[ ] No vulnerability counts are fabricated.<\/li>\n\n\n\n<li>[ ] Expected-output blocks are explicitly representative where values can change.<\/li>\n\n\n\n<li>[ ] Before\/after metrics must be populated from actual execution.<\/li>\n\n\n\n<li>[ ] Commands and versions were researched against current sources on 2026-10-03.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Complete Hands-On Lab Guide: Fundamentals -&gt; Basic -&gt; Intermediate -&gt; Advanced Generation \/ verification date:&nbsp;2026-10-03Primary scanner:&nbsp;OWASP Dependency-Check 13.0.0Primary build ecosystem:&nbsp;Java + MavenCapstone:&nbsp;real intentionally vulnerable GitHub training repositoryAudience:&nbsp;developers,&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1198","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/comments?post=1198"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1198\/revisions"}],"predecessor-version":[{"id":1199,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1198\/revisions\/1199"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/media?parent=1198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/categories?post=1198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/tags?post=1198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}