Skip to content

[REGRESSION]: AzureFunctionApp@2 v2.273.0 — archiver 7.0 upgrade stores symlinks as plain files in deployment zip #22154

@yodelzach

Description

@yodelzach

New issue checklist

Task name

AzureFunctionApp

Breaking task version

2.273.0

Last working task version

2.272.0

Regression Description

AzureFunctionApp@2 v2.273.0 stores Unix symlinks as plain files (containing the target
path as text) in the deployment zip, instead of following them and including the actual
file contents. This causes complete outages for Node.js Function Apps that use local
module references ("file:./my-local-module" in package.json), which npm resolves as
symlinks in node_modules/.

After upgrading from v2.272.0 to v2.273.0, node_modules/my-local-module (a symlink to
../my-local-module) is stored in the deployment zip as a 9-byte file containing the text
"../my-local-module" instead of the actual directory contents. On the Windows Function
App host, this results in:

Cannot find module 'my-local-module/some-file.js'

Every function in the app fails. The same code deployed via func azure functionapp publish (Azure Functions Core Tools) works fine.

The root cause is PR #22096 ("Fix CVE-2026-41672"), which ran npm audit fix and
cascaded into a major transitive dependency bump:

azure-pipelines-tasks-webdeployment-common: 4.272.1 → 4.274.0
└── archiver: 5.x → 7.0.1 (MAJOR version bump)
└── archiver-utils: 4.x → 5.0.2

archiver 7.0 changed directory traversal from fs.stat() (follows symlinks transparently)
to fs.lstat() (preserves symlinks as-is). The archiver does not set dereference: true,
so symlinks are stored verbatim in the zip.

Expected: Symlinks in node_modules/ are followed and their contents included in the
deployment zip (as in v2.272.0).

Actual: Symlinks are stored as small files whose content is the target path string.

Environment type (Please select at least one enviroment where you face this issue)

  • Self-Hosted
  • Microsoft Hosted
  • VMSS Pool
  • Container

Azure DevOps Server type

dev.azure.com (formerly visualstudio.com)

Azure DevOps Server Version (if applicable)

No response

Operation system

Ubuntu 22.04 (build agent) → Windows (Function App host)

Relevant log output

Exception: Worker was unable to load function myFunction_http: 
'Cannot find module 'my-local-module/core/SomeManager.js'
Require stack:
- C:\home\site\wwwroot\core\SomeManager.js
- C:\home\site\wwwroot\myFunction_http\index.js
- C:\Program Files (x86)\SiteExtensions\Functions\4.1048.200\workers\node\dist\src\worker-bundle.js'

Full task logs with system.debug enabled

UNSUCCESSFUL RUN
  Task: AzureFunctionApp 2.273.0
  Kudu inspection of deployed artifact:
  > dir node_modules\my-local-module
  05/07/2026  02:14 AM                 9 my-local-module    ← 9-byte file, NOT a directory

type node_modules\my-local-module
../my-local-module ← symlink target stored as file content

SUCCESSFUL RUN
  Task: AzureFunctionApp 2.272.0
  Kudu inspection of deployed artifact:
  > dir node_modules\my-local-module
  05/06/2026  11:30 PM              .
  05/06/2026  11:30 PM              ..
  05/06/2026  11:30 PM              src        ← real directory with actual files
  05/06/2026  11:30 PM              lib
  05/06/2026  11:30 PM              utils
  

Repro steps

# 1. Create a Node.js Function App with a local module dependency:
#    package.json: { "dependencies": { "my-local-module": "file:./my-local-module" } }
#    This causes npm install to create: node_modules/my-local-module → ../my-local-module (symlink)
#
# 2. Deploy using AzureFunctionApp@2 task v2.273.0
#
# 3. Observe: node_modules/my-local-module on the Function App is a 9-byte file 
#    containing "../my-local-module" instead of the actual directory contents
#
# Minimal pipeline YAML to reproduce:

trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
  - checkout: self
    submodules: true

  - task: NodeTool@0
    inputs:
      versionSpec: '18.x'

  - script: |
      npm install
      npm run build --if-present
    displayName: 'Build'

  - task: ArchiveFiles@2
    inputs:
      rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
      includeRootFolder: false
      archiveType: '7z'
      archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).7z'

  # Deploy using AzureFunctionApp@2 — this re-zips with archiver 7.0
  # which stores the node_modules/my-local-module symlink as a plain file
  - task: AzureFunctionApp@2
    inputs:
      azureSubscription: '<subscription>'
      appType: 'functionApp'
      appName: '<function-app-name>'
      package: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).7z'

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions