UNPKG

5.45 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.verifySignature = void 0;
4const builder_util_runtime_1 = require("builder-util-runtime");
5const child_process_1 = require("child_process");
6const os = require("os");
7// $certificateInfo = (Get-AuthenticodeSignature 'xxx\yyy.exe'
8// | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains("CN=siemens.com")})
9// | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }
10function verifySignature(publisherNames, unescapedTempUpdateFile, logger) {
11 return new Promise(resolve => {
12 // Escape quotes and backticks in filenames to prevent user from breaking the
13 // arguments and perform a remote command injection.
14 //
15 // Consider example powershell command:
16 // ```powershell
17 // Get-AuthenticodeSignature 'C:\\path\\my-bad-';calc;'filename.exe'
18 // ```
19 // The above would work expected and find the file name, however, it will also execute `;calc;`
20 // command and start the calculator app.
21 //
22 // From Powershell quoting rules:
23 // https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7
24 // * Double quotes `"` are treated literally within single-quoted strings;
25 // * Single quotes can be escaped by doubling them: 'don''t' -> don't;
26 // * Backticks can be escaped by doubling them: 'A backtick (``) character';
27 //
28 // Also note that at this point the file has already been written to the disk, thus we are
29 // guaranteed that the path will not contain any illegal characters like <>:"/\|?*
30 // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
31 const tempUpdateFile = unescapedTempUpdateFile.replace(/'/g, "''").replace(/`/g, "``");
32 // https://github.com/electron-userland/electron-builder/issues/2421
33 // https://github.com/electron-userland/electron-builder/issues/2535
34 child_process_1.execFile("powershell.exe", [
35 "-NoProfile",
36 "-NonInteractive",
37 "-InputFormat",
38 "None",
39 "-Command",
40 `Get-AuthenticodeSignature '${tempUpdateFile}' | ConvertTo-Json -Compress | ForEach-Object { [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($_)) }`,
41 ], {
42 timeout: 20 * 1000,
43 }, (error, stdout, stderr) => {
44 try {
45 if (error != null || stderr) {
46 handleError(logger, error, stderr);
47 resolve(null);
48 return;
49 }
50 const data = parseOut(Buffer.from(stdout, "base64").toString("utf-8"));
51 if (data.Status === 0) {
52 const name = builder_util_runtime_1.parseDn(data.SignerCertificate.Subject).get("CN");
53 if (publisherNames.includes(name)) {
54 resolve(null);
55 return;
56 }
57 }
58 const result = `publisherNames: ${publisherNames.join(" | ")}, raw info: ` + JSON.stringify(data, (name, value) => (name === "RawData" ? undefined : value), 2);
59 logger.warn(`Sign verification failed, installer signed with incorrect certificate: ${result}`);
60 resolve(result);
61 }
62 catch (e) {
63 logger.warn(`Cannot execute Get-AuthenticodeSignature: ${error}. Ignoring signature validation due to unknown error.`);
64 resolve(null);
65 return;
66 }
67 });
68 });
69}
70exports.verifySignature = verifySignature;
71function parseOut(out) {
72 const data = JSON.parse(out);
73 delete data.PrivateKey;
74 delete data.IsOSBinary;
75 delete data.SignatureType;
76 const signerCertificate = data.SignerCertificate;
77 if (signerCertificate != null) {
78 delete signerCertificate.Archived;
79 delete signerCertificate.Extensions;
80 delete signerCertificate.Handle;
81 delete signerCertificate.HasPrivateKey;
82 // duplicates data.SignerCertificate (contains RawData)
83 delete signerCertificate.SubjectName;
84 }
85 delete data.Path;
86 return data;
87}
88function handleError(logger, error, stderr) {
89 if (isOldWin6()) {
90 logger.warn(`Cannot execute Get-AuthenticodeSignature: ${error || stderr}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`);
91 return;
92 }
93 try {
94 child_process_1.execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", "ConvertTo-Json test"], { timeout: 10 * 1000 });
95 }
96 catch (testError) {
97 logger.warn(`Cannot execute ConvertTo-Json: ${testError.message}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`);
98 return;
99 }
100 if (error != null) {
101 throw error;
102 }
103 if (stderr) {
104 logger.warn(`Cannot execute Get-AuthenticodeSignature, stderr: ${stderr}. Ignoring signature validation due to unknown stderr.`);
105 return;
106 }
107}
108function isOldWin6() {
109 const winVersion = os.release();
110 return winVersion.startsWith("6.") && !winVersion.startsWith("6.3");
111}
112//# sourceMappingURL=windowsExecutableCodeSignatureVerifier.js.map
\No newline at end of file