From 3ea628a02f4d19ea9c1554012aaa5ba02e894404 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 12 Apr 2021 15:38:19 +1000 Subject: [PATCH 1/7] pin certificate for seed nodes --- certificates/public-loki-foundation.crt | 24 ++++++ certificates/storage-seed-1.crt | 25 +++++++ certificates/storage-seed-3.crt | 25 +++++++ config/default.json | 12 +-- package.json | 1 + ts/session/snode_api/serviceNodeAPI.ts | 99 +++++++++++++++++++++++++ ts/session/snode_api/snodePool.ts | 13 ++-- 7 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 certificates/public-loki-foundation.crt create mode 100644 certificates/storage-seed-1.crt create mode 100644 certificates/storage-seed-3.crt diff --git a/certificates/public-loki-foundation.crt b/certificates/public-loki-foundation.crt new file mode 100644 index 000000000..344a05543 --- /dev/null +++ b/certificates/public-loki-foundation.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEEzCCAvugAwIBAgIUY9RQqbjhsQEkdeSgV9L0os9xZ7AwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCQVUxETAPBgNVBAgMCFZpY3RvcmlhMRIwEAYDVQQHDAlN +ZWxib3VybmUxJTAjBgNVBAoMHE94ZW4gUHJpdmFjeSBUZWNoIEZvdW5kYXRpb24x +HzAdBgNVBAMMFnB1YmxpYy5sb2tpLmZvdW5kYXRpb24wHhcNMjEwNDA3MDExMDMx +WhcNMjMwNDA3MDExMDMxWjB8MQswCQYDVQQGEwJBVTERMA8GA1UECAwIVmljdG9y +aWExEjAQBgNVBAcMCU1lbGJvdXJuZTElMCMGA1UECgwcT3hlbiBQcml2YWN5IFRl +Y2ggRm91bmRhdGlvbjEfMB0GA1UEAwwWcHVibGljLmxva2kuZm91bmRhdGlvbjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5dBJSIR5+VNNUxUOo6FG0e +RmZteRqBt50KXGbOi2A23a6sa57pLFh9Yw3hmlWV+QCL7ipG1X4IC55OStgoesf+ +K65VwEMP6Mtq0sSJS3R5TiuV2ZSRdSZTVjUyRXVe5T4Aw6wXVTAbc/HsyS780tDh +GclfDHhonPhZpmTAnSbfMOS+BfOnBNvDxdto0kVh6k5nrGlkT4ECloulHTQF2lwJ +0D6IOtv9AJplPdg6s2c4dY7durOdvr3NNVfvn5PTeRvbEPqzZur4WUUKIPNGu6mY +PxImqd4eUsL0Vod4aAsTIx4YMmCTi0m9W6zJI6nXcK/6a+iiA3+NTNMzEA9gQhEC +AwEAAaOBjDCBiTAdBgNVHQ4EFgQU/zahokxLvvFUpbnM6z/pwS1KsvwwHwYDVR0j +BBgwFoAU/zahokxLvvFUpbnM6z/pwS1KsvwwDwYDVR0TAQH/BAUwAwEB/zAhBgNV +HREEGjAYghZwdWJsaWMubG9raS5mb3VuZGF0aW9uMBMGA1UdJQQMMAoGCCsGAQUF +BwMBMA0GCSqGSIb3DQEBCwUAA4IBAQBql+JvoqpaYrFFTOuDn08U+pdcd3GM7tbI +zRH5LU+YnIpp9aRheek+2COW8DXsIy/kUngETCMLmX6ZaUj/WdHnTDkB0KTgxSHv +ad3ZznKPKZ26qJOklr+0ZWj4J3jHbisSzql6mqq7R2Kp4ESwzwqxvkbykM5RUnmz +Go/3Ol7bpN/ZVwwEkGfD/5rRHf57E/gZn2pBO+zotlQgr7HKRsIXQ2hIXVQqWmPQ +lvfIwrwAZlfES7BARFnHOpyVQxV8uNcV5K5eXzuVFjHBqvq+BtyGhWkP9yKJCHS9 +OUXxch0rzRsH2C/kRVVhEk0pI3qlFiRC8pCJs98SNE9l69EQtG7I +-----END CERTIFICATE----- diff --git a/certificates/storage-seed-1.crt b/certificates/storage-seed-1.crt new file mode 100644 index 000000000..7360d6fca --- /dev/null +++ b/certificates/storage-seed-1.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEITCCAwmgAwIBAgIUJsox1ZQPK/6iDsCC+MUJfNAlFuYwDQYJKoZIhvcNAQEL +BQAwgYAxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJ +TWVsYm91cm5lMSUwIwYDVQQKDBxPeGVuIFByaXZhY3kgVGVjaCBGb3VuZGF0aW9u +MSMwIQYDVQQDDBpzdG9yYWdlLnNlZWQxLmxva2kubmV0d29yazAeFw0yMTA0MDcw +MTE5MjZaFw0yMzA0MDcwMTE5MjZaMIGAMQswCQYDVQQGEwJBVTERMA8GA1UECAwI +VmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJuZTElMCMGA1UECgwcT3hlbiBQcml2 +YWN5IFRlY2ggRm91bmRhdGlvbjEjMCEGA1UEAwwac3RvcmFnZS5zZWVkMS5sb2tp +Lm5ldHdvcmswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtWH3Rz8Dd +kEmM7tcBWHrJ/G8drr/+qidboEVYzxpyRjszaDxKXVhx4eBBsAD5RuCWuTuZmM8k +TKEDLtf8xfb5SQ7YNX+346s9NXS5Poy4CIPASiW/QWXgIHFbVdv2hC+cKOP61OLM +OGnOxfig6tQyd6EaCkedpY1DvSa2lPnQSOwC/jXCx6Vboc0zTY5R2bHtNc9hjIFP +F4VClLAQSh2F4R1V9MH5KZMW+CCP6oaJY658W9JYXYRwlLrL2EFOVxHgcxq/6+fw ++axXK9OXJrGZjuA+hiz+L/uAOtE4WuxrSeuNMHSrMtM9QqVn4bBuMJ21mAzfNoMP +OIwgMT9DwUjVAgMBAAGjgZAwgY0wHQYDVR0OBBYEFOubJp9SoXIw+ONiWgkOaW8K +zI/TMB8GA1UdIwQYMBaAFOubJp9SoXIw+ONiWgkOaW8KzI/TMA8GA1UdEwEB/wQF +MAMBAf8wJQYDVR0RBB4wHIIac3RvcmFnZS5zZWVkMS5sb2tpLm5ldHdvcmswEwYD +VR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIiHNhNrjYvwXVWs +gacx8T/dpqpu9GE3L17LotgQr4R+IYHpNtcmwOTdtWWFfUTr75OCs+c3DqgRKEoj +lnULOsVcalpAGIvW15/fmZWOf66Dpa4+ljDmAc3SOQiD0gGNtqblgI5zG1HF38QP +hjYRhCZ5CVeGOLucvQ8tVVwQvArPFIkBr0jH9jHVgRWEI2MeI3FsU2H93D4TfGln +N4SmmCfYBqygaaZBWkJEt0bYhn8uGHdU9UY9L2FPtfHVKkmFgO7cASGlvXS7B/TT +/8IgbtM3O8mZc2asmdQhGwoAKz93ryyCd8X2UZJg/IwCSCayOlYZWY2fR4OPQmmV +gxJsm+g= +-----END CERTIFICATE----- diff --git a/certificates/storage-seed-3.crt b/certificates/storage-seed-3.crt new file mode 100644 index 000000000..92574b769 --- /dev/null +++ b/certificates/storage-seed-3.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEITCCAwmgAwIBAgIUc486Dy9Y00bUFfDeYmJIgSS5xREwDQYJKoZIhvcNAQEL +BQAwgYAxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJ +TWVsYm91cm5lMSUwIwYDVQQKDBxPeGVuIFByaXZhY3kgVGVjaCBGb3VuZGF0aW9u +MSMwIQYDVQQDDBpzdG9yYWdlLnNlZWQzLmxva2kubmV0d29yazAeFw0yMTA0MDcw +MTIwNTJaFw0yMzA0MDcwMTIwNTJaMIGAMQswCQYDVQQGEwJBVTERMA8GA1UECAwI +VmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJuZTElMCMGA1UECgwcT3hlbiBQcml2 +YWN5IFRlY2ggRm91bmRhdGlvbjEjMCEGA1UEAwwac3RvcmFnZS5zZWVkMy5sb2tp +Lm5ldHdvcmswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtokMlsFzf +piYeD0EVNikMyvjltpF6fUEde9NOVrTtNTQT6kkDk+/0HF5LYgPaatv6v7fpUQHi +kIwd6F0LTRGeWDFdsaWMdtlR1n/GxLPrOROsE8dcLt6GLavPf9rDabgva93m/JD6 +XW+Ne+MPEwqS8dAmFGhZd0gju6AtKFoSHnIf5pSQN6fSZUF/JQtHLVprAKKWKDiS +ZwmWbmrZR2aofLD/VRpetabajnZlv9EeWloQwvUsw1C1hkAmmtFeeXtg7ePwrOzo +6CnmcUJwOmi+LWqQV4A+58RZPFKaZoC5pzaKd0OYB8eZ8HB1F41UjGJgheX5Cyl4 ++amfF3l8dSq1AgMBAAGjgZAwgY0wHQYDVR0OBBYEFM9VSq4pGydjtX92Beul4+ml +jBKtMB8GA1UdIwQYMBaAFM9VSq4pGydjtX92Beul4+mljBKtMA8GA1UdEwEB/wQF +MAMBAf8wJQYDVR0RBB4wHIIac3RvcmFnZS5zZWVkMy5sb2tpLm5ldHdvcmswEwYD +VR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAAYxmhhkcKE1n6g1 +JqOa3UCBo4EfbqY5+FDZ0FVqv/cwemwVpKLbe6luRIS8poomdPCyMOS45V7wN3H9 +cFpfJ1TW19ydPVKmCXrl29ngmnY1q7YDwE/4qi3VK/UiqDkTHMKWjVPkenOyi8u6 +VVQANXSnKrn6GtigNFjGyD38O+j7AUSXBtXOJczaoF6r6BWgwQZ2WmgjuwvKTWSN +4r8uObERoAQYVaeXfgdr4e9X/JdskBDaLFfoW/rrSozHB4FqVNFW96k+aIUgRa5p +9kv115QcBPCSh9qOyTHij4tswS6SyOFaiKrNC4hgHQXP4QgioKmtsR/2Y+qJ6ddH +6oo+4QU= +-----END CERTIFICATE----- diff --git a/config/default.json b/config/default.json index 029f2a0c0..03ac99195 100644 --- a/config/default.json +++ b/config/default.json @@ -6,16 +6,16 @@ "defaultPoWDifficulty": "1", "seedNodeList": [ { - "ip_url": "http://116.203.53.213/", - "url": "https://storage.seed1.loki.network/" + "ip_url": "http://116.203.53.213:4433/", + "url": "https://storage.seed1.loki.network:4433/" }, { - "ip_url": "http://212.199.114.66/", - "url": "https://storage.seed3.loki.network/" + "ip_url": "http://212.199.114.66:4433/", + "url": "https://storage.seed3.loki.network:4433/" }, { - "ip_url": "http://144.76.164.202/", - "url": "https://public.loki.foundation/" + "ip_url": "http://144.76.164.202:4433/", + "url": "https://public.loki.foundation:4433/" } ], "updatesEnabled": false, diff --git a/package.json b/package.json index a0366d6fc..3ae7a033e 100644 --- a/package.json +++ b/package.json @@ -300,6 +300,7 @@ "debug_log_preload.js", "password_preload.js", "main.js", + "certificates/**", "images/**", "fonts/*", "build/assets", diff --git a/ts/session/snode_api/serviceNodeAPI.ts b/ts/session/snode_api/serviceNodeAPI.ts index 95aa4dfe7..d1a717e92 100644 --- a/ts/session/snode_api/serviceNodeAPI.ts +++ b/ts/session/snode_api/serviceNodeAPI.ts @@ -1,5 +1,14 @@ // we don't throw or catch here import { default as insecureNodeFetch } from 'node-fetch'; +import https from 'https'; +import crypto from 'crypto'; + +import fs from 'fs'; +import path from 'path'; +import tls from 'tls'; +import Electron from 'electron'; + +const { remote } = Electron; import { snodeRpc } from './lokiRpc'; import { @@ -78,6 +87,93 @@ export async function getVersion( } } +const sha256 = (s: string) => { + return crypto + .createHash('sha256') + .update(s) + .digest('base64'); +}; + +const getSslAgentForSeedNode = (seedNodeHost: string) => { + let filePrefix = ''; + let pubkey256 = ''; + let cert256 = ''; + + switch (seedNodeHost) { + case 'storage.seed1.loki.network': + filePrefix = 'storage-seed-1'; + pubkey256 = 'JOsnIcAanVbgECNA8lHtC8f/cqN9m8EP7jKT6XCjeL8='; + cert256 = + '6E:2B:AC:F3:6E:C1:FF:FF:24:F3:CA:92:C6:94:81:B4:82:43:DF:C7:C6:03:98:B8:F5:6B:7D:30:7B:16:C1:CB'; + break; + case 'storage.seed3.loki.network': + filePrefix = 'storage-seed-3'; + pubkey256 = 'mMmZD3lG4Fi7nTC/EWzRVaU3bbCLsH6Ds2FHSTpo0Rk='; + cert256 = + '24:13:4C:0A:03:D8:42:A6:09:DE:35:76:F4:BD:FB:11:60:DB:F9:88:9F:98:46:B7:60:A6:60:0C:4C:CF:60:72'; + + break; + case 'public.loki.foundation': + filePrefix = 'public-loki-foundation'; + pubkey256 = 'W+Zv52qlcm1BbdpJzFwxZrE7kfmEboq7h3Dp/+Q3RPg='; + cert256 = + '40:E4:67:7D:18:6B:4D:08:8D:E9:D5:47:52:25:B8:28:E0:D3:63:99:9B:38:46:7D:92:19:5B:61:B9:AE:0E:EA'; + + break; + + default: + throw new Error(`Unknown seed node: ${seedNodeHost}`); + } + // tslint:disable: non-literal-fs-path + // read the cert each time. We only run this request once for each seed node nevertheless. + const appPath = remote.app.getAppPath(); + const crt = fs.readFileSync( + path.join(appPath, `/certificates/${filePrefix}.crt`), + 'utf-8' + ); + // debugger; + const sslOptions = { + // as the seed nodes are using a self signed certificate, we have to provide it here. + ca: crt, + // we might need to selectively disable that for tests on swarm-testing or so. + // we have to reject them, otherwise our errors returned in the checkServerIdentity are simply not making the call fail. + // so in production, rejectUnauthorized must be true. + rejectUnauthorized: true, + keepAlive: false, + checkServerIdentity: (host: string, cert: any) => { + // Make sure the certificate is issued to the host we are connected to + const err = tls.checkServerIdentity(host, cert); + if (err) { + return err; + } + + // we might need to selectively disable that for tests on swarm-testing or so. + + // Pin the public key, similar to HPKP pin-sha25 pinning + if (sha256(cert.pubkey) !== pubkey256) { + const msg = + 'Certificate verification error: ' + + `The public key of '${cert.subject.CN}' ` + + 'does not match our pinned fingerprint'; + return new Error(msg); + } + + // Pin the exact certificate, rather than the pub key + if (cert.fingerprint256 !== cert256) { + const msg = + 'Certificate verification error: ' + + `The certificate of '${cert.subject.CN}' ` + + 'does not match our pinned fingerprint'; + return new Error(msg); + } + return undefined; + }, + }; + + // we're creating a new Agent that will now use the certs we have configured + return new https.Agent(sslOptions); +}; + export async function getSnodesFromSeedUrl(urlObj: URL): Promise> { const { log } = window; @@ -103,11 +199,14 @@ export async function getSnodesFromSeedUrl(urlObj: URL): Promise> { method: 'get_n_service_nodes', params, }; + const sslAgent = getSslAgentForSeedNode(urlObj.hostname); const fetchOptions = { method: 'POST', timeout: 10000, body: JSON.stringify(body), + + agent: sslAgent, }; window.log.info('insecureNodeFetch => plaintext for getSnodesFromSeedUrl'); diff --git a/ts/session/snode_api/snodePool.ts b/ts/session/snode_api/snodePool.ts index 4bd6a21c3..d4bec192b 100644 --- a/ts/session/snode_api/snodePool.ts +++ b/ts/session/snode_api/snodePool.ts @@ -1,22 +1,18 @@ +import semver from 'semver'; +import _ from 'lodash'; + import { abortableIterator, allowOnlyOneAtATime, } from '../../../js/modules/loki_primitives'; -import { - getSnodesFromSeedUrl, - getVersion, - requestSnodesForPubkey, -} from './serviceNodeAPI'; +import { getSnodesFromSeedUrl, requestSnodesForPubkey } from './serviceNodeAPI'; import { getSwarmNodesForPubkey, updateSwarmNodesForPubkey, } from '../../../ts/data/data'; -import semver from 'semver'; -import _ from 'lodash'; - export type SnodeEdKey = string; const MIN_NODES = 3; @@ -60,6 +56,7 @@ async function tryGetSnodeListFromLokidSeednode( let snodes = []; try { const tryUrl = new URL(seedNode.url); + snodes = await getSnodesFromSeedUrl(tryUrl); // throw before clearing the lock, so the retries can kick in if (snodes.length === 0) { From a0698202df3ae90b735ee5978180408a4c4669ca Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 12 Apr 2021 16:46:20 +1000 Subject: [PATCH 2/7] redact snode IP used in logs on production builds --- js/modules/loki_public_chat_api.js | 10 +++++----- js/modules/privacy.js | 12 +++++++++++- ts/session/onions/index.ts | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/js/modules/loki_public_chat_api.js b/js/modules/loki_public_chat_api.js index 1e722b82e..27c61b4f3 100644 --- a/js/modules/loki_public_chat_api.js +++ b/js/modules/loki_public_chat_api.js @@ -154,11 +154,11 @@ class LokiPublicChatFactoryAPI extends EventEmitter { ); return null; } - if (window.isDev) { - log.info( - `loki_public_chat::findOrCreateServer - set token ${thisServer.token} for ${serverUrl}` - ); - } + // if (window.isDev) { + // log.info( + // `loki_public_chat::findOrCreateServer - set token ${thisServer.token} for ${serverUrl}` + // ); + // } this.servers.push(thisServer); } diff --git a/js/modules/privacy.js b/js/modules/privacy.js index 1720b7420..154535a9e 100644 --- a/js/modules/privacy.js +++ b/js/modules/privacy.js @@ -8,6 +8,7 @@ const { escapeRegExp } = require('lodash'); const APP_ROOT_PATH = path.join(__dirname, '..', '..', '..'); const SESSION_ID_PATTERN = /\b(05[0-9a-f]{64})\b/gi; +const SNODE_PATTERN = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; const GROUP_ID_PATTERN = /(group\()([^)]+)(\))/g; const REDACTION_PLACEHOLDER = '[REDACTED]'; @@ -64,6 +65,14 @@ exports.redactSessionID = text => { return text.replace(SESSION_ID_PATTERN, REDACTION_PLACEHOLDER); }; +exports.redactSnodeIP = text => { + if (!is.string(text)) { + throw new TypeError("'text' must be a string"); + } + + return text.replace(SNODE_PATTERN, REDACTION_PLACEHOLDER); +}; + // redactGroupIds :: String -> String exports.redactGroupIds = text => { if (!is.string(text)) { @@ -84,7 +93,8 @@ exports.redactSensitivePaths = exports._redactPath(APP_ROOT_PATH); exports.redactAll = compose( exports.redactSensitivePaths, exports.redactGroupIds, - exports.redactSessionID + exports.redactSessionID, + exports.redactSnodeIP ); const removeNewlines = text => text.replace(/\r?\n|\r/g, ''); diff --git a/ts/session/onions/index.ts b/ts/session/onions/index.ts index 396c8c4eb..b32aa1612 100644 --- a/ts/session/onions/index.ts +++ b/ts/session/onions/index.ts @@ -312,6 +312,6 @@ export class OnionPaths { this.onionPaths.push({ path, bad: false }); } - log.info(`Built ${this.onionPaths.length} onion paths`, this.onionPaths); + log.info(`Built ${this.onionPaths.length} onion paths`); } } From b31c397b368a0c3cd8b32f36bcc6ea13c7274e7c Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 13 Apr 2021 10:21:29 +1000 Subject: [PATCH 3/7] bump to v1.5.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ae7a033e..cf335e7f1 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.5.2", + "version": "1.5.3", "license": "GPL-3.0", "author": { "name": "Loki Project", From 2393dce44844a35444c1eb8c0c58f65b1a8fd4c3 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 13 Apr 2021 10:27:33 +1000 Subject: [PATCH 4/7] fix tslint --- ts/components/UserDetailsDialog.tsx | 2 +- ts/session/utils/JobQueue.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/components/UserDetailsDialog.tsx b/ts/components/UserDetailsDialog.tsx index 70e4e0301..70276c53d 100644 --- a/ts/components/UserDetailsDialog.tsx +++ b/ts/components/UserDetailsDialog.tsx @@ -64,7 +64,7 @@ export class UserDetailsDialog extends React.Component { private renderAvatar() { const { avatarPath, pubkey, profileName } = this.props; const size = this.state.isEnlargedImageShown ? 300 : 80; - const userName = name || profileName || pubkey; + const userName = profileName || pubkey; return ( = (() => PromiseLike) | (() => ResultType); // TODO: This needs to replace js/modules/job_queue.js export class JobQueue { - private pending: Promise = Promise.resolve(); + private pending?: Promise = Promise.resolve(); private readonly jobs: Map> = new Map(); public has(id: string): boolean { From 64b4dbe5686cdf57d2470e4707166347121348b6 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 13 Apr 2021 10:54:42 +1000 Subject: [PATCH 5/7] hide https urls from saved logs --- js/modules/privacy.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/js/modules/privacy.js b/js/modules/privacy.js index 154535a9e..051cd2583 100644 --- a/js/modules/privacy.js +++ b/js/modules/privacy.js @@ -7,9 +7,10 @@ const { compose } = require('lodash/fp'); const { escapeRegExp } = require('lodash'); const APP_ROOT_PATH = path.join(__dirname, '..', '..', '..'); -const SESSION_ID_PATTERN = /\b(05[0-9a-f]{64})\b/gi; -const SNODE_PATTERN = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; +const SESSION_ID_PATTERN = /\b((05)?[0-9a-f]{64})\b/gi; +const SNODE_PATTERN = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/; const GROUP_ID_PATTERN = /(group\()([^)]+)(\))/g; +const SERVER_URL_PATTERN = /https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; const REDACTION_PLACEHOLDER = '[REDACTED]'; // _redactPath :: Path -> String -> String @@ -73,6 +74,14 @@ exports.redactSnodeIP = text => { return text.replace(SNODE_PATTERN, REDACTION_PLACEHOLDER); }; +exports.redactServerUrl = text => { + if (!is.string(text)) { + throw new TypeError("'text' must be a string"); + } + + return text.replace(SERVER_URL_PATTERN, REDACTION_PLACEHOLDER); +}; + // redactGroupIds :: String -> String exports.redactGroupIds = text => { if (!is.string(text)) { @@ -94,7 +103,8 @@ exports.redactAll = compose( exports.redactSensitivePaths, exports.redactGroupIds, exports.redactSessionID, - exports.redactSnodeIP + exports.redactSnodeIP, + exports.redactServerUrl ); const removeNewlines = text => text.replace(/\r?\n|\r/g, ''); From a9f36f970514739cc2ad61db0573e8a60237f22a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 13 Apr 2021 11:24:35 +1000 Subject: [PATCH 6/7] add test for other redactAll of logs --- test/modules/privacy_test.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/modules/privacy_test.js b/test/modules/privacy_test.js index e51959f6a..2596351b1 100644 --- a/test/modules/privacy_test.js +++ b/test/modules/privacy_test.js @@ -63,20 +63,28 @@ describe('Privacy', () => { 'This is a log line with sensitive information:\n' + `path1 ${APP_ROOT_PATH}/main.js\n` + 'phone1 0531032fc7415b7cc1b7516480ad121d391eddce3cfb2cee27dd5b215609c32827 ipsum\n' + + 'group 31032fc7415b7cc1b7516480ad121d391eddce3cfb2cee27dd5b215609c32827 eeee\n' + 'group1 group(123456789) doloret\n' + `path2 file:///${encodedAppRootPath}/js/background.js.` + 'phone2 0531033dc7415b7cc1b7516480ad121d391eddce3cfb2cee27dd5b215609c32827 lorem\n' + - 'group2 group(abcdefghij) doloret\n'; + 'group2 group(abcdefghij) doloret\n' + + 'url1 https://you-have-to-hide.me aaa\n' + + 'url1 http://you-have-to-hide.me bbb\n' + + 'url1 127.0.0.1:22021 ccc\n'; const actual = Privacy.redactAll(text); const expected = 'This is a log line with sensitive information:\n' + 'path1 [REDACTED]/main.js\n' + 'phone1 [REDACTED] ipsum\n' + + 'group [REDACTED] eeee\n' + 'group1 group([REDACTED]789) doloret\n' + 'path2 file:///[REDACTED]/js/background.js.' + 'phone2 [REDACTED] lorem\n' + - 'group2 group([REDACTED]hij) doloret\n'; + 'group2 group([REDACTED]hij) doloret\n' + + 'url1 [REDACTED] aaa\n' + + 'url1 [REDACTED] bbb\n' + + 'url1 [REDACTED]:22021 ccc\n'; assert.equal(actual, expected); }); }); From 5bd402218cc36d75f19074558e77c66cc9885136 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 13 Apr 2021 13:11:58 +1000 Subject: [PATCH 7/7] fix lint --- js/modules/privacy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/modules/privacy.js b/js/modules/privacy.js index 051cd2583..de218bbe8 100644 --- a/js/modules/privacy.js +++ b/js/modules/privacy.js @@ -10,7 +10,7 @@ const APP_ROOT_PATH = path.join(__dirname, '..', '..', '..'); const SESSION_ID_PATTERN = /\b((05)?[0-9a-f]{64})\b/gi; const SNODE_PATTERN = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/; const GROUP_ID_PATTERN = /(group\()([^)]+)(\))/g; -const SERVER_URL_PATTERN = /https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; +const SERVER_URL_PATTERN = /https?:\/\/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g; const REDACTION_PLACEHOLDER = '[REDACTED]'; // _redactPath :: Path -> String -> String