What have I done lately? – Part 2: Automation of Dependency Upgrades

During my time at Atlassian I made a bunch of contributions to codebases for improving the way my teams’ code flowed through the build pipeline to get to production, using systems that included Bitbucket, Spinnaker and Renovate.

This post will focus on what I have been working on in relation to securely handling upgrades of dependencies with Renovate and Dependabot.

Renovate

Some context

Around 2024 – 2025 within my department at Atlassian we had a drive to be pro-active about picking up new versions of libraries in use by our services to ensure that we would not get caught out if a security vulnerability was exploited before we had gotten around to addressing it.

I don’t have all of the historical context available now, so this explanation may not be 100% accurate, but my expectation is that there had been automation put in place to automatically detect when a CVE (Common Vulnerability or Exposure) had been raised in relation to any third party library in the public domain then it would be flagged up when that particular library was detected as being referenced for inclusion in any of our codebases. Getting a VULN ticket in Jira would effectively start a timer for when the team would need to address the issue.

The majority of the time the quickest way to address a VULN issue was to bump the version number of the dependency and get the impacted service to be deployed with the non-vulnerable version.

Automation of version bumps

The pro-active approach would involve detecting that a new version of a dependency has been created, and automatically applying the version upgrade in the services. This would cut out the disruption of developers receiving VULN tickets from outside of the team’s regular workflow by having the service codebase already be up to date.

The level of automation involved for applying some of these version upgrades meant that the dependency upgrades were never reviewed by a developer, so I found it ironic that the only code that was not reviewed was the code being developed within Atlassian.

The potential downside to the automation of minor version upgrades is that this can leave systems exposed to a bug or vulnerability that is introduced in an upgrade. My personal preference would be for such automation to tie in only when a known vulnerability or significant bug has been addressed.

Avoiding major version upgrades breaking changes

When I re-joined Atlassian in late 2025 I noticed that the projects that my new team maintained would regularly receive a pull request from a Renovate bot that had failed to build the project after attempting to upgrade to the latest available version of a dependency.

Whenever a pull request came in it would trigger emails and or Slack notifications to all of the developers on the team that owned the repository, so I recognised that this noise was a disruption that needed to be addressed.

The pattern of failing builds associated with a dependency version upgrade attempt was almost always down to the fact that the new version was a major version increment – the well established signal from library developers that their new version includes changes that may be incompatible with the earlier versions’ API.

For some situations it was not feasible to update our code to migrate it to the new major version of a dependency, so I needed to update the Renovate configuration to specify that it should limit version upgrade attempts for that library to be below the next major version.

Since the majority of our services were based on the same version of a particular framework that controlled several of the problematic dependencies, I was able to apply the fix in a single centralised base configuration.

GitHub Dependabot

For a few of my hobby projects I use GitHub as the source code hosting service, which is a good way to keep myself aware of the mainstream tooling when my work projects are in Bitbucket.

Several years ago GitHub enabled developers to set up configuration to automatically raise pull requests for dependency version upgrade changes. If I recall correctly, in the Java space that initially only covered maven dependency management which might have put a dampener on projects that would otherwise be interested in Gradle or some other tool for managing dependencies. There seems to have been some progress made for support for more tools in GitHub dependencies by now (May 2026).

[ Sidenote: Writing blog posts like this stimulates me into a “thinking aloud” curiosity, so I have just gone back to try out enabling Dependabot for a project with Gradle ].

Avoiding supply chain attacks

In March and April of 2026 several open source projects had one or more versions of their artifacts corrupted by hackers and uploaded to the respective central repository for the languages involved (e.g. NodeJS and Python).

If an individual or a tool was unlucky enough to have checked for the latest available version of the particular library after the hack and before the discovery and withdrawal then they would end up with the dodgy code on their systems.

Based on the pattern of maintainers and other third parties detecting and removing the compromised versions, I am applying a slightly more cautious approach to upgrading dependencies with Dependabot, by setting up dependabot to default to using a cooldown period before considering a version upgrade as appropriate for inclusion of a dependency upgrade.

version: 2
updates:
  - package-ecosystem: "maven"
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 5

This approach won’t safeguard from all supply chain attacks, so I’m hoping to look further into this area. That may either show up in later posts, or become part of my next job.

Looking ahead

My gut feeling is that the detection of malicious behaviours introduced into dependencies will become essential for smaller projects, rather than only being a concern for enterprise systems.

There will be more focus on separation of concerns for build pipelines, so a tool that is intended for one purpose cannot be used as an attack vector for influencing other systems.

For example, if I have a GItHub action in place that is intended to scan an artifact or generate an SBOM from a build then it will not run in an environment that has API keys or access tokens for any other system, and there should be checks in place to verify that it has not attempted to touch files or make network calls out to anything beyond the expected bahaviour.

It must become more common to apply the mindset of, “Who guards the guards?” when integrating tooling to our builds.