@percy/core
Advanced tools
+59
-4
@@ -19,2 +19,3 @@ import fs from 'fs'; | ||
| import { createRequire } from 'module'; | ||
| import { configSchema } from './config.js'; | ||
| export const getPercyDomPath = url => { | ||
@@ -39,2 +40,53 @@ try { | ||
| // Walks the config schema and collects dot-paths of any fields marked `httpReadOnly: true` | ||
| // that are present in `body`. Driving this from the schema means new HTTP-blocked fields | ||
| // only need a one-line annotation next to their definition — no list to keep in sync here. | ||
| function findHttpReadOnlyPaths(body, schema, path = '') { | ||
| if (!body || typeof body !== 'object' || !(schema !== null && schema !== void 0 && schema.properties)) return []; | ||
| let paths = []; | ||
| for (let [key, propSchema] of Object.entries(schema.properties)) { | ||
| if (!Object.prototype.hasOwnProperty.call(body, key)) continue; | ||
| let childPath = path ? `${path}.${key}` : key; | ||
| if (propSchema !== null && propSchema !== void 0 && propSchema.httpReadOnly) { | ||
| paths.push(childPath); | ||
| } else { | ||
| paths.push(...findHttpReadOnlyPaths(body[key], propSchema, childPath)); | ||
| } | ||
| } | ||
| return paths; | ||
| } | ||
| // Top-level configSchema is a map of subschemas keyed by top-level config namespace | ||
| // (`discovery`, `snapshot`, …). Wrap it as a single object schema so the walker can recurse | ||
| // uniformly from the root. | ||
| const ROOT_CONFIG_SCHEMA = { | ||
| type: 'object', | ||
| properties: configSchema | ||
| }; | ||
| // Removes each dot-path's leaf from a deep clone of `body` and logs a warning per path. | ||
| // Returns the original `body` unchanged when `paths` is empty so we don't pay for a clone | ||
| // on every config request. Exported for unit testing: the `?.` chain in the reduce is a | ||
| // defensive guard for paths whose ancestor is absent from `body`. Through the production | ||
| // caller (stripBlockedConfigFields → findHttpReadOnlyPaths) every intermediate is verified | ||
| // present, so the guard is unreachable in normal use — but the explicit paths parameter | ||
| // lets a unit test exercise it without contorting the schema. | ||
| export function _applyHttpReadOnlyStripping(body, paths, log) { | ||
| if (!paths.length) return body; | ||
| let stripped = JSON.parse(JSON.stringify(body)); | ||
| for (let p of paths) { | ||
| let parts = p.split('.'); | ||
| let leaf = parts.pop(); | ||
| let parent = parts.reduce((o, k) => o === null || o === void 0 ? void 0 : o[k], stripped); | ||
| if (parent && typeof parent === 'object') delete parent[leaf]; | ||
| log.warn(`Ignoring \`${p}\` from /percy/config request: this field can only be set via the config file or CLI at startup.`); | ||
| } | ||
| return stripped; | ||
| } | ||
| // Returns a body with `httpReadOnly` fields removed. Caller guarantees `body` is truthy. | ||
| function stripBlockedConfigFields(body, log) { | ||
| return _applyHttpReadOnlyStripping(body, findHttpReadOnlyPaths(body, ROOT_CONFIG_SCHEMA), log); | ||
| } | ||
| // Parse PNG IHDR chunk for the screenshot's actual rendered dimensions. | ||
@@ -302,6 +354,9 @@ // Returns { width, height } when the buffer is a valid PNG with non-zero | ||
| // get or set config options | ||
| .route(['get', 'post'], '/percy/config', async (req, res) => res.json(200, { | ||
| config: req.body ? percy.set(req.body) : percy.config, | ||
| success: true | ||
| })) | ||
| .route(['get', 'post'], '/percy/config', async (req, res) => { | ||
| let body = req.body && stripBlockedConfigFields(req.body, logger('core:server')); | ||
| return res.json(200, { | ||
| config: body ? percy.set(body) : percy.config, | ||
| success: true | ||
| }); | ||
| }) | ||
| // responds once idle (may take a long time) | ||
@@ -308,0 +363,0 @@ .route('get', '/percy/idle', async (req, res) => res.json(200, { |
+7
-2
@@ -600,4 +600,8 @@ // Common config options used in Percy commands | ||
| properties: { | ||
| // httpReadOnly: never settable over /percy/config — accepting these would let any | ||
| // local process execute arbitrary code as the Percy user via flags like | ||
| // --renderer-cmd-prefix / --gpu-launcher. Must be set via static config or CLI. | ||
| executable: { | ||
| type: 'string' | ||
| type: 'string', | ||
| httpReadOnly: true | ||
| }, | ||
@@ -611,3 +615,4 @@ timeout: { | ||
| type: 'string' | ||
| } | ||
| }, | ||
| httpReadOnly: true | ||
| }, | ||
@@ -614,0 +619,0 @@ headless: { |
+9
-9
| { | ||
| "name": "@percy/core", | ||
| "version": "1.32.0-beta.3", | ||
| "version": "1.32.0-beta.4", | ||
| "license": "MIT", | ||
@@ -49,8 +49,8 @@ "repository": { | ||
| "@grpc/proto-loader": "^0.8.0", | ||
| "@percy/client": "1.32.0-beta.3", | ||
| "@percy/config": "1.32.0-beta.3", | ||
| "@percy/dom": "1.32.0-beta.3", | ||
| "@percy/logger": "1.32.0-beta.3", | ||
| "@percy/monitoring": "1.32.0-beta.3", | ||
| "@percy/webdriver-utils": "1.32.0-beta.3", | ||
| "@percy/client": "1.32.0-beta.4", | ||
| "@percy/config": "1.32.0-beta.4", | ||
| "@percy/dom": "1.32.0-beta.4", | ||
| "@percy/logger": "1.32.0-beta.4", | ||
| "@percy/monitoring": "1.32.0-beta.4", | ||
| "@percy/webdriver-utils": "1.32.0-beta.4", | ||
| "busboy": "^1.6.0", | ||
@@ -71,5 +71,5 @@ "content-disposition": "^0.5.4", | ||
| "optionalDependencies": { | ||
| "@percy/cli-doctor": "1.32.0-beta.3" | ||
| "@percy/cli-doctor": "1.32.0-beta.4" | ||
| }, | ||
| "gitHead": "7244de79269a8dddc4bd7883208bfbe4058fb382" | ||
| "gitHead": "2e5b1654806b609f961890f1a49fbc4154da1de2" | ||
| } |
Potential vulnerability
Supply chain riskInitial human review suggests the presence of a vulnerability in this package. It is pending further analysis and confirmation.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Potential vulnerability
Supply chain riskInitial human review suggests the presence of a vulnerability in this package. It is pending further analysis and confirmation.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 2 instances in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
653270
0.47%11060
0.51%45
-2.17%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated