Bläddra i källkod

fix(desktop): isolate Windows signature inspection modules

winewill 3 veckor sedan
förälder
incheckning
c781e85e92

+ 1 - 1
apps/desktop/scripts/windows-runtime-signature.d.mts

@@ -6,7 +6,7 @@ export interface WindowsRuntimeSignature {
 }
 
 /**
- * Read Windows trust, timestamp and signer identity without accessing the private key.
+ * Read Windows trust, timestamp and signer identity using the engine's bundled modules, without accessing the private key.
  * @param path File to inspect.
  * @returns Authenticode verification result.
  */

+ 3 - 2
apps/desktop/scripts/windows-runtime-signature.mjs

@@ -7,13 +7,14 @@ import { scrubWindowsSigningEnvironment } from './windows-sign.mjs'
 import { recordPackagingEvent } from './packaging-run.mjs'
 
 /**
- * Read Windows trust, timestamp and signer identity without accessing the private key.
+ * Read Windows trust, timestamp and signer identity using the engine's bundled modules, without accessing the private key.
  * @param {string} path File to inspect.
  * @returns {Promise<{status: string, timestamped: boolean, thumbprint: string | null}>} Authenticode verification result.
  */
 export async function inspectWindowsRuntimeSignature(path) {
+  // Node can inherit PowerShell 7's module search path while launching Windows PowerShell 5.
   const { stdout, stderr } = await promisify(execFile)('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command',
-    '$ErrorActionPreference="Stop"; $s=Get-AuthenticodeSignature -LiteralPath $env:DSH_RUNTIME_VERIFY_FILE; [pscustomobject]@{status=[string]$s.Status;timestamped=($null -ne $s.TimeStamperCertificate);thumbprint=$s.SignerCertificate.Thumbprint}|ConvertTo-Json -Compress'], {
+    '$ErrorActionPreference="Stop"; [Console]::OutputEncoding=[System.Text.UTF8Encoding]::new(); Import-Module "$PSHOME/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1" -ErrorAction Stop; Import-Module "$PSHOME/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1" -ErrorAction Stop; $s=Get-AuthenticodeSignature -LiteralPath $env:DSH_RUNTIME_VERIFY_FILE; [pscustomobject]@{status=[string]$s.Status;timestamped=($null -ne $s.TimeStamperCertificate);thumbprint=$s.SignerCertificate.Thumbprint}|ConvertTo-Json -Compress'], {
     env: { ...scrubWindowsSigningEnvironment(process.env), DSH_RUNTIME_VERIFY_FILE: path },
     encoding: 'utf8', windowsHide: true, timeout: 60_000, maxBuffer: 64 * 1024,
   })

+ 7 - 1
apps/desktop/tests/primary-runtime-signing.spec.ts

@@ -3,7 +3,7 @@ import { tmpdir } from 'node:os'
 import { join } from 'node:path'
 import { afterEach, expect, it, vi } from 'vitest'
 import { signWindowsPrimaryRuntime, windowsRuntimeCode } from '../scripts/sign-primary-runtime.ts'
-import { preserveWindowsRuntimeSignature } from '../scripts/windows-runtime-signature.mjs'
+import { inspectWindowsRuntimeSignature, preserveWindowsRuntimeSignature } from '../scripts/windows-runtime-signature.mjs'
 import { createPackagingRun } from '../scripts/packaging-run.mjs'
 
 const roots: string[] = []
@@ -123,6 +123,12 @@ it('refuses an empty runtime without declaring successful validation', async ()
   expect(smoke).not.toHaveBeenCalled()
 })
 
+it.skipIf(process.platform !== 'win32')('reads a Windows system signature without using signing hardware', async () => {
+  const signature = await inspectWindowsRuntimeSignature(join(process.env.SystemRoot!, 'System32', 'cmd.exe'))
+  expect(signature.status).toBe('Valid')
+  expect(signature.thumbprint).toMatch(/^[A-F\d]{40}$/iu)
+}, 70_000)
+
 it('preserves only identical, valid runtime copies and records verification without signing', async () => {
   const sourceRoot = await realpath(await fixture(['python.exe']))
   const destinationRoot = await realpath(await fixture(['python.exe']))