Skip to content

The trials and tribulations of secure software development

Discover effective strategies for managing third-party libraries, tackling security challenges & handling technical debt in secure software development.

software developer

In this blog post I’ll talk a little about how we approach the security lifecycle of our secure software development process. This isn’t inherently the ‘correct’ approach, but it does fit our needs and scratches the itch from the days gone by of security testing applications.

One of the biggest issues I’ve personally seen in my past as a security consultant is the difficulty that my clients had with keeping their software up to date. Primarily, this was the third-party libraries that were imported into their applications.

Here at CovertSwarm the situation is no different. Whilst we have a strong stance for developing our own components and libraries to use internally, there is often a need to initially utilise third-party software for our rate of development. Clearly, using paid or open source modules has its pros and cons; with the negatives being that a migration will eventually have to occur if the library ever becomes unsupported or breaking changes are implemented, with the positives being mostly off-the-shelf implementation that aid in the speed of development.

As for custom in-house developed components the positives greatly outweigh the need to invest time for the initial development given the full control over the libraries and components that we create. This fully extends to the control over dependencies, which is often a pitfall of any open-source libraries.

Getting your priorities straight

Ok, so you have a load of applications for your company. Let’s give a simpler example with a stack of a user interface, an API, and a database. Assuming there’s a load of security issues each, which do you tackle first?

As a security professional, I would always suggest the first few things that are addressed are those that are identified as being most impactful. This could be anything that could affect the confidentiality or integrity of the data, or critically, the availability of the data (and subsequently the application and/or infrastructure).

An example of an issue affecting the confidentiality of the data would be where there is an IDOR (insecure direct object reference) weakness, which when coupled with authorisation control weaknesses this could allow one user to access the data of another. Similarly, the impact of an integrity issue would be where one user could modify the data of another (usually these often appear side by side).

Availability is more of a broad term and could be something as trivial as the lack of rate limiting in application allowing a malicious person to drain all the resources from the API (and possibly the database). Or it could be that a user could delete the data of another user, rendering their data inaccessible. There are many more examples, and this isn’t a complete picture but more of a general overview to put things into perspective.

So, here we now have a general priority list of vulnerabilities or weaknesses that should be focused upon as a matter of importance. As with any ‘bug’ logging, having reproducible steps/scenarios for the development team is crucial.

Third-party libraries

Great, so we have a rough idea of which types of issues should be more important to resolve now and to then go down the list. How does this relate to software libraries?

I’m glad you I asked!

What we’re looking for with any third-party libraries (paid or otherwise open-source) is:

  • Coding weaknesses, such as using legacy or otherwise dangerous functionality
  • Legacy dependants within the library itself (such as the wonders of NPM package dependencies)
  • Insecurely imported JavaScript libraries from CDNs or third-party providers

Tooling

Additionally, anyone that has a SAST (Static application security testing) process within their development lifecycle should benefit from easier identification of both coding issues (we’ll cover that separately) and library/module/package issues (both direct and from dependents). There are a multitude of services available that provide this functionality, so we won’t name names here, but I would recommend ensuring you have a tool that can provide the level and depth of output to suit your teams’ needs.

The main requirement from my standpoint is that the output is clear (X vulnerability on Y component) and provides a good direction (e.g. on line Z) and explanation of the issue. Ideally, a tool should also provide a recommendation for remediation in good detail.

Suggestions and approach

With any imported third-party libraries there is always going to be security vulnerabilities, as with any software. One of the biggest issues that I’ve seen personally is that these libraries either have dependencies of their own, which the original maintainers do not keep maintained for security issues, or that the internal development team do not keep imported scripts updated.

For scenarios where there are dependency issues with third-party libraries there are a few mitigations that can be put in place:

  1. Your development team could fork the original project, make the security fixes, and then issue a pull request to the open-source maintainer.
  2. Find an alternative library and migrate to it.
  3. Build your own internal library and deprecate the original.
  4. Your development team could fork the original project and maintain it in-house. Depending upon the license this could be troublesome commercially (and it goes against the mantra of open-source, community-built projects).
  5. Pin dependencies for certain application types (such as with React or Angular) and deal with the fallout of package versioning errors.

Personally, I see that as a rough priority order. I’m a big fan of giving back to the ‘community’ and that is one of the values we hold dear at CovertSwarm. There are of course downsides to maintaining a fork: either you fork entirely and maintain in isolation or you continue to update the forked version from the main repository. You should always be mindful of license applicability too.

Where there are libraries imported from third-party sites (CDNs, etc.) and such (e.g., as a jQuery version imported in an index.html file), it can be a little trickier to handle especially if they’re loaded and stored within the application and not pulled from a third-party CDN directly in the application.

As a suggestion, I would document any libraries that are pulled in like this and keep a record of the version (and repository/file/etc.), which can then be used with any regular security review to ensure these are updated. Of course, don’t forget to update the SRI (Subresource Integrity) values!

If you do have SAST tools that will detect these types of imports/stored files, then these should provide a much more streamlined method of detecting and alerting on older/insecure libraries.

Of course, with this the simplest answer is to update the imported library and pull in the latest and greatest. But this does come with some possible implications of updating the application to match and new or breaking functionality changes.

Technical Debt

Everyone’s favourite topic, I’m sure, is technical debt within an application. For anyone that doesn’t know, technical debt is the task you give to new hires to do wh… I jest (although it can be useful for a fresh set of eyes to review older components of an application).

Technical debt can amount over time and could be something as mundane like the use of styles and classes within a user interface, or many individual components that could be replaced with a re-usable component. Another example is something much larger like a permissions system being inefficient in an API, or even a database schema using epoch values instead of timestamps that can impact localisation for end-users.

Whichever your poison, we all have it, and we all have to live with it to some degree. What should happen though is a continued reduction in the number of items on the list.

Our approach

At CovertSwarm we’re constantly looking to improve the Offensive Operations Center, and that includes addressing any technical debt that we’ve accrued over time. We’re not afraid to bite the bullet and implement drastic changes for the performance benefits or extensibility capabilities that could be gained from addressing technical debt.

My personal suggestions for how to approach technical debt (and bear in mind we have a fairly small team here that is much more intimate with the codebase) would be:

  1. Know and understand where the issues are. Document them if possible and keep this updated.
  2. Regularly discuss items on this list when it comes time to refactor a component or build something new (i.e., when planning and reviewing the backlog). If you have the ability to migrate or update a component during one of these development projects, you should consider it as part of the upcoming work stream.
  3. If an item on the list is important for performance optimisation, even if it is low on the priority list, consider it as a separate development stream to any upcoming projects. You’ll thank yourself later.
  4. Consider incremental improvements if the upcoming project work allows you to have this flexibility. An example here is if you have the capability to develop a component or module that can be reused through the application, you could potentially save code duplication and simplify code readability.

Conclusion

In the constantly changing landscape of software development, with your applications likely being the gateway to your business, keeping these products secure should always be a top priority.

Remember those third-party libraries? They’re like borrowed tools – super handy, but you’ve got to keep an eye on them. CovertSwarm’s approach of utilising open-source contributions and careful management of legacy components shows that it’s not just a “set it and forget it” deal. These libraries need a little TLC to minimise the risk to a business, however small or large.

And with the fan-favourite of technical debt, it’s like the storage cupboard you have in your home – one day you will look for something and will have to clean it out to get to what you were looking for. Technical debt shouldn’t be a burden, but another step in the development. Our own approach of taking small bites, regular communication, and smart prioritisation reduces the feeling of being overwhelmed.

Join the team

We are hiring for our team to further improve our own secure software development efforts. Take a look at the job specification here, and reach out to us with your CV at [email protected] with the title “Software Developer”.