chore: Bump latest changes from master (#21156)

This commit is contained in:
Mykola Mokhnach
2025-03-29 07:23:54 +01:00
committed by GitHub
parent 33073c0e5f
commit c5d64bb961
23 changed files with 732 additions and 654 deletions

1193
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -85,17 +85,17 @@
},
"devDependencies": {
"@colors/colors": "1.6.0",
"@eslint/js": "9.22.0",
"@eslint/js": "9.23.0",
"@tsconfig/node14": "14.1.3",
"@types/argparse": "2.0.17",
"@types/archiver": "6.0.3",
"@types/async-lock": "1.4.2",
"@types/base64-stream": "1.0.5",
"@types/bluebird": "3.5.42",
"@types/chai": "5.2.0",
"@types/chai": "5.2.1",
"@types/chai-as-promised": "8.0.2",
"@types/diff": "7.0.1",
"@types/express": "5.0.0",
"@types/diff": "7.0.2",
"@types/express": "5.0.1",
"@types/jsftp": "2.1.5",
"@types/json-schema": "7.0.15",
"@types/klaw": "3.0.6",
@@ -105,9 +105,9 @@
"@types/mocha": "10.0.10",
"@types/mv": "2.1.4",
"@types/ncp": "2.0.8",
"@types/node": "22.13.10",
"@types/node": "22.13.14",
"@types/pluralize": "0.0.33",
"@types/semver": "7.5.8",
"@types/semver": "7.7.0",
"@types/serve-favicon": "2.5.7",
"@types/shell-quote": "1.7.5",
"@types/sinon": "17.0.4",
@@ -127,9 +127,9 @@
"conventional-changelog-conventionalcommits": "7.0.2",
"cpy-cli": "5.0.0",
"cross-env": "7.0.3",
"eslint": "9.22.0",
"eslint": "9.23.0",
"eslint-config-prettier": "10.1.1",
"eslint-import-resolver-typescript": "3.9.1",
"eslint-import-resolver-typescript": "4.2.7",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-mocha": "10.5.0",
"eslint-plugin-promise": "7.2.1",
@@ -147,14 +147,14 @@
"rewiremock": "3.14.5",
"rimraf": "5.0.10",
"serve-static": "1.16.2",
"sinon": "19.0.2",
"sinon": "20.0.0",
"sync-monorepo-packages": "1.0.2",
"ts-node": "10.9.2",
"tsd": "0.31.2",
"typescript": "5.8.2",
"typescript-eslint": "8.26.1",
"typescript-eslint": "8.28.0",
"validate.js": "0.13.1",
"webdriverio": "9.12.0",
"webdriverio": "9.12.2",
"ws": "8.18.1",
"yaml-js": "0.3.1"
},

View File

@@ -73,7 +73,7 @@
"argparse": "2.0.1",
"async-lock": "1.4.1",
"asyncbox": "3.0.0",
"axios": "1.8.3",
"axios": "1.8.4",
"bluebird": "3.7.2",
"lilconfig": "3.1.3",
"lodash": "4.17.21",
@@ -84,7 +84,7 @@
"semver": "7.7.1",
"source-map-support": "0.5.21",
"teen_process": "2.3.1",
"type-fest": "4.37.0",
"type-fest": "4.38.0",
"winston": "3.17.0",
"wrap-ansi": "7.0.0",
"ws": "8.18.1",

View File

@@ -1,5 +1,5 @@
{
"devDependencies": {
"webdriverio": "9.12.0"
"webdriverio": "9.12.2"
}
}

View File

@@ -61,8 +61,15 @@ export function handleLogContext(req, res, next) {
const sessionId = SESSION_ID_PATTERN.exec(req.url)?.[1];
const sessionInfo = sessionId ? {sessionId, sessionSignature: calcSignature(sessionId)} : {};
const isSensitiveHeaderValue = _.isArray(req.headers['x-appium-is-sensitive'])
? _.first(req.headers['x-appium-is-sensitive'])
: req.headers['x-appium-is-sensitive'];
log.updateAsyncContext({requestId, ...sessionInfo}, true);
log.updateAsyncContext({
requestId,
...sessionInfo,
isSensitive: ['true', '1', 'yes'].includes(_.toLower(isSensitiveHeaderValue)),
}, true);
return next();
}

View File

@@ -12,7 +12,13 @@ import {
validateExecuteMethodParams,
} from './protocol';
import {NO_SESSION_ID_COMMANDS, ALL_COMMANDS, METHOD_MAP, routeToCommandName} from './routes';
import {errors, isErrorType, errorFromMJSONWPStatusCode, errorFromW3CJsonCode} from './errors';
import {
errors,
isErrorType,
errorFromMJSONWPStatusCode,
errorFromW3CJsonCode,
getResponseForW3CError,
} from './errors';
export {
routeConfiguringFunction,
@@ -34,4 +40,5 @@ export {
GET_STATUS_COMMAND,
LIST_DRIVER_COMMANDS_COMMAND,
LIST_DRIVER_EXTENSIONS_COMMAND,
getResponseForW3CError,
};

View File

@@ -49,7 +49,7 @@
"@colors/colors": "1.6.0",
"async-lock": "1.4.1",
"asyncbox": "3.0.0",
"axios": "1.8.3",
"axios": "1.8.4",
"bluebird": "3.7.2",
"body-parser": "1.20.3",
"express": "5.0.1",
@@ -62,7 +62,7 @@
"path-to-regexp": "8.2.0",
"serve-favicon": "2.5.0",
"source-map-support": "0.5.21",
"type-fest": "4.37.0",
"type-fest": "4.38.0",
"validate.js": "0.13.1"
},
"optionalDependencies": {

View File

@@ -62,7 +62,7 @@
"semver": "7.7.1",
"source-map-support": "0.5.21",
"teen_process": "2.3.1",
"type-fest": "4.37.0",
"type-fest": "4.38.0",
"typescript": "5.8.2",
"yaml": "2.7.0",
"yargs": "17.7.2",

View File

@@ -42,15 +42,15 @@
"types": "./build/lib/index.d.ts",
"dependencies": {
"@appium/types": "^0.25.2",
"axios": "1.8.3",
"axios": "1.8.4",
"bluebird": "3.7.2",
"chai": "5.2.0",
"chai-as-promised": "8.0.1",
"get-port": "5.1.1",
"lodash": "4.17.21",
"sinon": "19.0.2",
"sinon": "20.0.0",
"source-map-support": "0.5.21",
"type-fest": "4.37.0"
"type-fest": "4.38.0"
},
"peerDependencies": {
"appium": "^2.0.0-beta.43 || ^3.0.0-beta.0",

View File

@@ -33,7 +33,7 @@
"@eslint/js": "^9.0.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^10.0.0",
"eslint-import-resolver-typescript": "^3.5.0",
"eslint-import-resolver-typescript": "^4.0.0",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-mocha": "^10.4.0",
"eslint-plugin-promise": "^7.0.0",

View File

@@ -41,7 +41,7 @@
"bluebird": "3.7.2",
"lodash": "4.17.21",
"source-map-support": "0.5.21",
"webdriverio": "9.12.0"
"webdriverio": "9.12.2"
},
"peerDependencies": {
"appium": "^2.0.0-beta.35 || ^3.0.0-beta.0"

View File

@@ -1,5 +1,6 @@
import log from './lib/log';
export { markSensitive } from './lib/log';
export type * from './lib/types';
import log from './lib/log';
export {log};
export default log;

View File

@@ -16,7 +16,10 @@ import type {
import type {Writable} from 'node:stream';
import {AsyncLocalStorage} from 'node:async_hooks';
import { unleakString } from './utils';
import { SecureValuesPreprocessor } from './secure-values-preprocessor';
import {
DEFAULT_SECURE_REPLACER,
SecureValuesPreprocessor
} from './secure-values-preprocessor';
import { LRUCache } from 'lru-cache';
const DEFAULT_LOG_LEVELS = [
@@ -32,6 +35,7 @@ const DEFAULT_LOG_LEVELS = [
['silent', Infinity],
] as const;
const DEFAULT_HISTORY_SIZE = 10000;
const SENSITIVE_MESSAGE_KEY = 'f2b06625-35a2-4ed3-939a-b0b0a4abc750';
setBlocking(true);
@@ -230,17 +234,11 @@ export class Log extends EventEmitter implements Logger {
}
const messageArguments: any[] = [];
let stack: string | null = null;
for (const formatArg of [message, ...args]) {
messageArguments.push(formatArg);
// resolve stack traces to a plain string.
if (_.isError(formatArg) && formatArg.stack) {
Object.defineProperty(formatArg, 'stack', {
value: (stack = formatArg.stack + ''),
enumerable: true,
writable: true,
});
}
let stack: string | undefined;
for (const arg of [message, ...args]) {
const result = this._formatLogArgument(arg);
stack = result.stack;
messageArguments.push(result.arg);
}
if (stack) {
messageArguments.unshift(`${stack}\n`);
@@ -382,10 +380,44 @@ export class Log extends EventEmitter implements Logger {
}
}
private _formatLogArgument(arg: any): ArgumentFormatResult {
const result: ArgumentFormatResult = {
arg,
stack: undefined,
};
// mask sensitive data
if (_.has(result.arg, SENSITIVE_MESSAGE_KEY)) {
const { isSensitive } = this._asyncStorage.getStore() ?? {};
result.arg = isSensitive ? DEFAULT_SECURE_REPLACER : result.arg[SENSITIVE_MESSAGE_KEY];
}
// resolve stack traces to a plain string
if (_.isError(result.arg) && result.arg.stack) {
result.stack = result.arg.stack + '';
Object.defineProperty(result.arg, 'stack', {
value: result.stack,
enumerable: true,
writable: true,
});
}
return result;
}
// this functionality has been deliberately disabled
private clearProgress(): void {}
private showProgress(): void {}
}
export function markSensitive<T=any>(logMessage: T): {[SENSITIVE_MESSAGE_KEY]: T} {
return {[SENSITIVE_MESSAGE_KEY]: logMessage};
}
interface ArgumentFormatResult {
arg: any,
stack: string | undefined,
}
export const GLOBAL_LOG = new Log();
export default GLOBAL_LOG;

View File

@@ -6,7 +6,7 @@ import type {
LogFilter,
} from './types';
const DEFAULT_REPLACER = '**SECURE**';
export const DEFAULT_SECURE_REPLACER = '**SECURE**';
/**
* Type guard for log filter type
@@ -42,7 +42,7 @@ export class SecureValuesPreprocessor {
*/
parseRule(rule: string | LogFilter): SecureValuePreprocessingRule {
let pattern: string | undefined;
let replacer = DEFAULT_REPLACER;
let replacer = DEFAULT_SECURE_REPLACER;
let flags = ['g'];
if (_.isString(rule)) {
if (rule.length === 0) {
@@ -142,7 +142,7 @@ export class SecureValuesPreprocessor {
let result = str;
for (const rule of this._rules) {
result = result.replace(rule.pattern, rule.replacer ?? DEFAULT_REPLACER);
result = result.replace(rule.pattern, rule.replacer ?? DEFAULT_SECURE_REPLACER);
}
return result;
}

View File

@@ -1,10 +1,12 @@
/* eslint-disable no-console */
import { Log } from '../../lib/log';
import { Log, markSensitive} from '../../lib/log';
import { unleakString } from '../../lib/utils';
import {Stream} from 'node:stream';
import _ from 'lodash';
describe('basic', function () {
let chai;
/** @type {Log} */
let log;
before(async function () {
@@ -360,6 +362,15 @@ describe('basic', function () {
});
});
it('replaces senstive messages', async function() {
log.updateAsyncStorage({isSensitive: true}, true);
log.log('verbose', 'test', markSensitive('log 1'));
_.last(log.record).message.should.eql('**SECURE**');
log.updateAsyncStorage({isSensitive: false}, true);
log.log('verbose', 'test', markSensitive('log 1'));
_.last(log.record).message.should.eql('log 1');
});
it('max record size', function() {
log.maxRecordSize = 3;
log.log('verbose', 'test', 'log 1');

View File

@@ -4,11 +4,11 @@ import _ from 'lodash';
import { tempDir, fs, logger } from '@appium/support';
import { AddRequestResult, ItemOptions, StorageItem } from './types';
import type { Express, Request, Response } from 'express';
import { toW3cResponseError } from './utils';
import { AppiumServer } from '@appium/types';
import { LRUCache } from 'lru-cache';
import WebSocket from 'ws';
import { EventEmitter } from 'node:stream';
import { getResponseForW3CError } from 'appium/driver';
const log = logger.getLogger('StoragePlugin');
@@ -32,7 +32,7 @@ export class StoragePlugin extends BasePlugin {
const value = await STORAGE_HANDLERS[methodName](req, httpServer);
body = {value: value ?? null};
} catch (e) {
[status, body] = toW3cResponseError(e);
[status, body] = getResponseForW3CError(e);
}
log.debug(
`Responding to ${methodName} with ${_.truncate(JSON.stringify(body.value), {length: 200})}`
@@ -152,7 +152,7 @@ function prepareWebSockets(httpServer: AppiumServer, itemOptions: ItemOptions):
// in case of a failure we do not want to close the server yet
// in anticipation of a retry
log.error(e);
const [, errorBody] = toW3cResponseError(e);
const [, errorBody] = getResponseForW3CError(e);
signaler.emit('status', errorBody);
}
});

View File

@@ -1,14 +0,0 @@
import _ from 'lodash';
import { errors } from 'appium/driver';
export function toW3cResponseError(err: any): [number, Record<string, any>] {
const protocolError = _.has(err, 'w3cStatus') ? err : new errors.UnknownError(err);
return [protocolError.w3cStatus, {
value: {
error: protocolError.error,
message: protocolError.message,
stacktrace: protocolError.stacktrace || protocolError.stack,
},
}];
}

View File

@@ -1,4 +1,4 @@
import globalLog from '@appium/logger';
import globalLog, { markSensitive as _markSensitive } from '@appium/logger';
import _ from 'lodash';
import moment from 'moment';
@@ -84,6 +84,23 @@ export function getLogger(prefix = null) {
return /** @type {AppiumLogger} */ (wrappedLogger);
}
/**
* Marks arbitrary log message as sensitive.
* This message will then be replaced with the default replacer
* while being logged by any `info`, `debug`, etc. methods if the
* asyncStorage has `isSensitive` flag enabled in its async context.
* The latter is enabled by the corresponding HTTP middleware
* in response to the `X-Appium-Is-Sensitive` request header
* being set to 'true'.
*
* @template {any} T
* @param {T} logMessage
* @returns {{[k: string]: T}}
*/
export function markSensitive(logMessage) {
return _markSensitive(logMessage);
}
/**
*
* @returns {[import('@appium/logger').Logger, boolean]}

View File

@@ -46,7 +46,7 @@
"@appium/types": "^0.25.2",
"@colors/colors": "1.6.0",
"archiver": "7.0.1",
"axios": "1.8.3",
"axios": "1.8.4",
"base64-stream": "1.0.0",
"bluebird": "3.7.2",
"bplist-creator": "0.1.1",
@@ -73,7 +73,7 @@
"source-map-support": "0.5.21",
"supports-color": "8.1.1",
"teen_process": "2.3.1",
"type-fest": "4.37.0",
"type-fest": "4.38.0",
"uuid": "11.1.0",
"which": "4.0.0",
"yauzl": "3.2.0"

View File

@@ -1,4 +1,3 @@
import B from 'bluebird';
import sinon from 'sinon';
/**
@@ -68,7 +67,7 @@ export class MockStore {
if (this.#mocks) {
throw new ReferenceError('Cannot create mocks twice; call `reset()` first.');
}
this.sandbox = this.sandbox ?? sinon.createSandbox().usingPromise(B);
this.sandbox = this.sandbox ?? sinon.createSandbox();
for (const [key, value] of Object.entries(mockDefs)) {
this[key] = this.sandbox.mock(value);
}

View File

@@ -1,6 +1,5 @@
import sinon from 'sinon';
import _ from 'lodash';
import B from 'bluebird';
import {MockStore} from './mock-utils';
/**
@@ -59,7 +58,7 @@ export class SandboxStore {
* @param {Mocks} mocks
*/
createSandbox(mocks = /** @type {Mocks} */ ({})) {
this.sandbox = this.sandbox ?? sinon.createSandbox().usingPromise(B);
this.sandbox = this.sandbox ?? sinon.createSandbox();
this.mocks = new MockStore(this.sandbox).createMocks(mocks);
}

View File

@@ -50,7 +50,7 @@
"bluebird": "3.7.2",
"lodash": "4.17.21",
"loud-rejection": "2.2.0",
"sinon": "19.0.2",
"sinon": "20.0.0",
"source-map-support": "0.5.21"
},
"engines": {

View File

@@ -41,7 +41,7 @@
"@appium/logger": "^1.6.1",
"@appium/schema": "^0.8.1",
"@appium/tsconfig": "^0.3.5",
"type-fest": "4.37.0"
"type-fest": "4.38.0"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",