{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"74d57990-d6af-5953-b038-ee5d823d3e7a","frontmatter":{"category":"DevOps","title":"Enhancing AUTO1 Cloud Security Posture with Terraform Security Scanners","date":"2023-04-28","summary":"This article describes our journey to adopt KICS terraform scanner into our toolset. We will go through our approach to choosing the right tool from a vast selection of great options.","thumbnail":{"relativePath":"pages/terraform-security-scanners/logo.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAABBElEQVQY053RP2vCQBjH8eggRToIXYriVkFUsF7E6CAoaiLdLEJLh7rXLv4Dh0wuQqFQEBxEyFyo+iZcJVC7uPWd6PcpcXAqePDhnuTufsndaR3TbcPBL3aYd033qWQ8+LRzGgELAsb0Q9jU0465mchYRqUTutJflVI1WGgijjyi0Gk5BKmLQgIHeMMLPrqWuyXwWQKzygizZsVEE194xx3uEUMbKW88iZAENrHmz0qoUxPoFo874Os2CFYTVHGFClp4RMR7vsW1BAawRI/AERwJapQH2t7ea7JFAi/pb+Q9vdQFWYy0V1/AQPZ4jkF8Ytazvv8uo2/9+CKp0/Mm2P/fnRwAs2dyCkXlBpwAAAAASUVORK5CYII=","width":640,"height":189,"src":"/static/83bade24f8196b98a976b4fdbaebd2eb/0a508/logo.png","srcSet":"/static/83bade24f8196b98a976b4fdbaebd2eb/0a508/logo.png 1x"}}},"authorName":"Artem Marusov","authorDescription":"Artem Marusov is a Senior DevSecOps Engineer in the DevOps Team based in the Berlin office.","authorAvatar":{"relativePath":"pages/terraform-security-scanners/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsSAAALEgHS3X78AAAEkklEQVQ4yzVTCVNTVxR+v6EznUpYzPISCI1BZQoqLoMFiyyiLKKtUKAFEVpNaiG2yNIqlAwqboAFAgwOGBhQOtRCKsxQQKqY5eVlee9l33cgpGwDndILpTNn7tw753zn+85yobd/iiXvEESqUCnUuJowGMwERnT//CTrdOKxg6yEmKispJOtD5pMRovFZNPgWkyFo4hKKpGL30mhuTdiqViukO8gdcaJ0Zd5Gek0UjCVRIJDSMwwUnxURDybUVrwOQiwmKwEplErMLlMIXkng8RzUkSKqhQ4yOp0uB7V1UaHfXCIGhJLDjodRc/+KCIhkvwxmx4Dh5SXXbZbHXqtAWQBZFIxAoEEQMZ/tF6395vSksL46N/rv5L3NRl/68GETaKGa7U5iUeZlAhK2MwfM067C5CrFBgiQyGZGFGgmBbXWowWn3ehilP2rLp49XX/hmpyTTG5jog2Z4XuF/d+KDgbvjdsdmbW4/ZqCZ1aua0ckknkaiWu1+ptZtvi4hK/slxYU2L7td069jQw99I7NfimrW7qAa+uMO1kbDSOazwur15nBEpRRAkBdtBAoNlmsa+urgu7BdW5KZUXkipSDluH7o7dLimI+/Bmxomy5NjMhOMWo8nj8hn1JqBcIVdBgB1TEeDtcLgCi/7RnvaWr3Ma81LbynIIQfUsv0zAyW2/nNZSms5JPiodFs4HVow6I4FpUbkagJUgjclgdjrdS36/dGRA1tvoE7U5f3nsHbqvF9TOj3UuTXSI7nBaijJt0xPexYDJYAKjAW2GUJkSV2vADrgc7sDyinFmXNp3f3VGiHfVPavI77ySYe5t8IkEHdcvNRdlzxsMHu+C2WDeBSvkgJkAYDDkv5bXHFpi4km9SlA58t0lfnY8sKHrWeP1xbfzU0S9XYHAqtPpMRstBL5TswJRbcsGYKd7ccG/tvH3ZH97f0VWc0GSqLz4JffL9qLUbu7ZW8XnHV6/b3HZbndvgzHNjmwEyCZAzS6Ha947/8/W1utXoy2laXMPOcNVBcJvcyb4JTcy4xqqeP6VDbvLZ7W5jNv7/z94t9s2p9fjW1vfcDlseafjbuV90nE1494XiTcuJLBD3xe0Pl7Z2DJYnCaLU68zAz7QaTBnMCpcp9FbLfYlf2BtfdM/7+HmJMF73mPvJbHIJDh4z3FGyGBPp39zS292anQWjcagVuHgR0ASMQJ2zWq2AubpqTfI3Fv5q8EX/GvcjBMHyEFsctCZWBb3XNwdTt7oyIgE1ZmsHpwwoHKVVCyDMCWOSNCBgWEer/bQkVM/8Thof+NYc814a82PuUmc9Dh+0bma/JRu3qdXslMTTqU3PWybfi3GMJ0SVUN3Gh+dScvZty8mknmAxTp4OOZIF79y9ulddKh17MH3ww3c5/zyhtLzFYUX97OjYSoT2NFjCVev8Xr7nkMwzKKQGQx6JDOCDSycsY/FZH+WnnyzJL+BW1JTWnAxOTGaHUUFMBoThNHhSAqZHhpCZTL3QwyYSacxadQI4KPDu+7gEFpwMJVMCQ8NhbcvZDqNGg7TIsBJpTCoFHBnUsjwv61+3idVvgk1AAAAAElFTkSuQmCC","width":50,"height":50,"src":"/static/73b4f6833b9dadf507bf9df0f8322e21/45876/avatar.png","srcSet":"/static/73b4f6833b9dadf507bf9df0f8322e21/45876/avatar.png 1x,\n/static/73b4f6833b9dadf507bf9df0f8322e21/eb85b/avatar.png 1.5x,\n/static/73b4f6833b9dadf507bf9df0f8322e21/4f71c/avatar.png 2x,\n/static/73b4f6833b9dadf507bf9df0f8322e21/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/terraform-security-scanners/header.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsSAAALEgHS3X78AAABpUlEQVQoz2PglDBHQhYQxCFhxiEOQlyS5kAEkYKIICtjAHEkgSxzDjCCmMIlacUF5jIJGTIKGrKJmgDVQDTD9JtzipszcIibg5EZjGHOKmooKOMtr57k7J9k75Xs4JMsoebEKmICsgCmH2IEA1wbxDygbbyy1oLyDmJKXrI67gp6XooGPmIqTrwy1sg6IVrAmpGM5JG2ltFxElIx41c0ZhRU45Iz4pQx5JIzlNB04JGyYhczRTaCAcnBUM3imrZsEmrCKkZ13dPW7zikYOTAwCMrpGLJK22NTTMk9ED6TYHOk9R24JTSlNYyv3r/9cOP/5PzyxnYJMQ0bHFohvrZgl3MjFvKUkjVkklMmYFfLrmgpqSpX9HQjoFTUlARGG0gZ0OjCuZnc3joAeXEVF2MHCP1bPx1rP1VjD0kNe0VDT3UzX307cIk1F3ZIJpBUWsJimeINpARYM1AFeqmweomwUBS0yxE2yJM0zxUwzRYwyxEUsMN6DSUqAIawCWJSD1As5mFDEFI2AiEQGwjCJdV1AQ9nsFusIAmAGjSQ06wwNSGEEFLZAAKTmZdNevBHQAAAABJRU5ErkJggg==","width":1280,"height":748,"src":"/static/84f9df6613e6af34b6e63796561794af/26421/header.png","srcSet":"/static/84f9df6613e6af34b6e63796561794af/26421/header.png 1x,\n/static/84f9df6613e6af34b6e63796561794af/34a7a/header.png 1.5x"}}}},"html":"<h2>Introduction</h2>\n<p>At AUTO1, we rely on Terraform to manage our cloud infrastructure. And of course, we are trying to pay close attention to its security posture. Over time we realized that relying solely on reactive methods, such as AWS Config and Security Hub, to identify and combat misconfigurations in our AWS services wasn't sufficient. It was imperative for us to shift left in our infrastructure development cycle to avoid repeating the same misconfigurations over and over again. In this blog post, we'll be discussing the journey of how we implemented security scans for our Terraform code.</p>\n<h2>Goals and Success Criteria</h2>\n<p>Idea would be to introduce some sort of security tool, that would scan all of our changes introduced in the infrastructure codebase and report on security finding. Based on that we could eventually start to prevent merge of PRs that contain some of the most critical misconfigurations. That way we wouldn't have to chase the same Security Hun findings all of the time.</p>\n<p>To ensure successful implementation of Terraform security scanning, we needed to address two key questions:</p>\n<ol>\n<li>\n<p>Are we fully prepared to incorporate Terraform security scanners into our daily operations, even if it means potential blocks on some of our changes?</p>\n</li>\n<li>\n<p>If yes, then which one would be the best fit for our requirements?</p>\n</li>\n</ol>\n<p>To answer these questions, we had to formulate specific criteria that the security scanning tool had to meet.</p>\n<table>\n<thead>\n<tr>\n<th><strong>#</strong></th>\n<th><strong>Our ideal terraform security scanner...</strong></th>\n<th><strong>Importance</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>is able to perform various security checks on the terraform code for the majority of important AWS services (including custom checks: encryption, IAM, public resources, etc.</td>\n<td>CRITICAL</td>\n</tr>\n<tr>\n<td>2</td>\n<td>can be integrated into our development cycle for different repositories via Github Actions</td>\n<td>CRITICAL</td>\n</tr>\n<tr>\n<td>3</td>\n<td>can be run on self-hosted Github runners</td>\n<td>HIGH</td>\n</tr>\n<tr>\n<td>4</td>\n<td>has capability to configure different conditions to fail or pass checks (for example severity of the finding)</td>\n<td>MEDIUM</td>\n</tr>\n<tr>\n<td>5</td>\n<td>has capability to suppress findings directly inline in code</td>\n<td>HIGH</td>\n</tr>\n<tr>\n<td>6</td>\n<td>has good readability of the scan results</td>\n<td>MEDIUM</td>\n</tr>\n<tr>\n<td>7</td>\n<td>can be integrated into AWS Security Hub or AWS Inspector (or some other centralized view for analysis, like DefectDojo)</td>\n<td>LOW</td>\n</tr>\n<tr>\n<td>8</td>\n<td>has an open source community version</td>\n<td>HIGH</td>\n</tr>\n<tr>\n<td>9</td>\n<td>has good documentation, including mitigation recipes for found misconfigurations</td>\n<td>LOW</td>\n</tr>\n<tr>\n<td>10</td>\n<td>should take as little time as possible to scan target modules</td>\n<td>MEDIUM</td>\n</tr>\n<tr>\n<td>11</td>\n<td>can scan external terraform modules (local or on Github)</td>\n<td>LOW</td>\n</tr>\n<tr>\n<td>12</td>\n<td>can scan single files, not only directories</td>\n<td>LOW</td>\n</tr>\n</tbody>\n</table>\n<p>I think all of the criteria are pretty self-explanatory. Assigned 'importance' will come into play later, for now it just should be noted that of course chosen criteria and assigned values are mostly subjective and very team-dependent — for our specific case this outline was close enough.</p>\n<p>With goals and criteria of PoC figured out, we had to round up some contenders.</p>\n<h2>Choosing contenders</h2>\n<p><a href=\"https://postimg.cc/F1gJJZKf\"><img src=\"https://i.postimg.cc/kMLNzY3y/Picture1.png\" alt=\"Community adoption is important\"></a></p>\n<p>We started by conducting an initial assessment of the available Terraform security scanning tools. Based <em>mostly</em> on community adoption, we compiled a longlist of contenders, which included:</p>\n<ul>\n<li><a href=\"https://github.com/bridgecrewio/checkov\">checkov</a> by Bridgecrew</li>\n<li><a href=\"https://github.com/Checkmarx/kics\">KICS</a> by Checkmarx</li>\n<li><a href=\"https://github.com/fugue/regula\">regula</a> by Fugue</li>\n<li><a href=\"https://github.com/snyk/cli\">snyk</a> by Snyk</li>\n<li><a href=\"https://github.com/SonarSource/sonarqube\">SonarQube</a> by SonarSource (made the list only because we already use it as SAST for our application codebase and it recently started to support terraform)</li>\n<li><a href=\"https://github.com/tenable/terrascan\">terrafscan</a> by Tenable</li>\n<li><a href=\"https://github.com/aquasecurity/tfsec\">tfsec</a> by Aqua Security</li>\n<li><a href=\"https://github.com/aquasecurity/trivy\">trivy</a> by Aqua Security</li>\n</ul>\n<p>Here it is important to know that PoC took place in the second part of 2022, so our observations and conclusions were made based on the versions of these tools that were available at the time.</p>\n<p>The initial assessment was rather straightforward. It involved installing each tool, scanning a Terraform module that was part of our infrastructure, and evaluating the scan results. Based on the results of the evaluation (which basically boiled down to briefly looking at the produced report and comparing it to the results generated by other tools), we narrowed down the list to the following contenders:</p>\n<ul>\n<li>checkov</li>\n<li>KICS</li>\n<li>tfsec</li>\n</ul>\n<p>The ones that didn't make the cut either:</p>\n<ul>\n<li>\n<p>were producing non-satisfactory scan results:</p>\n<ul>\n<li>regula — had just mediocre list of available security checks, hence not too many findings;</li>\n<li>SonarQube — only recently got capability to scan terraform and at the time of testing had only around of 30 security checks (shortlisted contenders each already had more than a hundred at that time);</li>\n<li>terrascan — strangest case of all. According to the community adoption should show decent results, but for some reason I couldn't make it to produce them. I still think that it might be the result of misconfiguration, although there isn't much to configure there, to be honest.</li>\n</ul>\n</li>\n<li>turned out to be overkill for our use case — trivy actually can do a lot more than just to scan terraform code. Tfsec from the same vendor is a better pick for us. Not to mention, that it seems like under the hood trivy uses tfsec to scan terraform.</li>\n<li>had very hard usage limits introduced in the community version — snyk</li>\n</ul>\n<p>At the same time all the tools that we chose to shortlist looked pretty great. So, now we had to test each of them properly in order to decide which one would win.</p>\n<h2>Preparations</h2>\n<p>To properly evaluate the shortlisted tools, we decided to integrate them into our main infrastructure repository as Github Workflows.</p>\n<p>This way we would gather relevant statistics very quickly and at the same time get a taste of the new way of implementing changes.</p>\n<p>Github Workflows is an automation tool that is integrated within the Github platform. These workflows allow you to automate a variety of tasks, such as building and testing your code, releasing software updates, and more. Workflows are defined in a specific file format called YAML, which is stored in your Github repository. The workflows are triggered by specific events, such as a code push or a pull request, and they can run a series of actions in response to these events. These actions can be anything from running a set of commands, to integrating with external tools and services.</p>\n<p>Typical workflow in our case looked roughly like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">name: tfsec\non:\n  pull_request:\n\njobs:\n  tfsec:\n    name: tfsec\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n        with:\n          fetch-depth: 0\n\n      - name: Get changed files\n        id: changed-files\n        uses: tj-actions/changed-files@v35\n        with:\n          dir_names: true\n\n      - name: Install tfsec\n        continue-on-error: true\n        run: |\n          wget -O - -q &quot;$(wget -q https://api.github.com/repos/aquasecurity/tfsec/releases/latest -O - | grep -o -E &quot;https://.+?tfsec-linux-amd64&quot; | head -n1)&quot; &gt; tfsec\n          install tfsec /usr/local/bin/\n          tfsec --version\n\n      - name: Setup SSH Keys and known_hosts\n        env:\n          SSH_AUTH_SOCK: /tmp/ssh_agent.sock\n        continue-on-error: true\n        run: |\n          ssh-agent -a $SSH_AUTH_SOCK &gt; /dev/null\n          ssh-add - &lt;&lt;&lt; &quot;${{ secrets.TERRASCAN_SSH_KEY }}&quot;\n\n      - name: tfsec Security Scan\n        env:\n          SSH_AUTH_SOCK: /tmp/ssh_agent.sock\n          TERM: xterm-color\n        continue-on-error: true\n        run: |\n          for directory in ${{ steps.changed-files.outputs.all_changed_files }}; do\n            echo &quot;$(tput setaf 2) Currently scanning module: $directory&quot;\n            tfsec $directory --soft-fail || true\n          done\n\n      - name: Post scan message\n        continue-on-error: true\n        run: |\n          cat &lt;&lt; EOF\n          If security scan found misconfigurations in the code,\n          please either try to fix them or create inline ignore comments for the\n          appropriate resources.\n\n          Format:\n          (Place comment before resource code block or in the offending line)\n          #tfsec:ignore:&lt;rule&gt;\n\n          Rule identificators are specified in the scan results.\n\n          More about tfsecs format can be found here:\n          https://aquasecurity.github.io/tfsec/v1.27.4/guides/configuration/ignores/\n          EOF</code></pre></div>\n<p>Let's go over it bit by bit to explain what exactly is going on here:</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">name: tfsec\non:\n  pull_request:\n\njobs:\n  tfsec:\n    name: tfsec\n    runs-on: ubuntu-latest</code></pre></div>\n<p>In the beginning we need to define the name of the workflow (\"tfsec\"), its trigger (in our case — only opening or changing PRs) and where it will run. In this case it will run on Github Managed runners, but it is possible to integrate your own runners deployed, for example, in AWS — then we'd have to reference them using a specific name tag.</p>\n<p>In this case we defined only one job with multiple steps.</p>\n<p>Here they are:</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n        with:\n          fetch-depth: 0</code></pre></div>\n<p>Pretty standard, we use another Github Action (provided by Github in this case) to checkout target repo.</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">      - name: Get changed files\n        id: changed-files\n        uses: tj-actions/changed-files@v35\n        with:\n          dir_names: true</code></pre></div>\n<p>Here is the attempt to optimize our process. So, obviously when we started this PoC, we already had a pretty sizable terraform repo on our hands. For that reason, it didn't make a lot of sense (and also would be kind of unfair to a person that wants to make some small change to a specific module) to scan the whole repo and report on it each time someone creates a new PR. So here we use another awesome action to limit our scan to only changed modules. <strong>dir_names</strong> option indicates that we get only names of the directories that hold changed files, not the filenames themselves. This is used here because tfsec expect scanning path to be a single directory. For tools, that can scan separate files, we would disable this option to optimize scope.</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">      - name: Install tfsec\n        continue-on-error: true\n        run: |\n          wget -O - -q &quot;$(wget -q https://api.github.com/repos/aquasecurity/tfsec/releases/latest -O - | grep -o -E &quot;https://.+?tfsec-linux-amd64&quot; | head -n1)&quot; &gt; tfsec\n          install tfsec /usr/local/bin/\n          tfsec --version</code></pre></div>\n<p>This one is pretty self-explanatory. We need to download and install the latest version of the required tool.</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">      - name: Setup SSH Keys and known_hosts\n        env:\n          SSH_AUTH_SOCK: /tmp/ssh_agent.sock\n        continue-on-error: true\n        run: |\n          ssh-agent -a $SSH_AUTH_SOCK &gt; /dev/null\n          ssh-add - &lt;&lt;&lt; &quot;${{ secrets.TERRASCAN_SSH_KEY }}&quot;</code></pre></div>\n<p>This one is actually pretty tool and environment specific. It's relevant for tools that can scan modules that are being sourced from Github repos. Here we allow runners to use previously created SSH key, authorized to pull those modules.</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">      - name: tfsec Security Scan\n        env:\n          SSH_AUTH_SOCK: /tmp/ssh_agent.sock\n          TERM: xterm-color\n        continue-on-error: true\n        run: |\n          for directory in ${{ steps.changed-files.outputs.all_changed_files }}; do\n            echo &quot;$(tput setaf 2) Currently scanning module: $directory&quot;\n            tfsec $directory --soft-fail || true\n          done</code></pre></div>\n<p>Finally, we can scan code. We use a list of changed directories, found by one the previous steps, and just iterate through, launching the security tool to scan each one.</p>\n<p>Last part would be just a message to hint at the next possible steps for the engineers. In our case it was just a link to the documentation.</p>\n<p>One important thing. You might have noticed that almost in every step we use this option:</p>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\">continue-on-error: true</code></pre></div>\n<p>It was really crucial at this stage to not block work of the engineers under any circumstances. This option ensured that even if some step of the workflow would fail or produce security finding, it wouldn't block the PR.</p>\n<p>Because we wanted to compare all three scanners simultaneously to ensure that our observations were always in the same context, we had to construct a workflow for each one and activate them in our repository. Workflows looked roughly the same with small adjustments specific for each tool. After implementation was done it was time for the team members to continue to write code, push PRs and that way generate more and more scan results. For those who were directly responsible for the PoC it was time to perform some tests against formulated success criteria based on accumulated statistics.</p>\n<h2>Proof of Concept</h2>\n<p>Based on the accumulated scan results we tried to estimate how well each tool complies with our requirements.</p>\n<p>Boiled down results are listed below. We tried to make them at least a bit self-explanatory so we could be able to reference them in the future, when someone will inevitably ask: \"Does anybody remember why we chose this scanner over that scanner?\".</p>\n<p>We listed previously defined criteria and assigned numeric value to their importance characteristic:</p>\n<ul>\n<li>critical — 1.0</li>\n<li>high — 0.75</li>\n<li>medium — 0.5</li>\n<li>low — 0.25</li>\n</ul>\n<p>Then based on our observations we graded every tool, basically evaluating compliance of each tool to every criterion. Grades multiplied by importance got us numeric results that we could use to objectively compare contenders. Below are the results supplemented by the comments, intended to justify each grade. For better readability you can check out this <a href=\"https://docs.google.com/spreadsheets/d/1XLBaZEuGWcZls6VMFcDsBCCf2S5iTCkg7vL-49fGejg/edit?usp=sharing\">Google sheet</a>.</p>\n<iframe width=\"100%\" height=\"1080\" src=\"https://docs.google.com/spreadsheets/d/e/2PACX-1vQU2WdBiYPKZjE8d3Mq_5Ktj6oBlvJI-wkXOi_x8gk9MgYYUwpdpUFGFwT4B0F8ssYW5Nl3eLa5qRG1/pubhtml?gid=0&amp;single=true&amp;widget=true&amp;headers=false\"></iframe>\n<h2>Results and Conclusion</h2>\n<p>In the end we chose KICS as our terraform security scanner. Honestly, I believe that we'd have chosen it even if it wouldn't score highest in our internal test rating (but it also helped to reach the decision, of course). Reason for that would be that basically with the same scanning quality as other just these two KICS's killer-features:</p>\n<ul>\n<li>great scan visibility provided in the form of PR comments and annotations (this is a special feature of this <a href=\"https://github.com/Checkmarx/kics-github-action\">KICS Github Action</a>);</li>\n<li>ability to scan only changed files, nothing else (instead of the whole directories).</li>\n</ul>\n<p>made it the most appealing candidate. It is now integrated to all of our terraform repositories (more than a 100 in total). It scans every PR we make, reports on it and blocks them if any of the findings were classified with severity \"high\" (highest in the KICS terminology).</p>\n<p>As for the initial goal — to make our infrastructure a bit more secure — I believe KICS has indeed assisted us with that quite well. Sometimes we just fix one small existing or newly introduced misconfiguration and go on with our day. But sometimes we find something that turns into an epic with dozens of tickets that cover hundreds and hundreds of our resources and services. Both scenarios are great and valuable in the end. Additionally, it spreads awareness across all of the DevOps team about available security options of various AWS services and in general more secure ways to use them (at least I really hope so). Taking all this into account, the effort was well worth it and I think we will continue to benefit from it further and further.</p>\n<p>Thank you for reading!</p>","fields":{"slug":"/terraform-security-scanners/","tags":["security","terraform","DevOps","DevSecOps"]}}},{"node":{"id":"c61acf9d-7746-503a-ba8f-cf96f4042096","frontmatter":{"category":"Coding","title":"Secure coding practices for NodeJS Web Applications","date":"2018-06-20","summary":"This post highlights various coding practices for securing a NodeJS web application against the most critical web attacks.","thumbnail":{"relativePath":"pages/securing-nodejs-applications/thumbnail.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHMkZoCv//EABUQAQEAAAAAAAAAAAAAAAAAAAAS/9oACAEBAAEFApSl/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/AWf/xAAXEAADAQAAAAAAAAAAAAAAAAAAECEx/9oACAEBAAY/AoYv/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARIUFxUf/aAAgBAQABPyHOqLFGlciV85P/2gAMAwEAAgADAAAAEHvP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAEDAQE/EAJs/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EFjP/8QAHBABAAEEAwAAAAAAAAAAAAAAASEAETFxUWHw/9oACAEBAAE/EMpW8q+4qwMgymddUsU0EV//2Q==","width":867,"height":325,"src":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/a2998/thumbnail.jpeg","srcSet":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/a2998/thumbnail.jpeg 1x"}}},"authorName":"Rajababu Pradhan","authorDescription":"Raja is Senior Frontend Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/securing-nodejs-applications/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/securing-nodejs-applications/header-image.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHMkZoCv//EABUQAQEAAAAAAAAAAAAAAAAAAAAS/9oACAEBAAEFApSl/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/AWf/xAAXEAADAQAAAAAAAAAAAAAAAAAAECEx/9oACAEBAAY/AoYv/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARIUFxUf/aAAgBAQABPyHOqLFGlciV85P/2gAMAwEAAgADAAAAEHvP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAEDAQE/EAJs/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EFjP/8QAHBABAAEEAwAAAAAAAAAAAAAAASEAETFxUWHw/9oACAEBAAE/EMpW8q+4qwMgymddUsU0EV//2Q==","width":1200,"height":450,"src":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/935ac/header-image.jpeg","srcSet":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/935ac/header-image.jpeg 1x"}}}},"html":"<h1>Secure coding practices for NodeJS Web Applications</h1>\n<p>Everyone would agree that security is very important and with the increase in cyber attacks in the recent past, organizations are investing\nheavily on application security. In this post lets talk about securing a web application built in NodeJS.</p>\n<p><strong>NOTE</strong>: The security concepts discussed here are language or framework agnostic. However, here we will see how these practices are implemented\nin NodeJS web applications.</p>\n<h2>1. Use SSL/TLS for communication</h2>\n<p>It is always a good practice to send your data over HTTPS rather than HTTP and it is imperative if your app transmits sensitive data.\nEncrypting data transmitted between the client and server helps mitigate several attacks like <a href=\"https://www.owasp.org/index.php/Man-in-the-middle_attack\">man-in-the-middle(MITM)</a> attack, packet sniffing,\neavesdropping etc. Let’s see how to set up TLS/SSL in Express 4.x:</p>\n<p>Lets first generate a self-signed certificate:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365</code></pre></div>\n<p>This generates a self-signed certificate valid for 365 days.</p>\n<p><strong>NOTE</strong>: The self-signed certificate is not ideal for production. For production, you should get a certificate from a <em>Certificate Authority(CA)</em>.</p>\n<p>Next, enable HTTPS on Express. Additionally, redirect all HTTP traffic to HTTPS:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const fs = require('fs');\nconst https = require('https');\nconst express = require('express');\n\nconst NODE_ENV = process.env.NODE_ENV || 'development';\nconst PORT = process.env.PORT || 3443;\n\nconst app = express();\n\nhttps.createServer({\n  key: fs.readFileSync('/path/to/key.pem'),\n  cert: fs.readFileSync('/path/to/cert.pem')\n}, app).listen(PORT);\n\n// Redirect http requests to use https in production\nif (NODE_ENV === 'production') {\n  app.use((req, res, next) => {\n    if (req.header('x-forwarded-proto') !== 'https') {\n      res.redirect(`https://${req.header('host')}${req.url}`);\n    } else {\n      next();\n    }\n  });\n}</code></pre></div>\n<h2>2. Use security headers generously</h2>\n<p><strong>i) Strict-Transport-Security:</strong> <em>The HTTP Strict Transport Security(HSTS)</em> if set in the response header, tells the browser that it should only communicate using HTTPS instead of HTTP while communicating with the specified domain.</p>\n<p><em>Syntax:</em></p>\n<p><code class=\"language-text\">Strict-Transport-Security: max-age=&lt;expire-time></code></p>\n<p>Here, max-age is the time(in secs) that the browser should remember that this site is only to be accessed using HTTPS.</p>\n<p><em>Example: from facebook.com:</em></p>\n<p><code class=\"language-text\">strict-transport-security:max-age=15552000;</code></p>\n<p><strong>ii) X-Frame-Options:</strong> This HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <code class=\"language-text\">&lt;frame></code>, <code class=\"language-text\">&lt;iframe></code> or <code class=\"language-text\">&lt;object></code>. Sites can use this to avoid <a href=\"https://www.owasp.org/index.php/Clickjacking\">clickjacking</a> attacks, by ensuring that their content is not embedded into other sites.</p>\n<p><em>Syntax:</em></p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">X-Frame-Options: DENY\nX-Frame-Options: SAMEORIGIN\nX-Frame-Options: ALLOW-FROM https://siteutrust.com/</code></pre></div>\n<p><strong>iii) X-XSS-Protection:</strong> This HTTP response header enables the built-in XSS filter in modern browsers.</p>\n<p><em>Example:</em></p>\n<p><code class=\"language-text\">X-XSS-Protection: 1</code></p>\n<p><strong>iv) X-Content-Type-Options:</strong> This response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should not be changed and be followed. This prevents MIME type sniffing attacks.</p>\n<p><em>Syntax:</em></p>\n<p><code class=\"language-text\">X-Content-Type-Options: nosniff</code></p>\n<p><strong>v) Content-Security-Policy:</strong> Prevents a range of injection attacks including Cross Site Scripting(XSS) attack.</p>\n<p><em>Syntax:</em></p>\n<p><code class=\"language-text\">Content-Security-Policy: policy</code></p>\n<p>For a detailed explanation of CSP, go through this <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP\">link</a>.</p>\n<p>To set these headers in NodeJS, use the <a href=\"https://helmetjs.github.io/\">helmet</a> npm package:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const express = require('express');\nconst helmet = require('helmet');\n\nconst app = express();\n\n&lt;b>app.use(helmet())&lt;/b></code></pre></div>\n<p>This sets all the necessary headers in response.</p>\n<p>To set the headers individually:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">app.use(helmet({\n  frameguard: {\n    action: 'deny'\n  }\n}));</code></pre></div>\n<p>For an exhaustive list of security headers that should be set in a web application, check out the <a href=\"https://www.owasp.org/index.php/OWASP_Secure_Headers_Project\">OWASP Secure Headers Project</a>.</p>\n<p><strong>NOTE:</strong> In some web servers, the security headers can be set in the server configuration file itself. For example, in nginx server, we can set the above headers in <em>nginx.conf</em> as shown below:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">add_header X-Frame-Options DENY;\nadd_header X-Content-Type-Options nosniff;\nadd_header X-XSS-Protection 1;\nadd_header Content-Security-Policy \"default-src 'self'\";</code></pre></div>\n<h2>3. Preventing CSRF attacks</h2>\n<p><a href=\"https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29\">Cross site request forgery (CSRF)</a>, also known as <em>XSRF</em>, <em>Sea Surf</em> or <em>Session Riding</em>, is an attack vector that tricks a web browser into executing an unwanted action in an application to which a user is logged in. CSRF attacks specially targets state-changing requests and can force the victim to transfer funds, change email/password and so on.</p>\n<p>CSRFs are typically conducted using social engineering, such as an email or link that tricks the victim into sending a request to a server on behalf of the attacker. The server has no way to distinguish a forged request from a genuine one.</p>\n<p>In NodeJS, to prevent CSRF attack, we usually use the <a href=\"https://github.com/expressjs/csurf\">csurf</a> express middleware:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const cookieParser = require('cookie-parser');\nconst csrf = require('csurf');\nconst bodyParser = require('body-parser');\nconst express = require('express');\n\nconst csrfProtection = csrf({ cookie: true });\nconst parseForm = bodyParser.urlencoded({ extended: false });\n\n// create express app\nconst app = express();\n\n// we need this because \"cookie\" is true in csrfProtection\napp.use(cookieParser());\n\napp.get('/form', csrfProtection, (req, res) => {\n  // pass the csrfToken to the view\n  res.render('send', { csrfToken: req.csrfToken() });\n});</code></pre></div>\n<p>In the view use the CSRF token passed:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>form</span> <span class=\"token attr-name\">action</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/process<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">method</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>POST<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>hidden<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>csrf_token<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{{csrfToken}}<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n\n  Enter amount: <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>number<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>amount<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>submit<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Submit<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span>\n\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>form</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h2>4. Preventing XSS attacks</h2>\n<p>Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted web sites.\nAn attacker can use XSS to send a malicious script to an unsuspecting user. The end user’s browser has no way to know that the script should not\nbe trusted, and will execute the script. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other sensitive information retained by the browser and used with that site. These scripts can even rewrite the content of the HTML page.</p>\n<p>The thumb rule to prevent this category of attack is to always validate and sanitize user data before processing or storing in database. Never trust data coming from user.\nValidation must be done on the server-side as client-side validation can be easily bypassed using tools such as Burp Suite, TamperData etc.</p>\n<p>A common approach to validate and sanitize user data is to use a library like <a href=\"https://github.com/chriso/validator.js\">validator.js</a>.</p>\n<p>Example: To validate an email</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import validator from 'validator';\n\nif(validator.isEmail('foo@bar.com')) {\n  // Process email or store in DB\n}</code></pre></div>\n<p>This library provides a number of validators and sanitizers to filter user inputs.</p>\n<p>Other useful libraries include <a href=\"https://github.com/cure53/DOMPurify\">DOMPurify</a> and <a href=\"https://github.com/yahoo/xss-filters\">xss-filters</a>.</p>\n<p>Here is an example to sanitize user input using xss-filters:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\">const express = require('express');\nconst app = express();\nconst xssFilters = require('xss-filters');\n\napp.get('/', (req, res) => {\n  let firstname = req.query.firstname; //an untrusted input\n  res.send('<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span> Hello, ' + xssFilters.inHTMLData(firstname) + '!<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span>');\n});\n\napp.listen(3000);</code></pre></div>\n<h2>5. Preventing SQL Injection(SQLi) attacks</h2>\n<p>Passing unvalidated user input directly to a SQL statement is vulnerable to <a href=\"https://www.owasp.org/index.php/SQL_Injection\">SQL injection</a> attack.</p>\n<p>Conside the following example:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">// SQL query vulnerable to SQLi\nsql = \"SELECT * FROM users WHERE username='\" + username + \"' AND password='\" + password + \"'\";\n\n// Execute the SQL statement\ndatabase.execute(sql)</code></pre></div>\n<p>Now suppose the user enters the following in the username field:</p>\n<p><code class=\"language-text\">' OR '1'='1' --</code></p>\n<p>The above SQL statement becomes:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">sql = \"SELECT * FROM users WHERE username='\" + ' OR 1=1 -- + \"' AND password='\" + password + \"'\";</code></pre></div>\n<p>This effectively nullifies the need of a password and returns all the users in the database.</p>\n<p>This attack can be completely prevented by using parametrized or prepared statement.</p>\n<p>If you’re using an ORM to access the database (Mongoose, Sequelize etc), the ORM will normally take care of SQL injection by using prepared statements under the hood.</p>\n<h2>6. Secure cookies using cookie flags</h2>\n<p>XSS vulnerability in an application can be used to steal browser cookies. To prevent cookie stealing we can set the <strong>httpOnly</strong> flag of the cookie.\nAdditionaly, we can tell the browser to send cookies only over HTTPS using the <strong>secure</strong> flag.</p>\n<p><strong>secure :</strong> this attribute tells the browser to only send the cookie if the request is being sent over HTTPS.</p>\n<p><strong>HttpOnly :</strong> this attribute is used to help prevent attacks such as cross-site scripting, since it does not allow the cookie to be accessed via JavaScript.</p>\n<p>Example:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">app.use(session({\n  secret: ‘My super secret’,\n  &lt;b>cookie: { httpOnly: true, secure: true }&lt;/b>\n}));</code></pre></div>\n<h2>7. Preventing brute force and DoS attack</h2>\n<p>To prevent our site from overwhelming with a large number of requests, we need to put some kind of rate limiting to our API.</p>\n<p>We can use the <a href=\"https://github.com/tj/node-ratelimiter\">ratelimiter</a> npm package to implement rate limiting. If you are using Express, the <a href=\"https://github.com/nfriedly/express-rate-limit\">express-rate-limit</a> middleware can be used as shown below:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const RateLimit = require('express-rate-limit');\n\nconst limiter = new RateLimit({\n  windowMs: 15*60*1000, // 15 minutes\n  max: 100, // limit each IP to 100 requests per windowMs\n  delayMs: 0 // disable delaying — full speed until the max limit is reached\n});\n\n// apply to all requests\napp.use(limiter);</code></pre></div>\n<h2>8. Error Handling</h2>\n<p>Any error in the application should be handled gracefully by showing a custom error page to the user instead of showing stack trace in the error page\nthereby leaking sensitive infrastructure information like server info.</p>\n<h2>9. Tools of the trade</h2>\n<p><strong>i) <a href=\"https://github.com/nodesecurity/nsp\">The Node Security Project</a></strong>\nTo check the various npm modules for known vulnerabilities, the Node Security Project provides the nsp tool to check for vulnerabilities:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ nsp check</code></pre></div>\n<p><strong>ii) <a href=\"https://snyk.io/\">Synk</a></strong>\nSynk checks the application against Snyk’s open source vulnerability database for any known vulnerabilities in our dependencies.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ npm install -g snyk\n$ cd your-app\n$ snyk test</code></pre></div>\n<p><strong>iii) <a href=\"https://nmap.org/\">nmap</a></strong>\nNmap (“Network Mapper”) is a free and open source utility for network exploration or security auditing.</p>\n<p><strong>iv) <a href=\"http://sqlmap.org/\">sqlmap</a></strong>\nsqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers.</p>\n<p><strong>v) <a href=\"https://portswigger.net/burp\">Burp Suite</a></strong>\nThe must-have tool for application penetration testing. It includes an automated scanner to detect most common vulnerabilities in a web application.</p>\n<h3>Further Readings</h3>\n<p><a href=\"https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project\">OWASP Top 10 Most Critical Web Application Security Risks</a></p>\n<p><a href=\"https://blog.risingstack.com/node-js-security-checklist/\">NodeJS Security Checklist</a></p>","fields":{"slug":"/securing-nodejs-applications/","tags":["nodejs","javascript","security","appsec","infosec"]}}}]}},"pageContext":{"slug":"/tags/security","tag":"security","categories":["Architecture","Coding","DevOps","Engineering","ProjectManagement","QA","Social","TechRadar"]}}