@percy/nightwatch 2.2.1-beta.1 → 2.2.1
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/commands/percySnapshot.js +22 -3
- package/lib/snapshot.js +13 -1
- package/package.json +1 -1
|
@@ -46,10 +46,13 @@ module.exports = class PercySnapshotCommand {
|
|
|
46
46
|
// Readiness gate — runs before serialize when CLI supports it.
|
|
47
47
|
const readinessDiagnostics = await waitForReady(this.api, options, utils, log);
|
|
48
48
|
|
|
49
|
-
//
|
|
49
|
+
// Serialize and capture the DOM. Merge .percy.yml config with per-snapshot
|
|
50
|
+
// options (per-call wins) before handing them to serialize.
|
|
51
|
+
// domScript + log are threaded through so concurrent percySnapshot calls
|
|
50
52
|
// (parallel workers in the same Node process) don't race on shared
|
|
51
53
|
// module-level state.
|
|
52
|
-
|
|
54
|
+
const mergedOptions = utils.mergeSnapshotOptions(options);
|
|
55
|
+
let { domSnapshot, url } = await captureDOM(this.api, mergedOptions, utils, domScript, log);
|
|
53
56
|
|
|
54
57
|
// Attach readiness diagnostics so the CLI can log timing and pass/fail
|
|
55
58
|
if (readinessDiagnostics && domSnapshot && typeof domSnapshot === 'object' && !Array.isArray(domSnapshot)) {
|
|
@@ -63,8 +66,24 @@ module.exports = class PercySnapshotCommand {
|
|
|
63
66
|
...snapshotOptions
|
|
64
67
|
} = options;
|
|
65
68
|
|
|
69
|
+
// Sanitize caller-supplied options before spreading them into the outbound
|
|
70
|
+
// POST body (CWE-284/CWE-1321 — PER-8722): drop prototype-pollution keys
|
|
71
|
+
// and code-bearing fields the SDK must never forward. clientInfo /
|
|
72
|
+
// environmentInfo are hard-coded AFTER the spread so callers can't override.
|
|
73
|
+
const BLOCKED_OPTION_KEYS = new Set([
|
|
74
|
+
'__proto__', 'constructor', 'prototype', 'execute', 'domTransformation'
|
|
75
|
+
]);
|
|
76
|
+
const safeOptions = {};
|
|
77
|
+
for (const key of Object.keys(snapshotOptions)) {
|
|
78
|
+
if (BLOCKED_OPTION_KEYS.has(key)) {
|
|
79
|
+
log.debug?.(`Ignoring disallowed percySnapshot option: ${key}`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
safeOptions[key] = snapshotOptions[key];
|
|
83
|
+
}
|
|
84
|
+
|
|
66
85
|
const postData = {
|
|
67
|
-
...
|
|
86
|
+
...safeOptions,
|
|
68
87
|
domSnapshot,
|
|
69
88
|
environmentInfo: ENV_INFO,
|
|
70
89
|
clientInfo: CLIENT_INFO,
|
package/lib/snapshot.js
CHANGED
|
@@ -127,6 +127,17 @@ function getCookies(browser) {
|
|
|
127
127
|
}).catch(() => []);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
// Cookie names that commonly hold session/auth secrets. These are stripped from
|
|
131
|
+
// the snapshot payload by default so credentials aren't forwarded to the Percy
|
|
132
|
+
// daemon and on to the cloud (CWE-200). Set PERCY_FORWARD_ALL_COOKIES=true to
|
|
133
|
+
// restore forwarding the full cookie jar.
|
|
134
|
+
const SENSITIVE_COOKIE_PATTERN = /session|token|auth|sid|jwt|bearer|csrf|xsrf/i;
|
|
135
|
+
|
|
136
|
+
function filterSensitiveCookies(cookies) {
|
|
137
|
+
if (process.env.PERCY_FORWARD_ALL_COOKIES === 'true' || !Array.isArray(cookies)) return cookies;
|
|
138
|
+
return cookies.filter(cookie => !SENSITIVE_COOKIE_PATTERN.test(cookie?.name || ''));
|
|
139
|
+
}
|
|
140
|
+
|
|
130
141
|
function resolveMaxFrameDepth(options = {}, utils) {
|
|
131
142
|
return clampFrameDepth(
|
|
132
143
|
options.maxIframeDepth ??
|
|
@@ -398,7 +409,7 @@ async function captureSerializedDOM(browser, options = {}, utils, domScript = nu
|
|
|
398
409
|
}, [serializeOptions]);
|
|
399
410
|
|
|
400
411
|
if (!domSnapshot) domSnapshot = {};
|
|
401
|
-
domSnapshot.cookies = await getCookies(browser);
|
|
412
|
+
domSnapshot.cookies = filterSensitiveCookies(await getCookies(browser));
|
|
402
413
|
|
|
403
414
|
// Capture cross-origin iframes. ctx carries the per-call domScript + log so
|
|
404
415
|
// concurrent percySnapshot invocations don't race on shared module state.
|
|
@@ -726,6 +737,7 @@ module.exports = {
|
|
|
726
737
|
slowScrollToBottom,
|
|
727
738
|
ignoreCanvasSerializationErrors,
|
|
728
739
|
ignoreStyleSheetSerializationErrors,
|
|
740
|
+
filterSensitiveCookies,
|
|
729
741
|
isUnsupportedIframeSrc,
|
|
730
742
|
getOrigin,
|
|
731
743
|
captureCorsIframes,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/nightwatch",
|
|
3
3
|
"description": "Nightwatch client library for visual testing with Percy",
|
|
4
|
-
"version": "2.2.1
|
|
4
|
+
"version": "2.2.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Perceptual Inc.",
|
|
7
7
|
"repository": "https://github.com/percy/percy-nightwatch",
|