Software Hardening Guide

Sources & Citations

Much of this guide is built on the shoulders of others within the software development community. For expanded information checkout the following articles:

This guide is aimed at being a practical overview to the topics covered above. It is highly focused on the tools and technologies that we use at ESG day to day.

Ensure dependencies are up-to-date

According to OWASP over 70% of exploitations are due to outdated dependencies.

  • Use pip package manager for Python projects
  • Use npm package manager for JavaScript projects
  • Explicitly define the package requirements of your project and allow for patch updates where packages use Semantic Versioning (pip guide, npm guide)
  • Use Dependabot on your repository
    • Will open pull requests against your repository when new package updates are released with analysis of potential conflicts.
  • Use Snyk for early detection of vulnerabilities and license compliance

Explicitly declare acceptable user payloads

  • Don’t trust user input, ever.
    • Always have a serializer clean data prior to operating on it and especially before storing it to the database to avoid SQL injection attacks.
    • Define character limits
      • On serializers and database fields define explicit size limitations to avoid unexpected web request response times or bloat in the database.
      • Don’t trust request headers or query parameters either
        • If you’re allowing filtering using either of these fields, make sure to define the acceptable options and types of values you allow

Verify regular expressions

Prevent abusive requests

  • When an application begins to manage a consistent amount of traffic use throttling to manage usage
  • If malicious actors circumvent the integrated throttling you can utilize Sqreen (their site) Web Application Firewall (WAF) to better orchestrate blocking of IPs.
  • Require authentication for access to applications using Auth0
    • Auth0 provides Single Sign On Support and 2FA management out of the box
    • Can use nextjs-auth0 for frontend support and auth0-python for backend support
  • Associate data with the users and organizations that own it and limit access to that data to only those who have permission to access it

Secure-first code development

Store credentials outside your codebase

Deny HTTP requests

  • Never allow HTTP and always redirect to HTTPS
  • Heroku should manage this for you via their Automated Certificate Management system
  • If you need a certificate for an application that isn’t running on Heroku, check if your cloud platform provide has one or if you can use Let’s Encrypt.
  • If you are using a different communication technology the same principle applies, you should always use a secured line of communication. For example if you’re using MQTT in your application you should follow MQTT Security Fundamentals and set up your deployment to use TLS / SSL.

Enable certificate checking

Log and monitor suspicious behavior

  • As you move towards a 1.0.0 release you should begin to integrate logging of potential suspicious behavior which can include:
    • Successful and unsuccessful logins
    • Password resets
    • Changes to access levels
    • Authorization failures
  • You can use DataDog for anomaly detection
  • You can use io to monitor for repeat errors and issues
  • You can use Sqreen to monitor suspicious requests
  • Work with your team to perform risk assessments and determine what level of logging is right for your application and project.

Limit your own access

  • Use two-factor authentication wherever possible
  • Lock your computer screen any time you’re not at your workstation
  • Use unique passwords across accounts and services
  • As discussed above use authentication and permissions to manage access to data
  • Only grant access to those that have a role or responsibility that requires access. Work with your team to determine who should have what access.

Benchmark Response Times

  • Web servers should respond to requests in less than 2 seconds and should never exceed 30 seconds. If a response does not happen in 30 seconds the request will be canceled, and an error will be sent to the end user.
    • Long running background application tasks should use Worker dynos for execution.
  • Use pagination to limit the number of objects returned in a request
  • Enable filtering to allow users to filter the amount of data that is returned from the API


Separate Environments

  • Never develop on a production or staging server
    • We’ve spent many years working to create a continuous deployment pipeline that allows you to deploy code to test, staging, and production environments in minutes.
    • We’ve done this because we created many fires in the past by not following this rule and we want to protect you from them :).
  • When developing, fork from the repository you’re working on, clone the code locally to your machine, follow the README to stand up the local deployment (should use Docker Compose for backend applications and npm for frontend applications)
  • Once you’ve committed your changes, push them to your fork and create a pull request. This pull request will automatically trigger CircleCI to run all unit tests on your code and let you know if anything broke.
  • Once tests have passed request reviews on your changes and after you’ve fixed any open requests merge the code into the intended environment (production for pre-1.0.0 releases, and staging for releases after 1.0.0)


Encrypt Data at Rest

  • Always encrypt data in transit and at rest. We covered encryption in transit above.
  • When in doubt connect with your team to figure out what aligns with your objectives.


Use Frameworks

Frameworks won’t protect you from every threat but they do assist in facilitating best practices and protect from common issues that lead to exploits like Cross Site Request Forgery and Clickjacking. They also help protect the data in your database by providing serializers and object relational mapping systems, some of which was discussed above. The frameworks that are approved for usage are:


Collaborate on Changes

When you are living in your head, you are often attempting to control things outside your control through over-analysis. The problem-solving mind thinks it has all of the solutions, leading to constant thinking – Steve Rose PhD. It doesn’t, no one knows everything, and no one is immune to cognitive bias.

That’s why you should get your changes in front of others as quickly as possible, preferably before a line of code is written. It’s why we define experiments, prototype with diagrams and tools like Google Slides & Google Sheets, have policies requiring team members to open up pull requests within a day of starting any new development, and create feedback loops at each step of the process.

  • Coach and be coached through constructive peer reviews
  • Start gathering feedback from others as quickly as possible
    • Share your changes with other team members, stakeholders, and community members as much as possible to get multiple perspectives.
    • If a pull request is not yet ready for review or merger, you should include “WIP” in the pull request title to indicate it is a work in progress.
  • Collaborating helps to improve readability, reusability, security, stability, usability, and effectiveness in moving the needle towards meeting objectives
  • Conduct peer reviews prior to merger into upstream branches, doing so helps reduce change failure rates.
  • Automate testing new functions as you work, this helps reviewers better understand what your functionality does
    • Unsure of what to test or how much testing to do? Automate the manual tests you’re doing to verify that your function works. Use the manual tests as a baseline for what you expect your function(s) to accomplish in your experiment.
    • Manual tests should be stored alongside automated tests to maintain ease of access and project structure when possible. They should be documented in markdown files that can be easily followed by other team members.
      • Documenting manual tests helps us to better understand compiling technical debt and effort necessary to validate specific pieces of functionality.
      • It helps us to hand off validation for reused functionality like authentication to other parties so that validation can be done routinely and benchmarks can be recorded accordingly.
    • Label changes as bug, enhancement, or breaking change to inform reviewers of what they’re looking at and to help automate other activities like release note creation.
    • Make your pull request titles concise with a short explanation of what changes are contained in the pull request.
    • Include videos of your change in your pull requests or relevant tickets. This further helps others to understand what your change does and provide you with more relevant feedback. Tools like Loom make it easy to quickly capture walkthrough videos.
    • Keep pull requests scoped to a single change whether it be a bug fix, feature, or modification to existing function. Sprawling pull requests:
      • Are difficult to understand and review
      • Are difficult to document and communicate to users and stakeholders
      • Are difficult to test and validate leading to increased failure rates
      • Can bog down the development pipeline
        • Create unmanageable merge conflicts for other team members
        • Can create difficulties when needing to roll back, such as when many database migrations are made
        • Reduce the time to identify whether a change should be kept or killed
        • Reduce the lead time for change of the pipeline
        • Reduce the deployment frequency of the pipeline. Some examples being:
          • Causing team members to wait for sections of code being touched to be merged in so they can make other modifications to them
          • Causing team members to wait for one specific change from the large pull request to be merged in to work on integration functionality
        • Delay feedback loops with end users
        • Create too many modifications to know what impact any individual one has on reaching objectives

Get Support On Your Top Technology Problems

Blog Author:


Sign up for our Newsletter and stay up to date on the latest at ESG USA.  New blog posts, newsletters, case studies, and more.