Merge pull request #601 from vector-im/filter-token

Ensure unwanted data do not end up in logs
This commit is contained in:
Bruno Windels 2021-11-30 10:02:07 +01:00 committed by GitHub
commit 19827a0b5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 12 deletions

View file

@ -17,15 +17,17 @@ limitations under the License.
import {LogItem} from "./LogItem"; import {LogItem} from "./LogItem";
import {LogLevel, LogFilter} from "./LogFilter"; import {LogLevel, LogFilter} from "./LogFilter";
import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./types"; import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem, ISerializedItem} from "./types";
import type {Platform} from "../platform/web/Platform.js"; import type {Platform} from "../platform/web/Platform.js";
export abstract class BaseLogger implements ILogger { export abstract class BaseLogger implements ILogger {
protected _openItems: Set<LogItem> = new Set(); protected _openItems: Set<LogItem> = new Set();
protected _platform: Platform; protected _platform: Platform;
protected _serializedTransformer: (item: ISerializedItem) => ISerializedItem;
constructor({platform}) { constructor({platform, serializedTransformer = (item: ISerializedItem) => item}) {
this._platform = platform; this._platform = platform;
this._serializedTransformer = serializedTransformer;
} }
log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info): void { log(labelOrValues: LabelOrValues, logLevel: LogLevel = LogLevel.Info): void {

View file

@ -26,7 +26,7 @@ import {BaseLogger} from "./BaseLogger";
import type {Interval} from "../platform/web/dom/Clock"; import type {Interval} from "../platform/web/dom/Clock";
import type {Platform} from "../platform/web/Platform.js"; import type {Platform} from "../platform/web/Platform.js";
import type {BlobHandle} from "../platform/web/dom/BlobHandle.js"; import type {BlobHandle} from "../platform/web/dom/BlobHandle.js";
import type {ILogItem, ILogExport} from "./types"; import type {ILogItem, ILogExport, ISerializedItem} from "./types";
import type {LogFilter} from "./LogFilter"; import type {LogFilter} from "./LogFilter";
type QueuedItem = { type QueuedItem = {
@ -40,7 +40,7 @@ export class IDBLogger extends BaseLogger {
private readonly _flushInterval: Interval; private readonly _flushInterval: Interval;
private _queuedItems: QueuedItem[]; private _queuedItems: QueuedItem[];
constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform}) { constructor(options: {name: string, flushInterval?: number, limit?: number, platform: Platform, serializedTransformer?: (item: ISerializedItem) => ISerializedItem}) {
super(options); super(options);
const {name, flushInterval = 60 * 1000, limit = 3000} = options; const {name, flushInterval = 60 * 1000, limit = 3000} = options;
this._name = name; this._name = name;
@ -119,10 +119,13 @@ export class IDBLogger extends BaseLogger {
_persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void { _persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void {
const serializedItem = logItem.serialize(filter, undefined, forced); const serializedItem = logItem.serialize(filter, undefined, forced);
if (serializedItem) {
const transformedSerializedItem = this._serializedTransformer(serializedItem);
this._queuedItems.push({ this._queuedItems.push({
json: JSON.stringify(serializedItem) json: JSON.stringify(transformedSerializedItem)
}); });
} }
}
_persistQueuedItems(items: QueuedItem[]): void { _persistQueuedItems(items: QueuedItem[]): void {
try { try {

View file

@ -132,11 +132,7 @@ export class Platform {
this.clock = new Clock(); this.clock = new Clock();
this.encoding = new Encoding(); this.encoding = new Encoding();
this.random = Math.random; this.random = Math.random;
if (options?.development) { this._createLogger(options?.development);
this.logger = new ConsoleLogger({platform: this});
} else {
this.logger = new IDBLogger({name: "hydrogen_logs", platform: this});
}
this.history = new History(); this.history = new History();
this.onlineStatus = new OnlineStatus(); this.onlineStatus = new OnlineStatus();
this._serviceWorkerHandler = null; this._serviceWorkerHandler = null;
@ -162,6 +158,21 @@ export class Platform {
this._disposables = new Disposables(); this._disposables = new Disposables();
} }
_createLogger(isDevelopment) {
// Make sure that loginToken does not end up in the logs
const transformer = (item) => {
if (item.e?.stack) {
item.e.stack = item.e.stack.replace(/(?<=\/\?loginToken=).+/, "<snip>");
}
return item;
};
if (isDevelopment) {
this.logger = new ConsoleLogger({platform: this});
} else {
this.logger = new IDBLogger({name: "hydrogen_logs", platform: this, serializedTransformer: transformer});
}
}
get updateService() { get updateService() {
return this._serviceWorkerHandler; return this._serviceWorkerHandler;
} }
@ -272,3 +283,30 @@ export class Platform {
this._disposables.dispose(); this._disposables.dispose();
} }
} }
import {LogItem} from "../../logging/LogItem";
export function tests() {
return {
"loginToken should not be in logs": (assert) => {
const transformer = (item) => {
if (item.e?.stack) {
item.e.stack = item.e.stack.replace(/(?<=\/\?loginToken=).+/, "<snip>");
}
return item;
};
const logger = {
_queuedItems: [],
_serializedTransformer: transformer,
_now: () => {}
};
logger.persist = IDBLogger.prototype._persistItem.bind(logger);
const logItem = new LogItem("test", 1, logger);
logItem.error = new Error();
logItem.error.stack = "main http://localhost:3000/src/main.js:55\n<anonymous> http://localhost:3000/?loginToken=secret:26"
logger.persist(logItem, null, false);
const item = logger._queuedItems.pop();
console.log(item);
assert.strictEqual(item.json.search("secret"), -1);
}
};
}