{"id":104912,"date":"2025-01-16T21:51:01","date_gmt":"2025-01-16T21:51:01","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=104912"},"modified":"2025-06-27T15:38:39","modified_gmt":"2025-06-27T15:38:39","slug":"using-snyk-for-ci-cd-security-scanning","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/cloud\/security-and-compliance\/using-snyk-for-ci-cd-security-scanning\/","title":{"rendered":"Using Snyk for CI\/CD Security Scanning"},"content":{"rendered":"\n<p>Security is important regardless of your industry, whether it&#8217;s finance, retail, e-commerce, or the broader world of IT. A little security oversight can have catastrophic impacts, leading to loss of money and unauthorized access to classified information.<\/p>\n\n\n\n<p>It takes a lot of work to develop solutions that users trust. Therefore, you need to take security seriously to maintain the good reputation you have worked so hard for. In software delivery, security is as important as it is everywhere else.<\/p>\n\n\n\n<p>Software delivery is part of the <a href=\"https:\/\/www.red-gate.com\/blog\/database-devops\/introducing-a-devops-culture\">DevOps culture<\/a>. When you take extra steps to integrate security, you are practicing <a href=\"https:\/\/www.redhat.com\/en\/topics\/devops\/what-is-devsecops\">DevSecOps<\/a>. DevSecOps is still part of the DevOps culture but with an emphasis on &#8220;security.&#8221;<\/p>\n\n\n\n<p>This article will introduce the concept of security scanning in detail, explain what it entails, how it can be incorporated into the DevOps culture, and explain how Snyk, a popular security tool, fits into security scanning. You\u2019ll also see how to use Snyk in a CI\/CD pipeline.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-what-is-security-scanning\"><a id=\"post-104912-_basih5kptpa7\"><\/a>What is Security Scanning<\/h2>\n\n\n\n<p>Security scanning, also known as \u201c<a href=\"https:\/\/www.balbix.com\/insights\/what-is-vulnerability-scanning\/\">vulnerability scanning<\/a>,\u201d involves analyzing a system to determine whether it is susceptible to attacks. In this case, a system can be a network, hardware, a server, a piece of software, a bunch of code, an entire codebase, an application, or essentially anything that can be exposed to security threats.<\/p>\n\n\n\n<p>It should be taken seriously and conducted regularly to maintain system safety. Systems like servers will benefit from checking for server misconfigurations, weak permissions, unauthorized access, or suspicious activity from specific or ranges of IP addresses. Codebases will benefit from checking for insecure API usage, injection vulnerabilities, hard-coded secrets, XSS, SQL injection, and more.<\/p>\n\n\n\n<p>A significant shift is happening in the Cybersecurity space. If you do not have a plan or proactive measures to ensure your system is protected against Cyber-attacks, you&#8217;re on a dangerous path. Classified information could easily get into the wrong hands, you\u2019ll lose money, and you will experience reputational damage and operational disruptions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-what-does-security-scanning-in-ci-cd-entail\"><a id=\"post-104912-_9siitjs6k5vc\"><\/a>What does Security Scanning in CI\/CD Entail<\/h3>\n\n\n\n<p>Narrowing security scanning into <a href=\"https:\/\/www.red-gate.com\/simple-talk\/devops\/ci-cd\/\">CI\/CD<\/a>, which is a critical aspect of the DevOps culture, entails automatically ensuring the security of applications and infrastructure at every stage of development. Identifying vulnerabilities and addressing them continuously as new code and updates are deployed.<\/p>\n\n\n\n<p>For instance, in the development stage (CI), security scanning will involve running tests, checking for vulnerabilities, analyzing dependencies, and automatically checking for security best practices. While in the deployment stage (CD), security scanning will involve validating infrastructure as code (IaC) configurations, scanning container images, and checking that the deployment environment is securely configured and that it adheres to compliance standards.<\/p>\n\n\n\n<p>You\u2019ll need to use tools that\u2019ll help you detect security issues during different stages of your CI\/CD pipeline, such as during builds, before deployment, and on pull requests for cases where sensitive changes (new dependencies, configurations, etc) are introduced from contributors.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-what-is-snyk\"><a id=\"post-104912-_gsgreuv48p\"><\/a>What is Snyk<\/h3>\n\n\n\n<p><a href=\"https:\/\/snyk.io\/\">Synk<\/a> is a security tool that helps you identify and fix vulnerabilities in your code. It serves as an assistant so that you can focus on building the core functionalities while it seamlessly handles the security aspect. Synk has a free version, as well as paid for different use cases, which you can see on <a href=\"https:\/\/snyk.io\/plans\/\">their pricing page<\/a>.<\/p>\n\n\n\n<p>Snyk is categorized into Snyk code, Snyk open source, Snyk container, Snyk IaC, and Snyk AppRisk. Each of these categories works for specific use cases and does the following:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li><strong>Snyk open source and Snyk code<\/strong>:<a href=\"https:\/\/snyk.io\/product\/open-source-security-management\/\"> Snyk open source<\/a> checks open source libraries and dependencies for known vulnerabilities<a href=\"https:\/\/snyk.io\/product\/snyk-code\/\">. Snyk code<\/a> scans custom code and functions for security issues. You can grant Snyk access to your Git repository, whether it&#8217;s on GitHub, GitLab, or Bitbucket, to scan through; if it finds any security issue, it&#8217;ll create a pull request to fix it, which you can then review and merge if you choose to.<\/li>\n\n\n\n<li><strong>Snyk container<\/strong>:<a href=\"https:\/\/snyk.io\/product\/container-vulnerability-management\/\"> Snyk container<\/a> is for Snyk&#8217;s container registry integrations. It features a complementary tool called<a href=\"https:\/\/docs.snyk.io\/snyk-cli\/scan-and-maintain-projects-using-the-cli\/snyk-cli-for-snyk-container\"> Snyk CLI<\/a> that you can use to scan container images for vulnerabilities before you deploy them. It also features source code management (SCM), whereby Snyk automatically detects Dockerfiles stored in Git repositories like GitHub, GitLab, or Bitbucket, scans the base image for vulnerabilities using Snyk open source, and recommends a secure or less vulnerable version.<\/li>\n\n\n\n<li><strong>Snyk IaC<\/strong>: For infrastructure engineers who provision cloud resources through code,<a href=\"https:\/\/snyk.io\/product\/infrastructure-as-code-security\/\"> Snyk IaC<\/a> can identify and fix misconfigurations in infrastructure code. You can have Snyk scan infrastructure code within Terraform, CloudFormation, Helm charts, and ARM templates.<\/li>\n\n\n\n<li><strong>Snyk AppRisk<\/strong>: This category is for application security (AppSec) teams that want to manage and reduce application risk at scale.<a href=\"https:\/\/snyk.io\/product\/snyk-apprisk\/\"> Snyk AppRisk<\/a>, an application security posture management (ASPM) tool, provides insights into runtime behavior and spots application loopholes that attackers can exploit.<\/li>\n<\/ul>\n<\/div>\n\n\n<p>The IDE or text editor you use doesn&#8217;t matter; Snyk can be integrated into widely used IDEs and text editors like Vscode and Pycharm to provide real-time security checks and feedback directly in your development environment. Snyk can be used within CI\/CD platforms like GitHub actions, Bitbucket pipelines, Circle CI, Travis CI, GitLab CI, Jenkins, and<a href=\"https:\/\/docs.snyk.io\/scm-ide-and-ci-cd-integrations\/snyk-ci-cd-integrations\"> many others<\/a> to automate security checks as part of your development lifecycle to help you catch and fix security issues early and reduce the risk of vulnerabilities making it to production.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-performed-security-scanning-without-snyk\"><a id=\"post-104912-_46r8yj92wx91\"><\/a>Performed security scanning without Snyk<\/h3>\n\n\n\n<p>I have performed security scanning without Snyk, using <a href=\"https:\/\/docs.npmjs.com\/cli\/v9\/commands\/npm-audit\"><em>npm audit<\/em><\/a> (a command that scans project dependencies), and it was tedious. With <em>the npm audit, <\/em>I was able to generate a vulnerability report for my project and view their severity levels.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"859\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-1.png\" alt=\"\" class=\"wp-image-104913\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Checking for vulnerabilities with npm audit<\/strong><\/p>\n\n\n\n<p>Using the <code>npm audit fix<\/code> command, I was able to find and fix dependency vulnerabilities by upgrading to more secure ones, as recommended by the <code>npm audit<\/code> command.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1090\" height=\"316\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-2.png\" alt=\"\" class=\"wp-image-104914\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Fixing vulnerabilities with <em>npm audit fix<\/em><\/strong><\/p>\n\n\n\n<p>While the <code>npm audit<\/code> command helped, I just couldn\u2019t do enough; <code>npm audit<\/code> only works for Node.js projects, which use <a href=\"https:\/\/www.npmjs.com\/\">npm<\/a> as their package manager. I also couldn\u2019t check my code for patterns that could cause security issues. And, in an era where programmers need to diversify when it comes to programming languages, <code>npm audit<\/code> isn&#8217;t language agnostic, which is a feature that contributed to its limitation.<\/p>\n\n\n\n<p>Suppose I&#8217;m working on a Python, Java, Ruby, C++ project or any other programming language. In that case, I need to incorporate separate tools for vulnerability scanning and security checks. For instance, in a Python project, I could use <a href=\"https:\/\/pypi.org\/project\/pip-audit\/\">pip-audit<\/a>, for a Ruby project I could use <a href=\"https:\/\/rubygems.org\/gems\/bundle-audit\/versions\/0.1.0?locale=en\">bundle-audit<\/a>, and so on.<\/p>\n\n\n\n<p>These separate tools lack language-agnostic features, making managing security across diverse projects complex. Therefore, I don&#8217;t recommend using a language-specific tool for security scanning, but instead a robust, feature-rich, and sophisticated tool that integrates seamlessly with diverse ecosystems. Something that doesn&#8217;t just scan dependencies but can also scan custom code, that is, the one you wrote yourself.<\/p>\n\n\n\n<p>Snyk supports popular programming languages like Python, JavaScript, Elixir, Rust, TypeScript, Dart\/Flutter, and Go. The official documentation lists <a href=\"https:\/\/docs.snyk.io\/supported-languages-package-managers-and-frameworks\">supported languages<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-performing-security-scanning-with-snyk\"><a id=\"post-104912-_yfkqv0gbdq0n\"><\/a>Performing security scanning with Snyk<\/h2>\n\n\n\n<p>The following sections will walk you through Snyk and how to use it to implement security scanning on a GitHub actions CI\/CD pipeline. You&#8217;ll use the Snyk container to scan an Nginx image, Synk open source to scan open source libraries for a Django application, and Snyk code to scan the same Django application. This tutorial&#8217;s Django project is managed using Poetry version 1.8.5.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-prerequisites\"><a id=\"post-104912-_5xm09t3x3nse\"><\/a>Prerequisites<\/h3>\n\n\n\n<p>To follow along, you are required to have the following in place:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>A text editor. This tutorial uses <a href=\"https:\/\/code.visualstudio.com\/\">Visual Studio code<\/a>.<\/li>\n\n\n\n<li>Snyk<a href=\"https:\/\/docs.snyk.io\/scm-ide-and-ci-cd-integrations\/snyk-ide-plugins-and-extensions\/visual-studio-code-extension#how-to-install-and-set-up-the-extension\"> visual studio code extension<\/a> installed.<\/li>\n\n\n\n<li>Docker engine installed on your machine.<\/li>\n\n\n\n<li>A GitHub account.<\/li>\n<\/ul>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"h-scaffolding-an-application\"><a id=\"post-104912-_ofq64p6ei80g\"><\/a>Scaffolding an application<\/h3>\n\n\n\n<p>You&#8217;ll begin by using the Snyk container to demonstrate how to implement Snyk in a CI\/CD pipeline. For the most part, you&#8217;ll use Snyk CLI to scan a Nginx container image. To begin, clone the following Git repository with this command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">git clone git@github.com:mercybassey\/nginx-snyk-scaffolding.git\n<\/pre>\n\n\n\n<p>This will create a local copy of the repository on your machine. It contains a Dockerfile with a base image of <code>nginx:1.17.0<\/code> exposed on port <code>80<\/code> and an <code>index.html<\/code> file that says \u201cHello Snyk.\u201d<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-scanning-for-vulnerabilities-in-a-container-image\"><a id=\"post-104912-_758jc1t9l47m\"><\/a>Scanning for Vulnerabilities in a Container Image<\/h3>\n\n\n\n<p>If you installed the Snyk extension for VScode, then the Snyk CLI is installed automatically. To confirm this, execute the command below to check the Snyk version.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">snyk --version<\/pre>\n\n\n\n<p>Authenticate with the Snyk CLI using the following command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">snyk auth<\/pre>\n\n\n\n<p>This will open up a page on your default web browser where you must log in or sign up with GitHub, Google, BitBucket, Azure AD, or Docker ID. This article uses GitHub as the login option:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"852\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-3.png\" alt=\"\" class=\"wp-image-104915\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Signing up to Snyk.io with GitHub<\/strong><\/p>\n\n\n\n<p>Once you have successfully signed up and logged in, you must allow Snyk to authenticate your machine. Go ahead and authenticate. Once this process is successful, you should have the following image: <img loading=\"lazy\" decoding=\"async\" width=\"1914\" height=\"767\" class=\"wp-image-104916\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-4.png\"><\/p>\n\n\n\n<p><strong>Authenticating with Snyk successfully<\/strong><\/p>\n\n\n\n<p>However, you still need to retrieve your authentication token to integrate Snyk with GitHub actions. This makes it possible to authenticate your GitHub actions pipeline with your Snyk account. Snyk stores your authentication token in the following file <code>~\/.config\/configstore\/snyk.json;<\/code> run this command to view your authentication token:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cat ~\/.config\/configstore\/snyk.json<\/pre>\n\n\n\n<p>This will output your authentication token in the following format:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cat ~\/.config\/configstore\/snyk.json<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">{\n   \"api\": \"fc37....\"\n}<\/pre>\n\n\n\n<p>Copy it and add it to your GitHub repository as a secret. See the following guide on<a href=\"https:\/\/docs.github.com\/en\/actions\/security-for-github-actions\/security-guides\/using-secrets-in-github-actions#creating-secrets-for-a-repository\"> adding secrets in a GitHub repository for GitHub actions<\/a> if you don\u2019t know how to do so already.<\/p>\n\n\n\n<p>Alternatively, you can use this command to get your auth token:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">snyk config get api<\/pre>\n\n\n\n<p>Head to your working directory, create a <code>.github\/workflows\/ci.yml<\/code> file, and paste in the following code, replacing <code>&lt;dockerhub-username&gt;<\/code> with your username on DockerHub:<\/p>\n\n\n\n<p>Note: Naming your custom images using this format <code>&lt;dockerhub-username&gt;\/&lt;image-name&gt;<\/code> makes pushing to your DockerHub repository easy.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name: Snyk Container Scan\non:\n  push:\n    branches:\n      - main\njobs:\n  snyk:\n    runs-on: ubuntu-24.04\n    steps:\n      - name: Check out repository\n        uses: actions\/checkout@v2\n      - name: Build Docker image\n        run: docker build -t &lt;dockerhub-username&gt;\/custom-nginx .\n      - name: Run Snyk to check for vulnerabilities\n        uses: snyk\/actions\/docker@master\n        with:\n          image: &lt;dockerhub-username&gt;\/custom-nginx\n          args: --file=Dockerfile --severity-threshold=high\n        env:\n          SNYK_TOKEN: ${{ secrets.SNYK_AUTH_TOKEN }}<\/pre>\n\n\n\n<p>In the workflow above, GitHub Actions will automatically build the Docker image and then run Snyk to scan for vulnerabilities in the base image specified in the Dockerfile using the <code>--file<\/code> argument.<\/p>\n\n\n\n<p>If there\u2019s any issue with the base image, Snyk will report the vulnerabilities with high severity levels and above and recommend alternative base images, since it has access to the Dockerfile in this workflow.<\/p>\n\n\n\n<p>Execute the Git commands below sequentially to trigger this workflow:<\/p>\n\n\n\n<p>Replace <code>&lt;github-username&gt;<\/code> with your username on GitHub.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">git init\ngit commit -m \"first commit\"\ngit branch -M main\ngit remote add origin git@github.com:&lt;github-username&gt;\/nginx-snyk.git\ngit push -u origin main<\/pre>\n\n\n\n<p>Since the base image specified in the Dockerfile is outdated, you should see a ton of vulnerabilities with high and critical severity levels in your CI, specifically at the job &#8220;Run Snyk to check for vulnerabilities.&#8221; Because you have set the severity threshold to high and above, low and medium severity vulnerabilities will not be reported and thus, not trigger a failure in the CI process, though it&#8217;ll still be recorded.<\/p>\n\n\n\n<p>In this example, Snyk has identified 248 vulnerabilities, with 27 critical, 44 high, 52 medium, and 125 low.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>Base Image    Vulnerabilities      Severity nginx:1.17.0  248    27 critical, 44 high, 52 medium, 125 low<\/pre>\n\n\n\n<p>You should also see alternative base images that Snyk recommends, alongside the number of vulnerabilities detected and their levels.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Recommendations for base image upgrade:\nMinor upgrades\nBase Image   \t            Vulnerabilities  \t             Severity\nnginx:1.26.2  \t\t91               \t\t             1 critical, 1 high, 1 medium, 88 low\nAlternative image types\nBase Image                  \t\tVulnerabilities             Severity\nnginx:1.27.1-bookworm       \t\t91              \t\t1 critical, 1 high, 1 medium, 88 low\nnginx:1.26.2-bookworm-perl  \t91               \t\t1 critical, 1 high, 1 medium, 88 low\nnginx:stable-bookworm-perl  \t91              \t\t1 critical, 1 high, 1 medium, 88 low\nnginx:1.27.1-bookworm-otel  \t94             \t\t1 critical, 1 high, 1 medium, 91 low<\/pre>\n\n\n\n<p>From the output above, Snyk recommends upgrading to nginx:1.26.2 or use the following alternatives - <code>nginx:1.27.1-bookworm, nginx:1.26.2-bookworm-perl, nginx:stable-bookworm-perl or nginx:1.27.1-bookworm-otel<\/code> .<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-proceeding-regardless-of-vulnerabilities\"><a id=\"post-104912-_hxa0xkwqnj3m\"><\/a>Proceeding regardless of vulnerabilities<\/h3>\n\n\n\n<p>By design, Snyk will terminate a CI workflow if it finds any vulnerability, regardless of its severity level (low, medium, high, or critical). However, there's something you should note: there's no guarantee that official and latest Docker images have no vulnerabilities. There is always a possibility that even the most secure images may contain some vulnerabilities.<\/p>\n\n\n\n<p>In this case, Snyk will not recommend any alternatives; however, it will still record the vulnerabilities it finds, inform you that you are using the most secure base image, and halt the CI process. Therefore, you have to explicitly tell Snyk to continue even if vulnerabilities are detected.<\/p>\n\n\n\n<p>Head back to your project and use the <code>nginx:1.27.1-bookworm<\/code> as the base image in your Dockerfile, and edit the CI to look like the following:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name: Snyk Container Scan\non:\n  push:\n    branches:\n      - main\njobs:\n  snyk:\n    runs-on: ubuntu-24.04\n    steps:\n      - name: Check out repository\n        uses: actions\/checkout@v2\n      - name: Build Docker image\n        run: docker build -t &lt;dockerhub-username&gt;\/custom-nginx .\n      - name: Run Snyk to check for vulnerabilities\n        continue-on-error: true\n        uses: snyk\/actions\/docker@master\n        with:\n          image: &lt;dockerhub-username&gt;\/custom-nginx\n          args: --file=Dockerfile\n        env:\n          SNYK_TOKEN: ${{ secrets.SNYK_AUTH_TOKEN }}<\/pre>\n\n\n\n<p>From the CI above, the <code>continue-on-error<\/code> setting in the step \u201cRun Snyk to check for vulnerabilities\u201d allows it to proceed even if it finds vulnerabilities.<\/p>\n\n\n\n<p>Commit and push these changes to your GitHub repository to trigger the workflow. You should have the CI run to completion. <img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"850\" class=\"wp-image-104917\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-5.png\"><\/p>\n\n\n\n<p><strong>Viewing CI on GitHub<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-viewing-snyk-scan-results-with-github-code-scanning\"><a id=\"post-104912-_i8pla4u8u9dt\"><\/a>Viewing Snyk scan results with GitHub Code Scanning<\/h3>\n\n\n\n<p>GitHub code scanning is a SaaS tool that is available on GitHub. While Snyk already outputs scan results in the CI workflow, it's not the most accessible format for tracking and review in terms of vulnerability presentation. With GitHub code scanning you can view Snyk scan results in the <strong>Security<\/strong> tab on your GitHub repository, where vulnerabilities are organized and displayed clearly and interactively.<\/p>\n\n\n\n<p>Before you proceed, you need to give GitHub Token for Actions <em>read\/write<\/em> permissions at<a href=\"https:\/\/github.com\/\"> <em>https:\/\/github.com\/<\/em><\/a><em>&lt;your-github-username&gt;\/nginx-snyk-scaffolding\/settings\/actions.<\/em> You can read more about<a href=\"https:\/\/docs.github.com\/en\/actions\/writing-workflows\/choosing-what-your-workflow-does\/controlling-permissions-for-github_token\"> GitHub Token permission<\/a> in the official GitHub documentation.<\/p>\n\n\n\n<p>Once you have given GitHub Token for Actions <em>read\/write<\/em> permissions, update your CI to have the following configuration settings:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name: Snyk Container Scan\non:\n  push:\n    branches:\n      - main\njobs:\n  snyk:\n    runs-on: ubuntu-24.04\n    steps:\n      - name: Check out repository\n        uses: actions\/checkout@v2\n      - name: Build Docker image\n        run: docker build -t &lt;dockerhub-username&gt;\/custom-nginx .\n      - name: Run Snyk to check for vulnerabilities\n        continue-on-error: true\n        uses: snyk\/actions\/docker@master\n        with:\n          image: &lt;dockerhub-username&gt;\/custom-nginx\n          args: --file=Dockerfile --severity-threshold=high\n          json: true\n        env:\n          SNYK_TOKEN: ${{ secrets.SNYK_AUTH_TOKEN }}\n      - name: Convert Snyk JSON to SARIF\n        uses: garethr\/snyk-to-sarif@master\n        with:\n          input: snyk.json\n          output: snyk.sarif\n      - name: Upload scan results to GitHub Code Scanning\n        uses: github\/codeql-action\/upload-sarif@v3\n        with:\n          sarif_file: snyk.sarif<\/pre>\n\n\n\n<p>From the file above, after Snyk has checked for vulnerabilities, the scan results will be saved in a <code>snyk.json<\/code> file. Next, the \"Convert Snyk JSON to SARIF\" step will use the <code>garethr\/snyk-to-sarif@master<\/code> action to convert it into a format that GitHub code scanning can parse (<code>snyk.sarif<\/code>). Once this process is complete, the <code>sarif<\/code><em> file<\/em> <code>snyk.sarif<\/code> will be uploaded to GitHub code scanning.<\/p>\n\n\n\n<p><em>Note, a SARIF file is a Static Analysis Results Interchange Format. A standard that lets analysis tools exchange results in a standard format.<\/em><\/p>\n\n\n\n<p>Push your changes to trigger the workflow and head to the <strong>Security<\/strong> tab on your repository. You should see vulnerabilities with severity levels from high to critical.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"965\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-6.png\" alt=\"\" class=\"wp-image-104918\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Viewing Snyk scan results on GitHub code scanning<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-scanning-custom-code-and-open-source-libraries\"><a id=\"post-104912-_cmycezm2347h\"><\/a>Scanning Custom Code and Open Source Libraries<\/h3>\n\n\n\n<p>Running security checks automatically for both your code and the libraries used in your projects is always good practice before deploying them to production or building and deploying them to a container registry. Again, you can do this with Snyk code and Snyk open source.<\/p>\n\n\n\n<p>You\u2019ll use Snyk code and Snyk open source to check for Vulnerabilities for a Django project that uses Poetry as the package manager. Run the command below to clone this project to your machine:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">git clone git@github.com:mercybassey\/django-snyk-scaffolding.git<\/pre>\n\n\n\n<p>Run the following command to install all dependencies:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">poetry install<\/pre>\n\n\n\n<p>Create a <em>.<\/em><code>github\/workflows\/ci.yml<\/code> file and paste in the following code:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">name: Django Project CI\/CD\non:\n  push:\n    branches:\n      - main\njobs:\n  snyk:\n    runs-on: ubuntu-24.04\n    steps:\n      - name: Check out repository\n        uses: actions\/checkout@v2\n      - name: Set up Python\n        uses: actions\/setup-python@v2\n        with:\n          python-version: '3.8'\n      - name: Install Poetry\n        run: |\n          curl -sSL &lt;https:\/\/install.python-poetry.org&gt; | python3 -\n      - name: Install dependencies\n        run: |\n          poetry install\n      - name: Run Snyk Open Source Test\n        continue-on-error: true\n        uses: snyk\/actions\/python-3.8@master\n        with:\n          command: test\n          args: --sarif-file-output=snyk-test.sarif\n        env:\n          SNYK_TOKEN: ${{ secrets.SNYK_AUTH_TOKEN }}\n      - name: Run Snyk Code Test\n        continue-on-error: true\n        uses: snyk\/actions\/python-3.8@master\n        with:\n          command: code test\n          args: --sarif-file-output=snyk-code.sarif\n        env:\n          SNYK_TOKEN: ${{ secrets.SNYK_AUTH_TOKEN }}\n      - name: Upload Snyk Open Source Test Results to GitHub Code Scanning\n        uses: github\/codeql-action\/upload-sarif@v3\n        with:\n          sarif_file: snyk-test.sarif\n      - name: Upload Snyk Code Test Results to GitHub Code Scanning\n        uses: github\/codeql-action\/upload-sarif@v3\n        with:\n          sarif_file: snyk-code.sarif<\/pre>\n\n\n\n<p>This workflow will set up Python \u201c3.8\u201d and use the Snyk Python action <code>snyk\/actions\/python-3.8@master<\/code> to scan your code and open source dependencies using the <code>snyk code test<\/code> and <code>snyk test<\/code> commands, respectively.<\/p>\n\n\n\n<p>Create a new GitHub repository for this project, add the Snyk token as a secret, and give GitHub Token for Actions <em>read\/write<\/em> permissions.<\/p>\n\n\n\n<p>Commit and push your changes and wait for the CI to run to completion. Since the CI is configured to continue amidst Snyk vulnerability checks, you should have the following image indicating that the CI job ran to completion.<\/p>\n\n\n\n<p>You'll see a few vulnerability issues when you head to the Security tab on GitHub. This is Snyk doing its work, and if you look at the labels for each vulnerability issue, you'll see the ones related to Snyk open source and Synk code:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2048\" height=\"421\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-7.png\" alt=\"\" class=\"wp-image-104919\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Viewing Snyk open source on GitHub code scanning<\/strong><\/p>\n\n\n\n<p>If you scroll down, you will see just one related to the Snyk code, which is titled \"HardCoded secret.\"<\/p>\n\n\n\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1868\" height=\"133\" class=\"wp-image-104920\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/word-image-104912-8.png\"><strong>Viewing Snyk code scan results on GitHub code scanning<\/strong><\/p>\n\n\n\n<p>Snyk open-source vulnerabilities can be fixed by upgrading dependencies to less vulnerable ones, and for Snyk code vulnerabilities, you'll have to fix them yourself. To resolve Snyk open-source vulnerabilities, you have two options:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Use the <a href=\"https:\/\/docs.snyk.io\/snyk-cli\/scan-and-maintain-projects-using-the-cli\">snyk fix<\/a> command to allow Snyk to automatically upgrade to its recommended open source libraries, or add a step in the CI that executes the snyk fix command for you automatically. However, this option is only available for Snyk enterprise users.<\/li>\n\n\n\n<li>Manually upgrade to Snyk's recommended open-source libraries on your machine.<\/li>\n<\/ul>\n<\/div>\n\n\n<p>To resolve the vulnerability related to the Snyk code, you have to remove the hard-coded secret.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-resolving-open-source-libraries-for-snyk-open-source\"><a id=\"post-104912-_3bqomsg5jf0g\"><\/a>Resolving open source libraries for Snyk open source<\/h3>\n\n\n\n<p>Activate the Poetry virtual shell and run a vulnerability check for Snyk open source with the following command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">poetry shell\nsnyk test<\/pre>\n\n\n\n<p>As I write this article, Snyk asks me to upgrade to Django 4.2.16 and sqlparse 0.5.0. Depending on when you see this article, the recommended versions might be different.<\/p>\n\n\n\n<p><strong> Issues to fix by upgrading dependencies:<\/strong><\/p>\n\n\n\n<p><code>\t  Upgrade django@4.2.3 to django@4.2.16 to fix<\/code><\/p>\n\n\n\n<p><code>\t  \u2717 Regular Expression Denial of Service (ReDoS) [Medium Severity][&lt;https:\/\/security.snyk.io\/vuln\/SNYK-PYTHON-DJANGO-5932095&gt;] in django@4.2.3<\/code><\/p>\n\n\n\n<p><code>\t    introduced by django@4.2.3<\/code><\/p>\n\n\n\n<p><code>\t  \u2717 Denial of Service (DoS) [Medium Severity][&lt;https:\/\/security.snyk.io\/vuln\/SNYK-PYTHON-DJANGO-6041515&gt;] in django@4.2.3<\/code><\/p>\n\n\n\n<p><code>\t    introduced by django@4.2.3<\/code><\/p>\n\n\n\n<p><code>\t  \u2717 Regular Expression Denial of Service (ReDoS) [Medium Severity][&lt;https:\/\/security.snyk.io\/vuln\/SNYK-PYTHON-DJANGO-6370660&gt;] in django@4.2.3<\/code><\/p>\n\n\n\n<p><code>\t    introduced by django@4.2.3<\/code><\/p>\n\n\n\n<p><code>\t    ....<\/code><\/p>\n\n\n\n<p><code>\t  Upgrade sqlparse@0.4.4 to sqlparse@0.5.0 to fix<\/code><\/p>\n\n\n\n<p><code>  \u2717 Uncontrolled Recursion [High Severity][&lt;https:\/\/security.snyk.io\/vuln\/SNYK-PYTHON-SQLPARSE-6615674&gt;] in sqlparse@0.4.4<\/code><\/p>\n\n\n\n<p><code>    introduced by sqlparse@0.4.4 and 1 other path(s)<\/code><\/p>\n\n\n\n<p>Run the command below to install django 4.2.16 and sqlparse 0.5.0:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">poetry add django@4.2.16\npoetry add sqlparse@0.5.0<\/pre>\n\n\n\n<p>You should see the following output once this is successful:<\/p>\n\n\n\n<p><code>Updating dependencies<\/code><\/p>\n\n\n\n<p><code>Resolving dependencies... (0.4s)<\/code><\/p>\n\n\n\n<p><code>Package operations: 0 installs, 2 updates, 0 removals<\/code><\/p>\n\n\n\n<p><code>  - Updating sqlparse (0.4.4 -&gt; 0.5.0)<\/code><\/p>\n\n\n\n<p><code>  - Updating django (4.2.3 -&gt; 4.2.16)<\/code><\/p>\n\n\n\n<p><code>Writing lock file<\/code><\/p>\n\n\n\n<p>When you run the <code>snyk test<\/code> command again, you\u2019ll see the following, indicating all libraries are up-to-date and no vulnerabilities were found.<\/p>\n\n\n\n<p><code>\u2714 Tested 7 dependencies for known issues, no vulnerable paths found<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-resolving-hard-coded-secrets-for-snyk-code\"><a id=\"post-104912-_a3049hg5srn4\"><\/a>Resolving Hard Coded Secrets for Snyk code<\/h3>\n\n\n\n<p>Right now in my example, <code>snyk code<\/code> found a vulnerability at <code>django_project\/settings.py<\/code> where a secret is being hardcoded. To resolve this, you\u2019ll need to use environment variables.<\/p>\n\n\n\n<p>First, in the root of the Django project, create a <code>.env<\/code> file and populate it. Do this by replacing <code>&lt;secret-key&gt;<\/code> with the actual key from <code>django_project\/settings.py<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">DJANGO_SECRET_KEY='&lt;secret-key&gt;'<\/pre>\n\n\n\n<p>Next, edit the <code>SECRET_KEY<\/code> variable in <code>django_project\/settings.py<\/code> to hold the value <code>os.getenv(\"DJANGO_SECRET_KEY\")<\/code>:<\/p>\n\n\n\n<p>This will load the value from the <code>environment<\/code> variable using os.getenv:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import os\n\nSECRET_KEY = os.getenv(\"DJANGO_SECRET_KEY\")<\/pre>\n\n\n\n<p>Then, create a <code>.gitignore<\/code> file in the project\u2019s root and add the .env file to exclude it from version control:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># .gitignore\n.env<\/pre>\n\n\n\n<p>Now, run <code>snyk code test<\/code> again to recheck the code. You should see the following results:<\/p>\n\n\n\n<p><code>\u2714 Awesome! No issues were found.<\/code><\/p>\n\n\n\n<p>And there you go, no more code security issues, at least those that have been identified so far!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"post-104912-_vmaywe45s80i\"><\/a>Conclusion<\/h2>\n\n\n\n<p>In this article, you have learned what security scanning is, why you should implement security scanning in a CI\/CD workflow, and how to use Snyk for vulnerability scanning in a GitHub actions workflow. You have used Snyk container to scan and identify vulnerabilities in an Nginx container image, used Snyk open source to scan open source libraries within a Django application, and used Snyk code to scan custom code. Snyk is a robust tool, you can integrate Snyk with Kubernetes, Jira, and Slack. See the <a href=\"https:\/\/docs.snyk.io\/\">official Snyk documentation<\/a> to find more information about Snyk.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Security is important regardless of your industry, whether it&#8217;s finance, retail, e-commerce, or the broader world of IT. A little security oversight can have catastrophic impacts, leading to loss of money and unauthorized access to classified information. It takes a lot of work to develop solutions that users trust. Therefore, you need to take security&#8230;&hellip;<\/p>\n","protected":false},"author":341730,"featured_media":104922,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[46],"tags":[4619,159234],"coauthors":[158989],"class_list":["post-104912","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security-and-compliance","tag-security","tag-snyk"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104912","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/341730"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=104912"}],"version-history":[{"count":14,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104912\/revisions"}],"predecessor-version":[{"id":107319,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104912\/revisions\/107319"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/104922"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=104912"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=104912"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=104912"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=104912"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}