diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b6808ca..9f15d443 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- changed: Enhanced `dumpData()` to include server lists by provenance (info-server, custom) with URI sanitization + ## 3.8.11 (2026-02-03) - changed: CORS headers included in `webpack.config.js` for local development diff --git a/src/common/plugin/PluginState.ts b/src/common/plugin/PluginState.ts index 251f1d59..4bff0ec0 100644 --- a/src/common/plugin/PluginState.ts +++ b/src/common/plugin/PluginState.ts @@ -7,6 +7,7 @@ import { UtxoEngineProcessor } from '../utxobased/engine/UtxoEngineProcessor' import { asServerCache, ServerCache, + ServerInfo, ServerList, ServerScores } from './ServerScores' @@ -56,6 +57,43 @@ export interface PluginState { export function makePluginState(settings: PluginStateSettings): PluginState { const { defaultSettings, log, pluginDisklet, pluginId } = settings + const sanitizeServerUri = (uri: string): string => { + // `dumpData()` is often copied into support logs. + // Strip anything that might accidentally contain credentials/tokens. + // Keep scheme/host/path, but drop username/password + query/hash. + // Avoid using the global `URL` class since it is not guaranteed to exist + // in all runtime environments. + const noQueryHash = uri.split(/[?#]/)[0] + return noQueryHash.replace( + /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)([^@/]*@)(.*)$/, + '$1$3' + ) + } + + const sanitizeServerList = (serverList: ServerList): JsonObject => { + const out: JsonObject = {} + + for (const [serverUri, serverInfo] of Object.entries(serverList)) { + const sanitizedUri = sanitizeServerUri(serverUri) + const sanitizedInfo: ServerInfo = { + ...serverInfo, + serverUrl: sanitizeServerUri(serverInfo.serverUrl) + } + + // In case sanitization causes collisions (ex: query string removed), + // preserve all entries by suffixing the key. + if (out[sanitizedUri] == null) { + out[sanitizedUri] = sanitizedInfo + } else { + let i = 2 + while (out[`${sanitizedUri}#${i}`] != null) i++ + out[`${sanitizedUri}#${i}`] = sanitizedInfo + } + } + + return out + } + let engines: UtxoEngineProcessor[] = [] const memlet = makeMemlet(pluginDisklet) @@ -137,8 +175,18 @@ export function makePluginState(settings: PluginStateSettings): PluginState { }, dumpData(): JsonObject { + const selectedServerList = getSelectedServerList() + const infoServers = Object.keys( + instance.infoPayload?.blockbookServers ?? {} + ).map(sanitizeServerUri) + return { - 'pluginState.servers_': getSelectedServerList() + 'pluginState.servers_': sanitizeServerList(selectedServerList), + infoServers, + customServers: Object.keys(serverCache.customServers).map( + sanitizeServerUri + ), + enableCustomServers: serverCache.enableCustomServers } },