@netlify/build 32.1.4 → 33.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/core/build.d.ts +2 -1
- package/lib/core/build.js +8 -4
- package/lib/core/flags.d.ts +5 -0
- package/lib/core/flags.js +5 -0
- package/lib/log/messages/config.js +1 -0
- package/lib/log/messages/core_steps.js +15 -2
- package/lib/plugins/node_version.d.ts +1 -3
- package/lib/plugins/node_version.js +4 -30
- package/lib/plugins/resolve.js +0 -2
- package/lib/plugins_core/secrets_scanning/index.js +32 -13
- package/lib/plugins_core/secrets_scanning/utils.d.ts +23 -4
- package/lib/plugins_core/secrets_scanning/utils.js +115 -46
- package/lib/plugins_core/types.d.ts +1 -0
- package/lib/steps/core_step.d.ts +2 -1
- package/lib/steps/core_step.js +2 -1
- package/lib/steps/run_step.d.ts +2 -1
- package/lib/steps/run_step.js +7 -3
- package/lib/steps/run_steps.d.ts +2 -1
- package/lib/steps/run_steps.js +2 -1
- package/package.json +14 -14
package/lib/core/build.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export declare const startBuild: (flags: Partial<BuildFlags>) => {
|
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
34
|
export declare const execBuild: any;
|
|
35
|
-
export declare const runAndReportBuild: ({ pluginsOptions, netlifyConfig, defaultConfig, configOpts, siteInfo, configPath, outputConfigPath, headersPath, redirectsPath, packagePath, buildDir, repositoryRoot, nodePath, packageJson, userNodeVersion, childEnv, context, branch, buildbotServerSocket, constants, dry, mode, api, token, errorMonitor, deployId, errorParams, logs, debug, systemLog, systemLogFile, verbose, timers, sendStatus, saveConfig, testOpts, featureFlags, timeline, devCommand, quiet, integrations, explicitSecretKeys, edgeFunctionsBootstrapURL, eventHandlers, }: {
|
|
35
|
+
export declare const runAndReportBuild: ({ pluginsOptions, netlifyConfig, defaultConfig, configOpts, siteInfo, configPath, outputConfigPath, headersPath, redirectsPath, packagePath, buildDir, repositoryRoot, nodePath, packageJson, userNodeVersion, childEnv, context, branch, buildbotServerSocket, constants, dry, mode, api, token, errorMonitor, deployId, errorParams, logs, debug, systemLog, systemLogFile, verbose, timers, sendStatus, saveConfig, testOpts, featureFlags, timeline, devCommand, quiet, integrations, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, eventHandlers, }: {
|
|
36
36
|
pluginsOptions: any;
|
|
37
37
|
netlifyConfig: any;
|
|
38
38
|
defaultConfig: any;
|
|
@@ -75,6 +75,7 @@ export declare const runAndReportBuild: ({ pluginsOptions, netlifyConfig, defaul
|
|
|
75
75
|
quiet: any;
|
|
76
76
|
integrations: any;
|
|
77
77
|
explicitSecretKeys: any;
|
|
78
|
+
enhancedSecretScan: any;
|
|
78
79
|
edgeFunctionsBootstrapURL: any;
|
|
79
80
|
eventHandlers: any;
|
|
80
81
|
}) => Promise<{
|
package/lib/core/build.js
CHANGED
|
@@ -33,7 +33,7 @@ export const startBuild = function (flags) {
|
|
|
33
33
|
const errorMonitor = startErrorMonitor({ flags: { debug, systemLogFile, ...flagsA }, logs, bugsnagKey });
|
|
34
34
|
return { ...flagsA, debug, systemLogFile, errorMonitor, logs, timers };
|
|
35
35
|
};
|
|
36
|
-
const tExecBuild = async function ({ config, defaultConfig, cachedConfig, cachedConfigPath, outputConfigPath, cwd, packagePath, repositoryRoot, apiHost, token, siteId, accountId, context, branch, baseRelDir, env: envOpt, debug, systemLogFile, verbose, nodePath, functionsDistDir, edgeFunctionsDistDir, cacheDir, dry, mode, offline, deployId, buildId, testOpts, errorMonitor, errorParams, logs, timers, buildbotServerSocket, sendStatus, saveConfig, featureFlags, timeline, devCommand, quiet, framework, explicitSecretKeys, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
36
|
+
const tExecBuild = async function ({ config, defaultConfig, cachedConfig, cachedConfigPath, outputConfigPath, cwd, packagePath, repositoryRoot, apiHost, token, siteId, accountId, context, branch, baseRelDir, env: envOpt, debug, systemLogFile, verbose, nodePath, functionsDistDir, edgeFunctionsDistDir, cacheDir, dry, mode, offline, deployId, buildId, testOpts, errorMonitor, errorParams, logs, timers, buildbotServerSocket, sendStatus, saveConfig, featureFlags, timeline, devCommand, quiet, framework, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
37
37
|
const configOpts = getConfigOpts({
|
|
38
38
|
config,
|
|
39
39
|
defaultConfig,
|
|
@@ -139,6 +139,7 @@ const tExecBuild = async function ({ config, defaultConfig, cachedConfig, cached
|
|
|
139
139
|
quiet,
|
|
140
140
|
integrations,
|
|
141
141
|
explicitSecretKeys,
|
|
142
|
+
enhancedSecretScan,
|
|
142
143
|
edgeFunctionsBootstrapURL,
|
|
143
144
|
eventHandlers,
|
|
144
145
|
});
|
|
@@ -155,7 +156,7 @@ const tExecBuild = async function ({ config, defaultConfig, cachedConfig, cached
|
|
|
155
156
|
};
|
|
156
157
|
export const execBuild = measureDuration(tExecBuild, 'total', { parentTag: 'build_site' });
|
|
157
158
|
// Runs a build then report any plugin statuses
|
|
158
|
-
export const runAndReportBuild = async function ({ pluginsOptions, netlifyConfig, defaultConfig, configOpts, siteInfo, configPath, outputConfigPath, headersPath, redirectsPath, packagePath, buildDir, repositoryRoot, nodePath, packageJson, userNodeVersion, childEnv, context, branch, buildbotServerSocket, constants, dry, mode, api, token, errorMonitor, deployId, errorParams, logs, debug, systemLog, systemLogFile, verbose, timers, sendStatus, saveConfig, testOpts, featureFlags, timeline, devCommand, quiet, integrations, explicitSecretKeys, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
159
|
+
export const runAndReportBuild = async function ({ pluginsOptions, netlifyConfig, defaultConfig, configOpts, siteInfo, configPath, outputConfigPath, headersPath, redirectsPath, packagePath, buildDir, repositoryRoot, nodePath, packageJson, userNodeVersion, childEnv, context, branch, buildbotServerSocket, constants, dry, mode, api, token, errorMonitor, deployId, errorParams, logs, debug, systemLog, systemLogFile, verbose, timers, sendStatus, saveConfig, testOpts, featureFlags, timeline, devCommand, quiet, integrations, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
159
160
|
try {
|
|
160
161
|
const { stepsCount, netlifyConfig: netlifyConfigA, statuses, pluginsOptions: pluginsOptionsA, failedPlugins, timers: timersA, configMutations, metrics, } = await initAndRunBuild({
|
|
161
162
|
pluginsOptions,
|
|
@@ -200,6 +201,7 @@ export const runAndReportBuild = async function ({ pluginsOptions, netlifyConfig
|
|
|
200
201
|
quiet,
|
|
201
202
|
integrations,
|
|
202
203
|
explicitSecretKeys,
|
|
204
|
+
enhancedSecretScan,
|
|
203
205
|
edgeFunctionsBootstrapURL,
|
|
204
206
|
eventHandlers,
|
|
205
207
|
});
|
|
@@ -262,7 +264,7 @@ export const runAndReportBuild = async function ({ pluginsOptions, netlifyConfig
|
|
|
262
264
|
}
|
|
263
265
|
};
|
|
264
266
|
// Initialize plugin processes then runs a build
|
|
265
|
-
const initAndRunBuild = async function ({ pluginsOptions, netlifyConfig, defaultConfig, configOpts, siteInfo, configPath, outputConfigPath, headersPath, redirectsPath, buildDir, packagePath, repositoryRoot, nodePath, packageJson, userNodeVersion, childEnv, context, branch, dry, mode, api, token, errorMonitor, deployId, errorParams, logs, debug, systemLog, systemLogFile, verbose, sendStatus, saveConfig, timers, testOpts, buildbotServerSocket, constants, featureFlags, timeline, devCommand, quiet, integrations, explicitSecretKeys, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
267
|
+
const initAndRunBuild = async function ({ pluginsOptions, netlifyConfig, defaultConfig, configOpts, siteInfo, configPath, outputConfigPath, headersPath, redirectsPath, buildDir, packagePath, repositoryRoot, nodePath, packageJson, userNodeVersion, childEnv, context, branch, dry, mode, api, token, errorMonitor, deployId, errorParams, logs, debug, systemLog, systemLogFile, verbose, sendStatus, saveConfig, timers, testOpts, buildbotServerSocket, constants, featureFlags, timeline, devCommand, quiet, integrations, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
266
268
|
const pluginsEnv = {
|
|
267
269
|
...childEnv,
|
|
268
270
|
...getBlobsEnvironmentContext({ api, deployId: deployId, siteId: siteInfo?.id, token }),
|
|
@@ -351,6 +353,7 @@ const initAndRunBuild = async function ({ pluginsOptions, netlifyConfig, default
|
|
|
351
353
|
devCommand,
|
|
352
354
|
quiet,
|
|
353
355
|
explicitSecretKeys,
|
|
356
|
+
enhancedSecretScan,
|
|
354
357
|
edgeFunctionsBootstrapURL,
|
|
355
358
|
eventHandlers,
|
|
356
359
|
});
|
|
@@ -386,7 +389,7 @@ const initAndRunBuild = async function ({ pluginsOptions, netlifyConfig, default
|
|
|
386
389
|
};
|
|
387
390
|
// Load plugin main files, retrieve their event handlers then runs them,
|
|
388
391
|
// together with the build command
|
|
389
|
-
const runBuild = async function ({ childProcesses, pluginsOptions, netlifyConfig, defaultConfig, configOpts, packageJson, configPath, outputConfigPath, userNodeVersion, headersPath, redirectsPath, buildDir, repositoryRoot, packagePath, nodePath, childEnv, context, branch, dry, buildbotServerSocket, constants, mode, api, errorMonitor, deployId, errorParams, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, timeline, devCommand, quiet, explicitSecretKeys, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
392
|
+
const runBuild = async function ({ childProcesses, pluginsOptions, netlifyConfig, defaultConfig, configOpts, packageJson, configPath, outputConfigPath, userNodeVersion, headersPath, redirectsPath, buildDir, repositoryRoot, packagePath, nodePath, childEnv, context, branch, dry, buildbotServerSocket, constants, mode, api, errorMonitor, deployId, errorParams, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, timeline, devCommand, quiet, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, eventHandlers, }) {
|
|
390
393
|
const { pluginsSteps, timers: timersA } = await loadPlugins({
|
|
391
394
|
pluginsOptions,
|
|
392
395
|
childProcesses,
|
|
@@ -439,6 +442,7 @@ const runBuild = async function ({ childProcesses, pluginsOptions, netlifyConfig
|
|
|
439
442
|
quiet,
|
|
440
443
|
userNodeVersion,
|
|
441
444
|
explicitSecretKeys,
|
|
445
|
+
enhancedSecretScan,
|
|
442
446
|
edgeFunctionsBootstrapURL,
|
|
443
447
|
});
|
|
444
448
|
return {
|
package/lib/core/flags.d.ts
CHANGED
package/lib/core/flags.js
CHANGED
|
@@ -94,10 +94,23 @@ export const logSecretsScanSuccessMessage = function (logs, msg) {
|
|
|
94
94
|
log(logs, msg, { color: THEME.highlightWords });
|
|
95
95
|
};
|
|
96
96
|
export const logSecretsScanFailBuildMessage = function ({ logs, scanResults, groupedResults }) {
|
|
97
|
+
const { secretMatches, enhancedSecretMatches } = groupedResults;
|
|
97
98
|
logErrorSubHeader(logs, `Scanning complete. ${scanResults.scannedFilesCount} file(s) scanned. Secrets scanning found ${scanResults.matches.length} instance(s) of secrets in build output or repo code.\n`);
|
|
98
|
-
|
|
99
|
+
// Explicit secret matches
|
|
100
|
+
Object.keys(secretMatches).forEach((key) => {
|
|
99
101
|
logError(logs, `Secret env var "${key}"'s value detected:`);
|
|
100
|
-
|
|
102
|
+
secretMatches[key]
|
|
103
|
+
.sort((a, b) => {
|
|
104
|
+
return a.file > b.file ? 0 : 1;
|
|
105
|
+
})
|
|
106
|
+
.forEach(({ lineNumber, file }) => {
|
|
107
|
+
logError(logs, `found value at line ${lineNumber} in ${file}`, { indent: true });
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
// Likely secret matches from enhanced scan
|
|
111
|
+
Object.keys(enhancedSecretMatches).forEach((key) => {
|
|
112
|
+
logError(logs, `Env var "${key}"'s value detected as a likely secret value:`);
|
|
113
|
+
enhancedSecretMatches[key]
|
|
101
114
|
.sort((a, b) => {
|
|
102
115
|
return a.file > b.file ? 0 : 1;
|
|
103
116
|
})
|
|
@@ -15,11 +15,9 @@ export type PluginsOptions = {
|
|
|
15
15
|
* usually the system's Node.js version.
|
|
16
16
|
* If the user Node version does not satisfy our supported engine range use our own system Node version
|
|
17
17
|
*/
|
|
18
|
-
export declare const addPluginsNodeVersion: ({
|
|
19
|
-
featureFlags: any;
|
|
18
|
+
export declare const addPluginsNodeVersion: ({ pluginsOptions, nodePath, userNodeVersion, logs }: {
|
|
20
19
|
pluginsOptions: any;
|
|
21
20
|
nodePath: any;
|
|
22
21
|
userNodeVersion: any;
|
|
23
22
|
logs: any;
|
|
24
|
-
systemLog: any;
|
|
25
23
|
}) => Promise<any[]>;
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { dirname } from 'path';
|
|
2
1
|
import { execPath, version as currentVersion } from 'process';
|
|
3
2
|
import semver from 'semver';
|
|
4
3
|
import link from 'terminal-link';
|
|
5
4
|
import { logWarning, logWarningSubHeader } from '../log/logger.js';
|
|
6
|
-
import { getPackageJson } from '../utils/package.js';
|
|
7
5
|
/**
|
|
8
6
|
* This node version is minimum required to run the plugins code.
|
|
9
7
|
* If the users preferred Node.js version is below that we have to fall back to the system node version
|
|
10
8
|
*/
|
|
11
|
-
const MINIMUM_REQUIRED_NODE_VERSION = '
|
|
12
|
-
const UPCOMING_MINIMUM_REQUIRED_NODE_VERSION = '>=18.14.0';
|
|
9
|
+
const MINIMUM_REQUIRED_NODE_VERSION = '>=18.14.0';
|
|
13
10
|
/**
|
|
14
11
|
* Local plugins and `package.json`-installed plugins use user's preferred Node.js version if higher than our minimum
|
|
15
12
|
* supported version. Else default to the system Node version.
|
|
@@ -17,19 +14,17 @@ const UPCOMING_MINIMUM_REQUIRED_NODE_VERSION = '>=18.14.0';
|
|
|
17
14
|
* usually the system's Node.js version.
|
|
18
15
|
* If the user Node version does not satisfy our supported engine range use our own system Node version
|
|
19
16
|
*/
|
|
20
|
-
export const addPluginsNodeVersion = function ({
|
|
17
|
+
export const addPluginsNodeVersion = function ({ pluginsOptions, nodePath, userNodeVersion, logs }) {
|
|
21
18
|
const currentNodeVersion = semver.clean(currentVersion);
|
|
22
19
|
return Promise.all(pluginsOptions.map((pluginOptions) => addPluginNodeVersion({
|
|
23
|
-
featureFlags,
|
|
24
20
|
pluginOptions,
|
|
25
21
|
currentNodeVersion,
|
|
26
22
|
userNodeVersion,
|
|
27
23
|
nodePath,
|
|
28
24
|
logs,
|
|
29
|
-
systemLog,
|
|
30
25
|
})));
|
|
31
26
|
};
|
|
32
|
-
const addPluginNodeVersion = async function ({
|
|
27
|
+
const addPluginNodeVersion = async function ({ pluginOptions, pluginOptions: { loadedFrom, packageName }, currentNodeVersion, userNodeVersion, nodePath, logs, }) {
|
|
33
28
|
const systemNode = { ...pluginOptions, nodePath: execPath, nodeVersion: currentNodeVersion };
|
|
34
29
|
const userNode = { ...pluginOptions, nodePath, nodeVersion: userNodeVersion };
|
|
35
30
|
const isLocalPlugin = loadedFrom === 'local' || loadedFrom === 'package.json';
|
|
@@ -37,33 +32,12 @@ const addPluginNodeVersion = async function ({ featureFlags, pluginOptions, plug
|
|
|
37
32
|
if (isUIOrAutoInstalledPlugin) {
|
|
38
33
|
return systemNode;
|
|
39
34
|
}
|
|
40
|
-
if (featureFlags.build_warn_upcoming_system_version_change &&
|
|
41
|
-
!semver.satisfies(userNodeVersion, UPCOMING_MINIMUM_REQUIRED_NODE_VERSION)) {
|
|
42
|
-
if (pluginPath) {
|
|
43
|
-
const pluginDir = dirname(pluginPath);
|
|
44
|
-
const { packageJson: pluginPackageJson } = await getPackageJson(pluginDir);
|
|
45
|
-
// Ensure Node.js version is compatible with plugin's `engines.node`
|
|
46
|
-
const pluginNodeVersionRange = pluginPackageJson?.engines?.node;
|
|
47
|
-
if (!pluginNodeVersionRange) {
|
|
48
|
-
systemLog(`plugin "${packageName}" does not specify node support range`);
|
|
49
|
-
}
|
|
50
|
-
else if (semver.satisfies('22.0.0', pluginNodeVersionRange)) {
|
|
51
|
-
systemLog(`plugin "${packageName}" node support range includes v22`);
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
systemLog(`plugin "${packageName}" node support range does NOT include v22`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
systemLog(`plugin "${packageName}" pluginPath not available`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
35
|
if (semver.satisfies(userNodeVersion, MINIMUM_REQUIRED_NODE_VERSION)) {
|
|
62
36
|
return userNode;
|
|
63
37
|
}
|
|
64
38
|
logWarningSubHeader(logs, `Warning: ${packageName} will be executed with Node.js version ${currentNodeVersion}`);
|
|
65
39
|
logWarning(logs, ` The plugin cannot be executed with your defined Node.js version ${userNodeVersion}
|
|
66
40
|
|
|
67
|
-
Read more about our minimum required version in our ${link('forums announcement', 'https://answers.netlify.com/t/build-plugins-
|
|
41
|
+
Read more about our minimum required version in our ${link('forums announcement', 'https://answers.netlify.com/t/build-plugins-end-of-support-for-node-js-14-node-js-16/136405')}`);
|
|
68
42
|
return systemNode;
|
|
69
43
|
};
|
package/lib/plugins/resolve.js
CHANGED
|
@@ -15,12 +15,10 @@ export const resolvePluginsPath = async function ({ pluginsOptions, siteInfo, bu
|
|
|
15
15
|
const autoPluginsDir = getAutoPluginsDir(buildDir, packagePath);
|
|
16
16
|
const pluginsOptionsA = await Promise.all(pluginsOptions.map((pluginOptions) => resolvePluginPath({ pluginOptions, buildDir, packagePath, autoPluginsDir })));
|
|
17
17
|
const pluginsOptionsB = await addPluginsNodeVersion({
|
|
18
|
-
featureFlags,
|
|
19
18
|
pluginsOptions: pluginsOptionsA,
|
|
20
19
|
nodePath,
|
|
21
20
|
userNodeVersion,
|
|
22
21
|
logs,
|
|
23
|
-
systemLog,
|
|
24
22
|
});
|
|
25
23
|
const pluginsOptionsC = await addPinnedVersions({ pluginsOptions: pluginsOptionsB, api, siteInfo, sendStatus });
|
|
26
24
|
const pluginsOptionsD = await addExpectedVersions({
|
|
@@ -3,9 +3,9 @@ import { addErrorInfo } from '../../error/info.js';
|
|
|
3
3
|
import { log } from '../../log/logger.js';
|
|
4
4
|
import { logSecretsScanFailBuildMessage, logSecretsScanSkipMessage, logSecretsScanSuccessMessage, } from '../../log/messages/core_steps.js';
|
|
5
5
|
import { reportValidations } from '../../status/validations.js';
|
|
6
|
-
import { getFilePathsToScan, getSecretKeysToScanFor,
|
|
6
|
+
import { getFilePathsToScan, getNonSecretKeysToScanFor, getSecretKeysToScanFor, groupScanResultsByKeyAndScanType, isSecretsScanningEnabled, scanFilesForKeyValues, } from './utils.js';
|
|
7
7
|
const tracer = trace.getTracer('secrets-scanning');
|
|
8
|
-
const coreStep = async function ({ buildDir, logs, netlifyConfig, explicitSecretKeys, systemLog, deployId, api, }) {
|
|
8
|
+
const coreStep = async function ({ buildDir, logs, netlifyConfig, explicitSecretKeys, enhancedSecretScan, systemLog, deployId, api, }) {
|
|
9
9
|
const stepResults = {};
|
|
10
10
|
const passedSecretKeys = (explicitSecretKeys || '').split(',');
|
|
11
11
|
const envVars = netlifyConfig.build.environment;
|
|
@@ -21,9 +21,14 @@ const coreStep = async function ({ buildDir, logs, netlifyConfig, explicitSecret
|
|
|
21
21
|
if (envVars['SECRETS_SCAN_OMIT_PATHS'] !== undefined) {
|
|
22
22
|
log(logs, `SECRETS_SCAN_OMIT_PATHS override option set to: ${envVars['SECRETS_SCAN_OMIT_PATHS']}\n`);
|
|
23
23
|
}
|
|
24
|
-
const
|
|
24
|
+
const explicitSecretKeysToScanFor = getSecretKeysToScanFor(envVars, passedSecretKeys);
|
|
25
|
+
const potentialSecretKeysToScanFor = enhancedSecretScan ? getNonSecretKeysToScanFor(envVars, passedSecretKeys) : [];
|
|
26
|
+
const keysToSearchFor = explicitSecretKeysToScanFor.concat(potentialSecretKeysToScanFor);
|
|
25
27
|
if (keysToSearchFor.length === 0) {
|
|
26
|
-
|
|
28
|
+
const msg = enhancedSecretScan
|
|
29
|
+
? 'Secrets scanning skipped because no env vars are set to non-empty/non-trivial values or they are all omitted with SECRETS_SCAN_OMIT_KEYS env var setting.'
|
|
30
|
+
: 'Secrets scanning skipped because no env vars marked as secret are set to non-empty/non-trivial values or they are all omitted with SECRETS_SCAN_OMIT_KEYS env var setting.';
|
|
31
|
+
logSecretsScanSkipMessage(logs, msg);
|
|
27
32
|
return stepResults;
|
|
28
33
|
}
|
|
29
34
|
// buildDir is the repository root or the base folder
|
|
@@ -35,6 +40,8 @@ const coreStep = async function ({ buildDir, logs, netlifyConfig, explicitSecret
|
|
|
35
40
|
return stepResults;
|
|
36
41
|
}
|
|
37
42
|
let scanResults;
|
|
43
|
+
let secretMatches;
|
|
44
|
+
let enhancedSecretMatches;
|
|
38
45
|
await tracer.startActiveSpan('scanning-files', { attributes: { keysToSearchFor, totalFiles: filePaths.length } }, async (span) => {
|
|
39
46
|
scanResults = await scanFilesForKeyValues({
|
|
40
47
|
env: envVars,
|
|
@@ -42,9 +49,13 @@ const coreStep = async function ({ buildDir, logs, netlifyConfig, explicitSecret
|
|
|
42
49
|
base: buildDir,
|
|
43
50
|
filePaths,
|
|
44
51
|
});
|
|
52
|
+
secretMatches = scanResults.matches.filter((match) => explicitSecretKeysToScanFor.includes(match.key));
|
|
53
|
+
enhancedSecretMatches = scanResults.matches.filter((match) => potentialSecretKeysToScanFor.includes(match.key));
|
|
45
54
|
const attributesForLogsAndSpan = {
|
|
46
|
-
secretsScanFoundSecrets:
|
|
47
|
-
|
|
55
|
+
secretsScanFoundSecrets: secretMatches.length > 0,
|
|
56
|
+
enhancedSecretsScanFoundSecrets: enhancedSecretMatches.length > 0,
|
|
57
|
+
secretsScanMatchesCount: secretMatches.length,
|
|
58
|
+
enhancedSecretsScanMatchesCount: enhancedSecretMatches.length,
|
|
48
59
|
secretsFilesCount: scanResults.scannedFilesCount,
|
|
49
60
|
keysToSearchFor,
|
|
50
61
|
};
|
|
@@ -55,7 +66,8 @@ const coreStep = async function ({ buildDir, logs, netlifyConfig, explicitSecret
|
|
|
55
66
|
if (deployId !== '0') {
|
|
56
67
|
const secretScanResult = {
|
|
57
68
|
scannedFilesCount: scanResults?.scannedFilesCount ?? 0,
|
|
58
|
-
secretsScanMatches:
|
|
69
|
+
secretsScanMatches: secretMatches ?? [],
|
|
70
|
+
enhancedSecretsScanMatches: enhancedSecretMatches ?? [],
|
|
59
71
|
};
|
|
60
72
|
reportValidations({ api, secretScanResult, deployId, systemLog });
|
|
61
73
|
}
|
|
@@ -65,15 +77,22 @@ const coreStep = async function ({ buildDir, logs, netlifyConfig, explicitSecret
|
|
|
65
77
|
}
|
|
66
78
|
// at this point we have found matching secrets
|
|
67
79
|
// Output the results and fail the build
|
|
68
|
-
logSecretsScanFailBuildMessage({
|
|
80
|
+
logSecretsScanFailBuildMessage({
|
|
81
|
+
logs,
|
|
82
|
+
scanResults,
|
|
83
|
+
groupedResults: groupScanResultsByKeyAndScanType(scanResults, potentialSecretKeysToScanFor),
|
|
84
|
+
});
|
|
69
85
|
const error = new Error(`Secrets scanning found secrets in build.`);
|
|
70
86
|
addErrorInfo(error, { type: 'secretScanningFoundSecrets' });
|
|
71
87
|
throw error;
|
|
72
88
|
};
|
|
73
|
-
// We run this core step if the build was run with explicit secret keys.
|
|
74
|
-
// is passed from BB to build so only accounts that are allowed to have explicit
|
|
75
|
-
// secrets and actually have them will have them.
|
|
76
|
-
const
|
|
89
|
+
// We run this core step if the build was run with explicit secret keys or if enhanced secret scanning is enabled.
|
|
90
|
+
// This is passed from BB to build so only accounts that are allowed to have explicit
|
|
91
|
+
// secrets and actually have them / have enhanced secret scanning enabled will have them.
|
|
92
|
+
const hasExplicitSecretsKeysOrEnhancedScanningEnabled = function ({ explicitSecretKeys, enhancedSecretScan, }) {
|
|
93
|
+
if (enhancedSecretScan) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
77
96
|
if (typeof explicitSecretKeys !== 'string') {
|
|
78
97
|
return false;
|
|
79
98
|
}
|
|
@@ -85,5 +104,5 @@ export const scanForSecrets = {
|
|
|
85
104
|
coreStepId: 'secrets_scanning',
|
|
86
105
|
coreStepName: 'Secrets scanning',
|
|
87
106
|
coreStepDescription: () => 'Scanning for secrets in code and build output.',
|
|
88
|
-
condition:
|
|
107
|
+
condition: hasExplicitSecretsKeysOrEnhancedScanningEnabled,
|
|
89
108
|
};
|
|
@@ -16,6 +16,7 @@ interface MatchResult {
|
|
|
16
16
|
export type SecretScanResult = {
|
|
17
17
|
scannedFilesCount: number;
|
|
18
18
|
secretsScanMatches: MatchResult[];
|
|
19
|
+
enhancedSecretsScanMatches: MatchResult[];
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* Determine if the user disabled scanning via env var
|
|
@@ -36,6 +37,16 @@ export declare function isSecretsScanningEnabled(env: Record<string, unknown>):
|
|
|
36
37
|
* @returns string[]
|
|
37
38
|
*/
|
|
38
39
|
export declare function getSecretKeysToScanFor(env: Record<string, unknown>, secretKeys: string[]): string[];
|
|
40
|
+
/**
|
|
41
|
+
* given the explicit secret keys and env vars, return the list of non-secret keys which should be scanned in the enhanced secret scan
|
|
42
|
+
* (i.e. any that look very likely to be secrets).
|
|
43
|
+
* This will also filter out keys passed in the SECRETS_SCAN_OMIT_KEYS env var.
|
|
44
|
+
*
|
|
45
|
+
* @param env env vars list
|
|
46
|
+
* @param secretKeys
|
|
47
|
+
* @returns string[]
|
|
48
|
+
*/
|
|
49
|
+
export declare function getNonSecretKeysToScanFor(env: Record<string, unknown>, secretKeys: string[]): string[];
|
|
39
50
|
/**
|
|
40
51
|
* Given the env and base directory, find all file paths to scan. It will look at the
|
|
41
52
|
* env vars to decide if it should omit certain paths.
|
|
@@ -59,13 +70,21 @@ export declare function getFilePathsToScan({ env, base }: {
|
|
|
59
70
|
export declare function scanFilesForKeyValues({ env, keys, filePaths, base }: ScanArgs): Promise<ScanResults>;
|
|
60
71
|
/**
|
|
61
72
|
* ScanResults are all of the finds for all keys and their disparate locations. Scanning is
|
|
62
|
-
* async in streams so order can change a lot.
|
|
63
|
-
*
|
|
73
|
+
* async in streams so order can change a lot. Some matches are the result of an env var explictly being marked as secret,
|
|
74
|
+
* while others are part of the enhanced secret scan.
|
|
75
|
+
*
|
|
76
|
+
* This function groups the results into an object where the results are separate into the secretMatches and enhancedSecretMatches,
|
|
77
|
+
* their value being an object where the keys are the env var keys and the values are all match results for that key.
|
|
64
78
|
*
|
|
65
79
|
* @param scanResults
|
|
66
80
|
* @returns
|
|
67
81
|
*/
|
|
68
|
-
export declare function
|
|
69
|
-
|
|
82
|
+
export declare function groupScanResultsByKeyAndScanType(scanResults: ScanResults, enhancedScanKeys?: string[]): {
|
|
83
|
+
secretMatches: {
|
|
84
|
+
[key: string]: MatchResult[];
|
|
85
|
+
};
|
|
86
|
+
enhancedSecretMatches: {
|
|
87
|
+
[key: string]: MatchResult[];
|
|
88
|
+
};
|
|
70
89
|
};
|
|
71
90
|
export {};
|
|
@@ -14,6 +14,40 @@ export function isSecretsScanningEnabled(env) {
|
|
|
14
14
|
}
|
|
15
15
|
return true;
|
|
16
16
|
}
|
|
17
|
+
function filterOmittedKeys(env, envKeys = []) {
|
|
18
|
+
if (typeof env.SECRETS_SCAN_OMIT_KEYS !== 'string') {
|
|
19
|
+
return envKeys;
|
|
20
|
+
}
|
|
21
|
+
const omitKeys = env.SECRETS_SCAN_OMIT_KEYS.split(',')
|
|
22
|
+
.map((s) => s.trim())
|
|
23
|
+
.filter(Boolean);
|
|
24
|
+
return envKeys.filter((key) => !omitKeys.includes(key));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Trivial values are values that are:
|
|
28
|
+
* - empty or short strings
|
|
29
|
+
* - string forms of booleans
|
|
30
|
+
* - booleans
|
|
31
|
+
* - numbers or objects with fewer than 4 chars
|
|
32
|
+
*/
|
|
33
|
+
function isValueTrivial(val) {
|
|
34
|
+
if (typeof val === 'string') {
|
|
35
|
+
// string forms of booleans
|
|
36
|
+
if (val === 'true' || val === 'false') {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
// trivial values are empty or short strings
|
|
40
|
+
return val.trim().length < 4;
|
|
41
|
+
}
|
|
42
|
+
if (typeof val === 'boolean') {
|
|
43
|
+
// booleans are always considered trivial
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
if (typeof val === 'number' || typeof val === 'object') {
|
|
47
|
+
return JSON.stringify(val).length < 4;
|
|
48
|
+
}
|
|
49
|
+
return !val;
|
|
50
|
+
}
|
|
17
51
|
/**
|
|
18
52
|
* given the explicit secret keys and env vars, return the list of secret keys which have non-empty or non-trivial values. This
|
|
19
53
|
* will also filter out keys passed in the SECRETS_SCAN_OMIT_KEYS env var.
|
|
@@ -27,34 +61,52 @@ export function isSecretsScanningEnabled(env) {
|
|
|
27
61
|
* @returns string[]
|
|
28
62
|
*/
|
|
29
63
|
export function getSecretKeysToScanFor(env, secretKeys) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
64
|
+
const filteredSecretKeys = filterOmittedKeys(env, secretKeys);
|
|
65
|
+
return filteredSecretKeys.filter((key) => !isValueTrivial(env[key]));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* given the explicit secret keys and env vars, return the list of non-secret keys which should be scanned in the enhanced secret scan
|
|
69
|
+
* (i.e. any that look very likely to be secrets).
|
|
70
|
+
* This will also filter out keys passed in the SECRETS_SCAN_OMIT_KEYS env var.
|
|
71
|
+
*
|
|
72
|
+
* @param env env vars list
|
|
73
|
+
* @param secretKeys
|
|
74
|
+
* @returns string[]
|
|
75
|
+
*/
|
|
76
|
+
export function getNonSecretKeysToScanFor(env, secretKeys) {
|
|
77
|
+
const nonSecretKeys = Object.keys(env).filter((key) => !secretKeys.includes(key));
|
|
78
|
+
const filteredNonSecretKeys = filterOmittedKeys(env, nonSecretKeys);
|
|
79
|
+
const nonSecretKeysToScanFor = filteredNonSecretKeys.filter((key) => {
|
|
40
80
|
const val = env[key];
|
|
41
|
-
if (
|
|
42
|
-
// string forms of booleans
|
|
43
|
-
if (val === 'true' || val === 'false') {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
// non-trivial/non-empty values only
|
|
47
|
-
return val.trim().length > 4;
|
|
48
|
-
}
|
|
49
|
-
else if (typeof val === 'boolean') {
|
|
50
|
-
// booleans are trivial values
|
|
81
|
+
if (isValueTrivial(val)) {
|
|
51
82
|
return false;
|
|
52
83
|
}
|
|
53
|
-
|
|
54
|
-
return JSON.stringify(val).length > 4;
|
|
55
|
-
}
|
|
56
|
-
return !!val;
|
|
84
|
+
return isLikelySecretValue(val);
|
|
57
85
|
});
|
|
86
|
+
return nonSecretKeysToScanFor;
|
|
87
|
+
}
|
|
88
|
+
const AWS_PREFIXES = ['aws_', 'asia'];
|
|
89
|
+
const SLACK_PREFIXES = ['xoxb-', 'xwfp-', 'xoxb-', 'xoxp-', 'xapp-'];
|
|
90
|
+
const LIKELY_SECRET_PREFIXES = ['pk_', 'sk_', 'pat_', 'db_', 'github_pat_', ...AWS_PREFIXES, ...SLACK_PREFIXES];
|
|
91
|
+
const LIKELY_SECRET_MIN_LENGTH = 16;
|
|
92
|
+
/**
|
|
93
|
+
* When the enhanced secret scan is run, we check any env vars _not_ marked as secret if they are highly likely to be secret values.
|
|
94
|
+
* For now, this means the value is a string of at least 16 chars and starts with one of the known prefixes.
|
|
95
|
+
*
|
|
96
|
+
* @param val env var value
|
|
97
|
+
* @returns boolean
|
|
98
|
+
*/
|
|
99
|
+
function isLikelySecretValue(val) {
|
|
100
|
+
if (typeof val !== 'string') {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (val.length < LIKELY_SECRET_MIN_LENGTH) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (LIKELY_SECRET_PREFIXES.some((prefix) => val.toLowerCase().startsWith(prefix))) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
58
110
|
}
|
|
59
111
|
/**
|
|
60
112
|
* Given the env and base directory, find all file paths to scan. It will look at the
|
|
@@ -262,41 +314,58 @@ const searchStream = (basePath, file, keyValues) => {
|
|
|
262
314
|
};
|
|
263
315
|
/**
|
|
264
316
|
* ScanResults are all of the finds for all keys and their disparate locations. Scanning is
|
|
265
|
-
* async in streams so order can change a lot.
|
|
266
|
-
*
|
|
317
|
+
* async in streams so order can change a lot. Some matches are the result of an env var explictly being marked as secret,
|
|
318
|
+
* while others are part of the enhanced secret scan.
|
|
319
|
+
*
|
|
320
|
+
* This function groups the results into an object where the results are separate into the secretMatches and enhancedSecretMatches,
|
|
321
|
+
* their value being an object where the keys are the env var keys and the values are all match results for that key.
|
|
267
322
|
*
|
|
268
323
|
* @param scanResults
|
|
269
324
|
* @returns
|
|
270
325
|
*/
|
|
271
|
-
export function
|
|
272
|
-
const
|
|
326
|
+
export function groupScanResultsByKeyAndScanType(scanResults, enhancedScanKeys = []) {
|
|
327
|
+
const secretMatchesByKeys = {};
|
|
328
|
+
const enhancedSecretMatchesByKeys = {};
|
|
273
329
|
scanResults.matches.forEach((matchResult) => {
|
|
274
|
-
|
|
275
|
-
|
|
330
|
+
const isEnhancedCheck = enhancedScanKeys.includes(matchResult.key);
|
|
331
|
+
if (isEnhancedCheck) {
|
|
332
|
+
if (!enhancedSecretMatchesByKeys[matchResult.key]) {
|
|
333
|
+
enhancedSecretMatchesByKeys[matchResult.key] = [];
|
|
334
|
+
}
|
|
335
|
+
enhancedSecretMatchesByKeys[matchResult.key].push(matchResult);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
if (!secretMatchesByKeys[matchResult.key]) {
|
|
339
|
+
secretMatchesByKeys[matchResult.key] = [];
|
|
340
|
+
}
|
|
341
|
+
secretMatchesByKeys[matchResult.key].push(matchResult);
|
|
276
342
|
}
|
|
277
|
-
matchesByKeys[matchResult.key].push(matchResult);
|
|
278
343
|
});
|
|
279
344
|
// sort results to get a consistent output and logically ordered match results
|
|
280
|
-
|
|
281
|
-
matchesByKeys
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
// sort by line number second
|
|
287
|
-
if (a.file === b.file) {
|
|
288
|
-
if (a.lineNumber > b.lineNumber) {
|
|
345
|
+
const sortMatches = (matchesByKeys) => {
|
|
346
|
+
Object.keys(matchesByKeys).forEach((key) => {
|
|
347
|
+
matchesByKeys[key].sort((a, b) => {
|
|
348
|
+
// sort by file name first
|
|
349
|
+
if (a.file > b.file) {
|
|
289
350
|
return 1;
|
|
290
351
|
}
|
|
291
|
-
|
|
292
|
-
|
|
352
|
+
// sort by line number second
|
|
353
|
+
if (a.file === b.file) {
|
|
354
|
+
if (a.lineNumber > b.lineNumber) {
|
|
355
|
+
return 1;
|
|
356
|
+
}
|
|
357
|
+
if (a.lineNumber === b.lineNumber) {
|
|
358
|
+
return 0;
|
|
359
|
+
}
|
|
360
|
+
return -1;
|
|
293
361
|
}
|
|
294
362
|
return -1;
|
|
295
|
-
}
|
|
296
|
-
return -1;
|
|
363
|
+
});
|
|
297
364
|
});
|
|
298
|
-
}
|
|
299
|
-
|
|
365
|
+
};
|
|
366
|
+
sortMatches(secretMatchesByKeys);
|
|
367
|
+
sortMatches(enhancedSecretMatchesByKeys);
|
|
368
|
+
return { secretMatches: secretMatchesByKeys, enhancedSecretMatches: enhancedSecretMatchesByKeys };
|
|
300
369
|
}
|
|
301
370
|
function isMultiLineVal(v) {
|
|
302
371
|
return typeof v === 'string' && v.includes('\n');
|
package/lib/steps/core_step.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const fireCoreStep: ({ coreStep, coreStepId, coreStepName, configPath, outputConfigPath, buildDir, repositoryRoot, packagePath, constants, buildbotServerSocket, events, logs, quiet, nodePath, childEnv, context, branch, envChanges, errorParams, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, featureFlags, debug, systemLog, saveConfig, userNodeVersion, explicitSecretKeys, edgeFunctionsBootstrapURL, deployId, outputFlusher, api, }: {
|
|
1
|
+
export declare const fireCoreStep: ({ coreStep, coreStepId, coreStepName, configPath, outputConfigPath, buildDir, repositoryRoot, packagePath, constants, buildbotServerSocket, events, logs, quiet, nodePath, childEnv, context, branch, envChanges, errorParams, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, featureFlags, debug, systemLog, saveConfig, userNodeVersion, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, deployId, outputFlusher, api, }: {
|
|
2
2
|
coreStep: any;
|
|
3
3
|
coreStepId: any;
|
|
4
4
|
coreStepName: any;
|
|
@@ -30,6 +30,7 @@ export declare const fireCoreStep: ({ coreStep, coreStepId, coreStepName, config
|
|
|
30
30
|
saveConfig: any;
|
|
31
31
|
userNodeVersion: any;
|
|
32
32
|
explicitSecretKeys: any;
|
|
33
|
+
enhancedSecretScan: any;
|
|
33
34
|
edgeFunctionsBootstrapURL: any;
|
|
34
35
|
deployId: any;
|
|
35
36
|
outputFlusher: any;
|
package/lib/steps/core_step.js
CHANGED
|
@@ -3,7 +3,7 @@ import { addErrorInfo, isBuildError } from '../error/info.js';
|
|
|
3
3
|
import { addOutputFlusher } from '../log/logger.js';
|
|
4
4
|
import { updateNetlifyConfig, listConfigSideFiles } from './update_config.js';
|
|
5
5
|
// Fire a core step
|
|
6
|
-
export const fireCoreStep = async function ({ coreStep, coreStepId, coreStepName, configPath, outputConfigPath, buildDir, repositoryRoot, packagePath, constants, buildbotServerSocket, events, logs, quiet, nodePath, childEnv, context, branch, envChanges, errorParams, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, featureFlags, debug, systemLog, saveConfig, userNodeVersion, explicitSecretKeys, edgeFunctionsBootstrapURL, deployId, outputFlusher, api, }) {
|
|
6
|
+
export const fireCoreStep = async function ({ coreStep, coreStepId, coreStepName, configPath, outputConfigPath, buildDir, repositoryRoot, packagePath, constants, buildbotServerSocket, events, logs, quiet, nodePath, childEnv, context, branch, envChanges, errorParams, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, featureFlags, debug, systemLog, saveConfig, userNodeVersion, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, deployId, outputFlusher, api, }) {
|
|
7
7
|
const logsA = outputFlusher ? addOutputFlusher(logs, outputFlusher) : logs;
|
|
8
8
|
try {
|
|
9
9
|
const configSideFiles = await listConfigSideFiles([headersPath, redirectsPath]);
|
|
@@ -35,6 +35,7 @@ export const fireCoreStep = async function ({ coreStep, coreStepId, coreStepName
|
|
|
35
35
|
saveConfig,
|
|
36
36
|
userNodeVersion,
|
|
37
37
|
explicitSecretKeys,
|
|
38
|
+
enhancedSecretScan,
|
|
38
39
|
edgeFunctionsBootstrapURL,
|
|
39
40
|
deployId,
|
|
40
41
|
});
|
package/lib/steps/run_step.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const runStep: ({ event, childProcess, packageName, coreStep, coreStepId, coreStepName, coreStepDescription, coreStepQuiet, pluginPackageJson, loadedFrom, origin, condition, configPath, outputConfigPath, buildDir, packagePath, repositoryRoot, nodePath, index, childEnv, context, branch, envChanges, constants, steps, buildbotServerSocket, events, mode, api, errorMonitor, deployId, errorParams, error, failedPlugins, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, edgeFunctionsBootstrapURL, extensionMetadata, }: {
|
|
1
|
+
export declare const runStep: ({ event, childProcess, packageName, coreStep, coreStepId, coreStepName, coreStepDescription, coreStepQuiet, pluginPackageJson, loadedFrom, origin, condition, configPath, outputConfigPath, buildDir, packagePath, repositoryRoot, nodePath, index, childEnv, context, branch, envChanges, constants, steps, buildbotServerSocket, events, mode, api, errorMonitor, deployId, errorParams, error, failedPlugins, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, extensionMetadata, }: {
|
|
2
2
|
event: any;
|
|
3
3
|
childProcess: any;
|
|
4
4
|
packageName: any;
|
|
@@ -50,6 +50,7 @@ export declare const runStep: ({ event, childProcess, packageName, coreStep, cor
|
|
|
50
50
|
quiet: any;
|
|
51
51
|
userNodeVersion: any;
|
|
52
52
|
explicitSecretKeys: any;
|
|
53
|
+
enhancedSecretScan: any;
|
|
53
54
|
edgeFunctionsBootstrapURL: any;
|
|
54
55
|
extensionMetadata: any;
|
|
55
56
|
}) => Promise<{}>;
|
package/lib/steps/run_step.js
CHANGED
|
@@ -11,7 +11,7 @@ import { firePluginStep } from './plugin.js';
|
|
|
11
11
|
import { getStepReturn } from './return.js';
|
|
12
12
|
const tracer = trace.getTracer('steps');
|
|
13
13
|
// Run a step (core, build command or plugin)
|
|
14
|
-
export const runStep = async function ({ event, childProcess, packageName, coreStep, coreStepId, coreStepName, coreStepDescription, coreStepQuiet, pluginPackageJson, loadedFrom, origin, condition, configPath, outputConfigPath, buildDir, packagePath, repositoryRoot, nodePath, index, childEnv, context, branch, envChanges, constants, steps, buildbotServerSocket, events, mode, api, errorMonitor, deployId, errorParams, error, failedPlugins, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, edgeFunctionsBootstrapURL, extensionMetadata, }) {
|
|
14
|
+
export const runStep = async function ({ event, childProcess, packageName, coreStep, coreStepId, coreStepName, coreStepDescription, coreStepQuiet, pluginPackageJson, loadedFrom, origin, condition, configPath, outputConfigPath, buildDir, packagePath, repositoryRoot, nodePath, index, childEnv, context, branch, envChanges, constants, steps, buildbotServerSocket, events, mode, api, errorMonitor, deployId, errorParams, error, failedPlugins, configOpts, netlifyConfig, defaultConfig, configMutations, headersPath, redirectsPath, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, extensionMetadata, }) {
|
|
15
15
|
// Add relevant attributes to the upcoming span context
|
|
16
16
|
const attributes = {
|
|
17
17
|
'build.execution.step.name': coreStepName,
|
|
@@ -45,6 +45,7 @@ export const runStep = async function ({ event, childProcess, packageName, coreS
|
|
|
45
45
|
buildDir,
|
|
46
46
|
saveConfig,
|
|
47
47
|
explicitSecretKeys,
|
|
48
|
+
enhancedSecretScan,
|
|
48
49
|
deployId,
|
|
49
50
|
featureFlags,
|
|
50
51
|
});
|
|
@@ -104,6 +105,7 @@ export const runStep = async function ({ event, childProcess, packageName, coreS
|
|
|
104
105
|
featureFlags,
|
|
105
106
|
userNodeVersion,
|
|
106
107
|
explicitSecretKeys,
|
|
108
|
+
enhancedSecretScan,
|
|
107
109
|
edgeFunctionsBootstrapURL,
|
|
108
110
|
deployId,
|
|
109
111
|
api,
|
|
@@ -170,7 +172,7 @@ export const runStep = async function ({ event, childProcess, packageName, coreS
|
|
|
170
172
|
// or available. However, one might be created by a build plugin, in which case,
|
|
171
173
|
// those core plugins should be triggered. We use a dynamic `condition()` to
|
|
172
174
|
// model this behavior.
|
|
173
|
-
const shouldRunStep = async function ({ event, packageName, error, packagePath, failedPlugins, netlifyConfig, condition, constants, buildbotServerSocket, buildDir, saveConfig, explicitSecretKeys, deployId, featureFlags = {}, }) {
|
|
175
|
+
const shouldRunStep = async function ({ event, packageName, error, packagePath, failedPlugins, netlifyConfig, condition, constants, buildbotServerSocket, buildDir, saveConfig, explicitSecretKeys, enhancedSecretScan, deployId, featureFlags = {}, }) {
|
|
174
176
|
if (failedPlugins.includes(packageName) ||
|
|
175
177
|
(condition !== undefined &&
|
|
176
178
|
!(await condition({
|
|
@@ -181,6 +183,7 @@ const shouldRunStep = async function ({ event, packageName, error, packagePath,
|
|
|
181
183
|
netlifyConfig,
|
|
182
184
|
saveConfig,
|
|
183
185
|
explicitSecretKeys,
|
|
186
|
+
enhancedSecretScan,
|
|
184
187
|
deployId,
|
|
185
188
|
featureFlags,
|
|
186
189
|
})))) {
|
|
@@ -199,7 +202,7 @@ const getFireStep = function (packageName, coreStepId, event) {
|
|
|
199
202
|
const parentTag = normalizeTagName(packageName);
|
|
200
203
|
return measureDuration(tFireStep, event, { parentTag, category: 'pluginEvent' });
|
|
201
204
|
};
|
|
202
|
-
const tFireStep = function ({ defaultConfig, event, childProcess, packageName, pluginPackageJson, loadedFrom, outputFlusher, origin, coreStep, coreStepId, coreStepName, configPath, outputConfigPath, buildDir, repositoryRoot, packagePath, nodePath, childEnv, context, branch, envChanges, constants, steps, buildbotServerSocket, events, error, logs, debug, quiet, systemLog, verbose, saveConfig, errorParams, configOpts, netlifyConfig, configMutations, headersPath, redirectsPath, featureFlags, userNodeVersion, explicitSecretKeys, edgeFunctionsBootstrapURL, deployId, extensionMetadata, api, }) {
|
|
205
|
+
const tFireStep = function ({ defaultConfig, event, childProcess, packageName, pluginPackageJson, loadedFrom, outputFlusher, origin, coreStep, coreStepId, coreStepName, configPath, outputConfigPath, buildDir, repositoryRoot, packagePath, nodePath, childEnv, context, branch, envChanges, constants, steps, buildbotServerSocket, events, error, logs, debug, quiet, systemLog, verbose, saveConfig, errorParams, configOpts, netlifyConfig, configMutations, headersPath, redirectsPath, featureFlags, userNodeVersion, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, deployId, extensionMetadata, api, }) {
|
|
203
206
|
if (coreStep !== undefined) {
|
|
204
207
|
return fireCoreStep({
|
|
205
208
|
coreStep,
|
|
@@ -234,6 +237,7 @@ const tFireStep = function ({ defaultConfig, event, childProcess, packageName, p
|
|
|
234
237
|
saveConfig,
|
|
235
238
|
userNodeVersion,
|
|
236
239
|
explicitSecretKeys,
|
|
240
|
+
enhancedSecretScan,
|
|
237
241
|
edgeFunctionsBootstrapURL,
|
|
238
242
|
deployId,
|
|
239
243
|
api,
|
package/lib/steps/run_steps.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function runSteps({ defaultConfig, steps, buildbotServerSocket, events, configPath, outputConfigPath, headersPath, redirectsPath, buildDir, packagePath, repositoryRoot, nodePath, childEnv, context, branch, constants, mode, api, errorMonitor, deployId, errorParams, netlifyConfig, configOpts, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, edgeFunctionsBootstrapURL, }: {
|
|
1
|
+
export function runSteps({ defaultConfig, steps, buildbotServerSocket, events, configPath, outputConfigPath, headersPath, redirectsPath, buildDir, packagePath, repositoryRoot, nodePath, childEnv, context, branch, constants, mode, api, errorMonitor, deployId, errorParams, netlifyConfig, configOpts, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, }: {
|
|
2
2
|
defaultConfig: any;
|
|
3
3
|
steps: any;
|
|
4
4
|
buildbotServerSocket: any;
|
|
@@ -33,6 +33,7 @@ export function runSteps({ defaultConfig, steps, buildbotServerSocket, events, c
|
|
|
33
33
|
quiet: any;
|
|
34
34
|
userNodeVersion: any;
|
|
35
35
|
explicitSecretKeys: any;
|
|
36
|
+
enhancedSecretScan: any;
|
|
36
37
|
edgeFunctionsBootstrapURL: any;
|
|
37
38
|
}): Promise<{
|
|
38
39
|
stepsCount: number;
|
package/lib/steps/run_steps.js
CHANGED
|
@@ -7,7 +7,7 @@ import { runStep } from './run_step.js';
|
|
|
7
7
|
// list of `failedPlugins` (that ran `utils.build.failPlugin()`).
|
|
8
8
|
// If an error arises, runs `onError` events.
|
|
9
9
|
// Runs `onEnd` events at the end, whether an error was thrown or not.
|
|
10
|
-
export const runSteps = async function ({ defaultConfig, steps, buildbotServerSocket, events, configPath, outputConfigPath, headersPath, redirectsPath, buildDir, packagePath, repositoryRoot, nodePath, childEnv, context, branch, constants, mode, api, errorMonitor, deployId, errorParams, netlifyConfig, configOpts, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, edgeFunctionsBootstrapURL, }) {
|
|
10
|
+
export const runSteps = async function ({ defaultConfig, steps, buildbotServerSocket, events, configPath, outputConfigPath, headersPath, redirectsPath, buildDir, packagePath, repositoryRoot, nodePath, childEnv, context, branch, constants, mode, api, errorMonitor, deployId, errorParams, netlifyConfig, configOpts, logs, debug, systemLog, verbose, saveConfig, timers, testOpts, featureFlags, quiet, userNodeVersion, explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, }) {
|
|
11
11
|
const { index: stepsCount, error: errorA, netlifyConfig: netlifyConfigC, statuses: statusesB, failedPlugins: failedPluginsA, timers: timersC, configMutations: configMutationsB, metrics: metricsC, } = await pReduce(steps, async ({ index, error, failedPlugins, envChanges, netlifyConfig: netlifyConfigA, configMutations, headersPath: headersPathA, redirectsPath: redirectsPathA, statuses, timers: timersA, metrics: metricsA, }, { event, childProcess, packageName, extensionMetadata, coreStep, coreStepId, coreStepName, coreStepDescription, pluginPackageJson, loadedFrom, origin, condition, quiet: coreStepQuiet, }) => {
|
|
12
12
|
const { newIndex = index, newError = error, failedPlugin = [], newEnvChanges = {}, netlifyConfig: netlifyConfigB = netlifyConfigA, configMutations: configMutationsA = configMutations, headersPath: headersPathB = headersPathA, redirectsPath: redirectsPathB = redirectsPathA, newStatus, timers: timersB = timersA, metrics: metricsB = [], } = await runStep({
|
|
13
13
|
event,
|
|
@@ -62,6 +62,7 @@ export const runSteps = async function ({ defaultConfig, steps, buildbotServerSo
|
|
|
62
62
|
quiet,
|
|
63
63
|
userNodeVersion,
|
|
64
64
|
explicitSecretKeys,
|
|
65
|
+
enhancedSecretScan,
|
|
65
66
|
edgeFunctionsBootstrapURL,
|
|
66
67
|
});
|
|
67
68
|
const statusesA = addStatus({ newStatus, statuses, event, packageName, pluginPackageJson });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/build",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "33.0.0",
|
|
4
4
|
"description": "Netlify build module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./lib/index.js",
|
|
@@ -68,16 +68,16 @@
|
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@bugsnag/js": "^7.0.0",
|
|
70
70
|
"@netlify/blobs": "^8.2.0",
|
|
71
|
-
"@netlify/cache-utils": "^
|
|
72
|
-
"@netlify/config": "^
|
|
73
|
-
"@netlify/edge-bundler": "
|
|
74
|
-
"@netlify/framework-info": "^
|
|
75
|
-
"@netlify/functions-utils": "^
|
|
76
|
-
"@netlify/git-utils": "^
|
|
77
|
-
"@netlify/opentelemetry-utils": "^
|
|
71
|
+
"@netlify/cache-utils": "^6.0.0",
|
|
72
|
+
"@netlify/config": "^23.0.0",
|
|
73
|
+
"@netlify/edge-bundler": "14.0.0",
|
|
74
|
+
"@netlify/framework-info": "^10.0.0",
|
|
75
|
+
"@netlify/functions-utils": "^6.0.0",
|
|
76
|
+
"@netlify/git-utils": "^6.0.0",
|
|
77
|
+
"@netlify/opentelemetry-utils": "^2.0.0",
|
|
78
78
|
"@netlify/plugins-list": "^6.80.0",
|
|
79
|
-
"@netlify/run-utils": "^
|
|
80
|
-
"@netlify/zip-it-and-ship-it": "
|
|
79
|
+
"@netlify/run-utils": "^6.0.0",
|
|
80
|
+
"@netlify/zip-it-and-ship-it": "11.0.0",
|
|
81
81
|
"@sindresorhus/slugify": "^2.0.0",
|
|
82
82
|
"ansi-escapes": "^6.0.0",
|
|
83
83
|
"chalk": "^5.0.0",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"yargs": "^17.6.0"
|
|
127
127
|
},
|
|
128
128
|
"devDependencies": {
|
|
129
|
-
"@netlify/nock-udp": "^
|
|
129
|
+
"@netlify/nock-udp": "^5.0.0",
|
|
130
130
|
"@opentelemetry/api": "~1.8.0",
|
|
131
131
|
"@opentelemetry/sdk-trace-base": "~1.24.0",
|
|
132
132
|
"@types/node": "^14.18.53",
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
"yarn": "^1.22.22"
|
|
149
149
|
},
|
|
150
150
|
"peerDependencies": {
|
|
151
|
-
"@netlify/opentelemetry-sdk-setup": "^
|
|
151
|
+
"@netlify/opentelemetry-sdk-setup": "^2.0.0",
|
|
152
152
|
"@opentelemetry/api": "~1.8.0"
|
|
153
153
|
},
|
|
154
154
|
"peerDependenciesMeta": {
|
|
@@ -157,7 +157,7 @@
|
|
|
157
157
|
}
|
|
158
158
|
},
|
|
159
159
|
"engines": {
|
|
160
|
-
"node": "
|
|
160
|
+
"node": ">=18.14.0"
|
|
161
161
|
},
|
|
162
|
-
"gitHead": "
|
|
162
|
+
"gitHead": "f879acfe2bb508728578f9483c99bcdf372a2e83"
|
|
163
163
|
}
|