|
| 1 | +import _ from 'lodash' |
| 2 | + |
| 3 | +import Debug from 'debug' |
| 4 | +import * as errors from '../errors' |
| 5 | +import os from 'os' |
| 6 | +import { enumerateValues, HKEY } from 'registry-js' |
| 7 | +import type { RegistryValue } from 'registry-js' |
| 8 | + |
| 9 | +const debug = Debug('cypress:server:chrome_policy_check') |
| 10 | +// https://chromeenterprise.google/policies/#Proxy |
| 11 | +// https://chromeenterprise.google/policies/#ProxySettings |
| 12 | +const BAD_PROXY_POLICY_NAMES = [ |
| 13 | + 'ProxySettings', |
| 14 | + 'ProxyMode', |
| 15 | + 'ProxyServerMode', |
| 16 | + 'ProxyServer', |
| 17 | + 'ProxyPacUrl', |
| 18 | + 'ProxyBypassList', |
| 19 | +] |
| 20 | + |
| 21 | +// https://chromeenterprise.google/policies/#Extensions |
| 22 | +const BAD_EXTENSION_POLICY_NAMES = [ |
| 23 | + 'ExtensionInstallBlacklist', |
| 24 | + 'ExtensionInstallWhitelist', |
| 25 | + 'ExtensionInstallForcelist', |
| 26 | + 'ExtensionInstallSources', |
| 27 | + 'ExtensionAllowedTypes', |
| 28 | + 'ExtensionAllowInsecureUpdates', |
| 29 | + 'ExtensionSettings', |
| 30 | + 'UninstallBlacklistedExtensions', |
| 31 | +] |
| 32 | + |
| 33 | +const POLICY_KEYS: string[] = [ |
| 34 | + 'Software\\Policies\\Google\\Chrome', |
| 35 | + 'Software\\Policies\\Google\\Chromium', |
| 36 | +] |
| 37 | + |
| 38 | +const POLICY_HKEYS: HKEY[] = [ |
| 39 | + HKEY.HKEY_LOCAL_MACHINE, |
| 40 | + HKEY.HKEY_CURRENT_USER, |
| 41 | +] |
| 42 | + |
| 43 | +type RegistryValueWithPath = RegistryValue & { fullPath: string } |
| 44 | + |
| 45 | +function warnIfPolicyMatches (policyNames: string[], allPolicies: RegistryValueWithPath[], warningName: Parameters<typeof errors.get>[0], cb: (err: Error) => void) { |
| 46 | + const matchedPolicyPaths = policyNames |
| 47 | + .map((policyName) => _.find(allPolicies, { name: policyName })?.fullPath) |
| 48 | + .filter((path): path is string => Boolean(path)) |
| 49 | + |
| 50 | + if (!matchedPolicyPaths.length) { |
| 51 | + return |
| 52 | + } |
| 53 | + |
| 54 | + cb(errors.get(warningName, matchedPolicyPaths)) |
| 55 | +} |
| 56 | + |
| 57 | +export function getRunner ({ enumerateValues }: { enumerateValues: (hkey: HKEY, key: string) => ReadonlyArray<RegistryValue> }) { |
| 58 | + function getAllPolicies (): RegistryValueWithPath[] { |
| 59 | + return _.flattenDeep( |
| 60 | + POLICY_KEYS.map((key) => { |
| 61 | + return POLICY_HKEYS.map((hkey) => { |
| 62 | + return enumerateValues(hkey, key) |
| 63 | + .map((value): RegistryValueWithPath => ({ |
| 64 | + ...value, |
| 65 | + fullPath: `${hkey}\\${key}\\${value.name}`, |
| 66 | + })) |
| 67 | + }) |
| 68 | + }), |
| 69 | + ) |
| 70 | + } |
| 71 | + |
| 72 | + return function run (cb: (err: Error) => void) { |
| 73 | + try { |
| 74 | + debug('running chrome policy check') |
| 75 | + |
| 76 | + const policies = getAllPolicies() |
| 77 | + const badPolicyNames = _.concat(BAD_PROXY_POLICY_NAMES, BAD_EXTENSION_POLICY_NAMES) |
| 78 | + |
| 79 | + debug('received policies %o', { policies, badPolicyNames }) |
| 80 | + |
| 81 | + warnIfPolicyMatches(badPolicyNames, policies, 'BAD_POLICY_WARNING', cb) |
| 82 | + } catch (err) { |
| 83 | + debug('error running policy check %o', { err }) |
| 84 | + } |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +export function run (cb: (err: Error) => void): void { |
| 89 | + if (os.platform() !== 'win32') { |
| 90 | + return _.noop(cb) |
| 91 | + } |
| 92 | + |
| 93 | + /** |
| 94 | + * Only check on Windows. While it is possible for macOS/Linux to have preferences set that |
| 95 | + * override Cypress's settings, it's never been reported as an issue and would require more |
| 96 | + * native extensions to support checking. |
| 97 | + * https://github.com/cypress-io/cypress/issues/4391 |
| 98 | + */ |
| 99 | + const runner = getRunner({ |
| 100 | + enumerateValues, |
| 101 | + }) |
| 102 | + |
| 103 | + return runner(cb) |
| 104 | +} |
0 commit comments