Background

I have been doing the regular maintenance in our Azure DevOps Pipelines of updating the versions of tasks. This usually means you perform one of the following actions

  • Just increment the major version number in the YAML e.g task: MyTask@1 to task: MyTask@2 when there is a newer version of a task available.
  • If the task is out of support and abandoned, swap to a different task, one that is still being supported, that does the same action.
  • Fork the out of date task, and perform the updates to bring it back into support.
  • Swap to a PowerShell/Bash script that wrappers a CLI tool to do the same action - increasingly my go to solution.

It is a shame the first option is often not possible, but don’t get me, or other MVPs on the long running subject of abandoned insecure Azure DevOps extensions

The Problem

The problem I hit today was with the Post Build Cleanup extension from Microsoft Premier Services. This had started reporting the warning

##[warning]Task 'Post Build Cleanup' version 4 (PostBuildCleanup@4) is dependent on a Node version (16) that is end-of-life. Contact the extension owner for an updated version of the task. Task maintainers should review Node upgrade guidance: https://aka.ms/node-runner-guidance

On checking the project repo, I saw that version 4 was the latest version of this task. There is an issue #263 that says the extension has no maintainer, and it is recommended you swap to using a PowerShell script. However, I wondered if the extension could be forked, and that is where it got interesting.

The problem is that the Microsoft Premier Services team choose not to open source the code for their extensions, the project repo is only used to track issues and store archived .VSIX packages. However, with Azure DevOps that is not a complete blocker, as you can:

  1. Pick the option to get download the extension .VSIX package for Azure DevOps Server use in the Azure DevOps marketplace
  2. Rename the .VSIX file to .ZIP
  3. Expand the ZIP file into a folder and then you can have a look at the code

As I said, this is where it got interesting. When I looked on the task.json file I could see the task was setup to use any of three Node versions including Node 20

 "execution": {
        "Node10": {
            "target": "enableCleanup.js",
            "argumentFormat": ""
        },
        "Node16": {
            "target": "enableCleanup.js",
            "argumentFormat": ""
        },
        "Node20": {
            "target": "enableCleanup.js",
            "argumentFormat": ""
        }
    },

So why was I getting the warning about Node 16 when it should have been using Node 20?

The Answer

The issue is that the current Azure DevOps agents, and GitHub runners that use a related codebase, no longer ship with Node 20. If you looking a self hosted runners external folder you will see folders for

  • node10
  • node16
  • node20_1
  • node24

The task can’t find Node 20, as it is replaced by Node 20.1 with it’s numerous security fixes, so the runner falls back to use Node 16 and hence generates the version warning.

The fix, if you forked the extension, or had your own extension showing the same issues, is to change the execution block in the task.json to target Node 20.1

 "execution": {
        "Node10": {
            "target": "enableCleanup.js",
            "argumentFormat": ""
        },
        "Node16": {
            "target": "enableCleanup.js",
            "argumentFormat": ""
        },
        "Node20_1": {
            "target": "enableCleanup.js",
            "argumentFormat": ""
        }
    },

Once this is done Node 16 is not longer used

Summing Up

In this case swapping to the recommended clean-up template is the obvious answer, but it was an interesting exploration to find the root cause of this confusing warning.