Repository: actions/toolkit
Pull request #1563 (2023-10-16 16:22:58)

Use sha256 instead of md5 for artifact v4 integrity hash
Recent MSFT guidance is to not use MD5, even for integrity. This updates the upload response to use SHA256 instead.

Related:
- https://github.com/github/actions-results-team/issues/1907


Patch:
diff --git a/package-lock.json b/package-lock.json
index fe39020..c0fd14e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -185,12 +185,12 @@
       }
     },
     "node_modules/@babel/generator": {
-      "version": "7.22.10",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
-      "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+      "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.22.10",
+        "@babel/types": "^7.23.0",
         "@jridgewell/gen-mapping": "^0.3.2",
         "@jridgewell/trace-mapping": "^0.3.17",
         "jsesc": "^2.5.1"
@@ -225,22 +225,22 @@
       }
     },
     "node_modules/@babel/helper-environment-visitor": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
-      "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+      "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-function-name": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
-      "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+      "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
       "dev": true,
       "dependencies": {
-        "@babel/template": "^7.22.5",
-        "@babel/types": "^7.22.5"
+        "@babel/template": "^7.22.15",
+        "@babel/types": "^7.23.0"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -332,9 +332,9 @@
       }
     },
     "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
-      "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+      "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
@@ -449,9 +449,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.22.13",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.13.tgz",
-      "integrity": "sha512-3l6+4YOvc9wx7VlCSw4yQfcBo01ECA8TicQfbnCPuCEpRQrf+gTUyGdxNw+pyTUyywp6JRD1w0YQs9TpBXYlkw==",
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+      "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
       "dev": true,
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -650,33 +650,33 @@
       }
     },
     "node_modules/@babel/template": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
-      "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+      "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
       "dev": true,
       "dependencies": {
-        "@babel/code-frame": "^7.22.5",
-        "@babel/parser": "^7.22.5",
-        "@babel/types": "^7.22.5"
+        "@babel/code-frame": "^7.22.13",
+        "@babel/parser": "^7.22.15",
+        "@babel/types": "^7.22.15"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.22.11",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz",
-      "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==",
+      "version": "7.23.2",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+      "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
       "dev": true,
       "dependencies": {
-        "@babel/code-frame": "^7.22.10",
-        "@babel/generator": "^7.22.10",
-        "@babel/helper-environment-visitor": "^7.22.5",
-        "@babel/helper-function-name": "^7.22.5",
+        "@babel/code-frame": "^7.22.13",
+        "@babel/generator": "^7.23.0",
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-function-name": "^7.23.0",
         "@babel/helper-hoist-variables": "^7.22.5",
         "@babel/helper-split-export-declaration": "^7.22.6",
-        "@babel/parser": "^7.22.11",
-        "@babel/types": "^7.22.11",
+        "@babel/parser": "^7.23.0",
+        "@babel/types": "^7.23.0",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       },
@@ -694,13 +694,13 @@
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.22.11",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
-      "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+      "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
       "dev": true,
       "dependencies": {
         "@babel/helper-string-parser": "^7.22.5",
-        "@babel/helper-validator-identifier": "^7.22.5",
+        "@babel/helper-validator-identifier": "^7.22.20",
         "to-fast-properties": "^2.0.0"
       },
       "engines": {
diff --git a/packages/artifact/src/internal/upload/blob-upload.ts b/packages/artifact/src/internal/upload/blob-upload.ts
index 42a3fbd..2bed1f3 100644
--- a/packages/artifact/src/internal/upload/blob-upload.ts
+++ b/packages/artifact/src/internal/upload/blob-upload.ts
@@ -18,9 +18,9 @@ export interface BlobUploadResponse {
   uploadSize?: number
 
   /**
-   * The MD5 hash of the uploaded file. Empty if the upload failed
+   * The SHA256 hash of the uploaded file. Empty if the upload failed
    */
-  md5Hash?: string
+  sha256Hash?: string
 }
 
 export async function uploadZipToBlobStorage(
@@ -48,9 +48,9 @@ export async function uploadZipToBlobStorage(
     onProgress: uploadCallback
   }
 
-  let md5Hash: string | undefined = undefined
+  let sha256Hash: string | undefined = undefined
   const uploadStream = new stream.PassThrough()
-  const hashStream = crypto.createHash('md5')
+  const hashStream = crypto.createHash('sha256')
 
   zipUploadStream.pipe(uploadStream) // This stream is used for the upload
   zipUploadStream.pipe(hashStream).setEncoding('hex') // This stream is used to compute a hash of the zip content that gets used. Integrity check
@@ -68,8 +68,8 @@ export async function uploadZipToBlobStorage(
     core.info('Finished uploading artifact content to blob storage!')
 
     hashStream.end()
-    md5Hash = hashStream.read() as string
-    core.info(`MD5 hash of uploaded artifact zip is ${md5Hash}`)
+    sha256Hash = hashStream.read() as string
+    core.info(`SHA256 hash of uploaded artifact zip is ${sha256Hash}`)
   } catch (error) {
     core.warning(
       `Failed to upload artifact zip to blob storage, error: ${error}`
@@ -91,6 +91,6 @@ export async function uploadZipToBlobStorage(
   return {
     isSuccess: true,
     uploadSize: uploadByteCount,
-    md5Hash
+    sha256Hash
   }
 }
diff --git a/packages/artifact/src/internal/upload/upload-artifact.ts b/packages/artifact/src/internal/upload/upload-artifact.ts
index 4d360d0..ced0556 100644
--- a/packages/artifact/src/internal/upload/upload-artifact.ts
+++ b/packages/artifact/src/internal/upload/upload-artifact.ts
@@ -99,9 +99,9 @@ export async function uploadArtifact(
     size: uploadResult.uploadSize ? uploadResult.uploadSize.toString() : '0'
   }
 
-  if (uploadResult.md5Hash) {
+  if (uploadResult.sha256Hash) {
     finalizeArtifactReq.hash = StringValue.create({
-      value: `md5:${uploadResult.md5Hash}`
+      value: `sha256:${uploadResult.sha256Hash}`
     })
   }
 


Test patch:
diff --git a/packages/artifact/__tests__/upload-artifact.test.ts b/packages/artifact/__tests__/upload-artifact.test.ts
index c36a9ad..955929b 100644
--- a/packages/artifact/__tests__/upload-artifact.test.ts
+++ b/packages/artifact/__tests__/upload-artifact.test.ts
@@ -65,7 +65,7 @@ describe('upload-artifact', () => {
       Promise.resolve({
         isSuccess: true,
         uploadSize: 1234,
-        md5Hash: 'test-md5-hash'
+        sha256Hash: 'test-sha256-hash'
       })
     )
     jest
@@ -334,7 +334,7 @@ describe('upload-artifact', () => {
       Promise.resolve({
         isSuccess: true,
         uploadSize: 1234,
-        md5Hash: 'test-md5-hash'
+        sha256Hash: 'test-sha256-hash'
       })
     )
     jest