From 747a7c81c20ba5dea44ea82ac46219eee2c0cb85 Mon Sep 17 00:00:00 2001 From: sharevb Date: Tue, 25 Jun 2024 09:00:27 +0200 Subject: [PATCH 1/6] feat(new tool): Sensitive data masker Fix #765 --- components.d.ts | 8 +--- package.json | 1 + pnpm-lock.yaml | 44 +++++++++++++++---- src/tools/index.ts | 2 + src/tools/sensitive-data-masker/index.ts | 12 +++++ .../sensitive-data-masker.vue | 29 ++++++++++++ 6 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 src/tools/sensitive-data-masker/index.ts create mode 100644 src/tools/sensitive-data-masker/sensitive-data-masker.vue diff --git a/components.d.ts b/components.d.ts index f2c3146f..18d55a57 100644 --- a/components.d.ts +++ b/components.d.ts @@ -130,21 +130,14 @@ declare module '@vue/runtime-core' { NCode: typeof import('naive-ui')['NCode'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] - NDivider: typeof import('naive-ui')['NDivider'] NEllipsis: typeof import('naive-ui')['NEllipsis'] - NFormItem: typeof import('naive-ui')['NFormItem'] - NGi: typeof import('naive-ui')['NGi'] - NGrid: typeof import('naive-ui')['NGrid'] NH1: typeof import('naive-ui')['NH1'] NH3: typeof import('naive-ui')['NH3'] NIcon: typeof import('naive-ui')['NIcon'] - NInputNumber: typeof import('naive-ui')['NInputNumber'] - NLabel: typeof import('naive-ui')['NLabel'] NLayout: typeof import('naive-ui')['NLayout'] NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NMenu: typeof import('naive-ui')['NMenu'] NScrollbar: typeof import('naive-ui')['NScrollbar'] - NSpin: typeof import('naive-ui')['NSpin'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] @@ -160,6 +153,7 @@ declare module '@vue/runtime-core' { RouterView: typeof import('vue-router')['RouterView'] RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default'] SafelinkDecoder: typeof import('./src/tools/safelink-decoder/safelink-decoder.vue')['default'] + SensitiveDataMasker: typeof import('./src/tools/sensitive-data-masker/sensitive-data-masker.vue')['default'] SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default'] SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default'] SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default'] diff --git a/package.json b/package.json index c6cb7757..95db4279 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "libphonenumber-js": "^1.10.28", "lodash": "^4.17.21", "marked": "^10.0.0", + "mask-sensitive-data": "^0.11.5", "mathjs": "^11.9.1", "mime-types": "^2.1.35", "monaco-editor": "^0.43.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8619d8c0..e1413fad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -110,6 +110,9 @@ dependencies: marked: specifier: ^10.0.0 version: 10.0.0 + mask-sensitive-data: + specifier: ^0.11.5 + version: 0.11.5 mathjs: specifier: ^11.9.1 version: 11.9.1 @@ -3354,7 +3357,7 @@ packages: dependencies: '@unhead/dom': 0.5.1 '@unhead/schema': 0.5.1 - '@vueuse/shared': 10.8.0(vue@3.3.4) + '@vueuse/shared': 10.11.0(vue@3.3.4) unhead: 0.5.1 vue: 3.3.4 transitivePeerDependencies: @@ -3987,19 +3990,19 @@ packages: - vue dev: false - /@vueuse/shared@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} + /@vueuse/shared@10.11.0(vue@3.3.4): + resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==} dependencies: - vue-demi: 0.14.5(vue@3.3.4) + vue-demi: 0.14.8(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue dev: false - /@vueuse/shared@10.8.0(vue@3.3.4): - resolution: {integrity: sha512-dUdy6zwHhULGxmr9YUg8e+EnB39gcM4Fe2oKBSrh3cOsV30JcMPtsyuspgFCUo5xxFNaeMf/W2yyKfST7Bg8oQ==} + /@vueuse/shared@10.3.0(vue@3.3.4): + resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} dependencies: - vue-demi: 0.14.7(vue@3.3.4) + vue-demi: 0.14.5(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -6799,6 +6802,10 @@ packages: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: false + /map-or-similar@1.5.0: + resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} + dev: false + /map-stream@0.1.0: resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} dev: true @@ -6819,6 +6826,12 @@ packages: hasBin: true dev: false + /mask-sensitive-data@0.11.5: + resolution: {integrity: sha512-NBl/OC0kkKQaF5uo7dNnnNihidZM0TBCpxnKAHzTTmBnFPaWX9sZ2DHXOpnWRdrltgeTryTnrQ8pOutKIhkMgw==} + dependencies: + telejson: 7.2.0 + dev: false + /mathjs@11.9.1: resolution: {integrity: sha512-VdB9ELZ6Dwda13j5d1eCBETmPO8m9qIJETUdfZmTA9cPnXUiIk7UuoAmvxFqtfAe32XYuRugAec2Ndv0/RfRhg==} engines: {node: '>= 14'} @@ -6861,6 +6874,12 @@ packages: /mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + /memoizerific@1.11.3: + resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} + dependencies: + map-or-similar: 1.5.0 + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -8373,6 +8392,12 @@ packages: tslib: 2.5.0 dev: true + /telejson@7.2.0: + resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} + dependencies: + memoizerific: 1.11.3 + dev: false + /temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} @@ -9158,8 +9183,8 @@ packages: vue: 3.3.4 dev: false - /vue-demi@0.14.7(vue@3.3.4): - resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} + /vue-demi@0.14.8(vue@3.3.4): + resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==} engines: {node: '>=12'} hasBin: true requiresBuild: true @@ -9449,6 +9474,7 @@ packages: /workbox-google-analytics@7.0.0: resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained dependencies: workbox-background-sync: 7.0.0 workbox-core: 7.0.0 diff --git a/src/tools/index.ts b/src/tools/index.ts index aa861c93..2f0aafea 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer'; import { tool as textToUnicode } from './text-to-unicode'; import { tool as safelinkDecoder } from './safelink-decoder'; +import { tool as sensitiveDataMasker } from './sensitive-data-masker'; import { tool as pdfSignatureChecker } from './pdf-signature-checker'; import { tool as numeronymGenerator } from './numeronym-generator'; import { tool as macAddressGenerator } from './mac-address-generator'; @@ -172,6 +173,7 @@ export const toolsByCategory: ToolCategory[] = [ textDiff, numeronymGenerator, asciiTextDrawer, + sensitiveDataMasker, ], }, { diff --git a/src/tools/sensitive-data-masker/index.ts b/src/tools/sensitive-data-masker/index.ts new file mode 100644 index 00000000..ccafe88f --- /dev/null +++ b/src/tools/sensitive-data-masker/index.ts @@ -0,0 +1,12 @@ +import { ShieldLock } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Sensitive data masker', + path: '/sensitive-data-masker', + description: 'Clean sensitive data from textual content (ie logs)', + keywords: ['sensitive', 'data', 'masker', 'obfuscator', 'clean', 'log'], + component: () => import('./sensitive-data-masker.vue'), + icon: ShieldLock, + createdAt: new Date('2024-06-16'), +}); diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.vue b/src/tools/sensitive-data-masker/sensitive-data-masker.vue new file mode 100644 index 00000000..1cba1ad0 --- /dev/null +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.vue @@ -0,0 +1,29 @@ + + + From e6e51cf1c46f629e59203e0885777dc04fb8f872 Mon Sep 17 00:00:00 2001 From: ShareVB Date: Sun, 9 Jun 2024 12:32:10 +0200 Subject: [PATCH 2/6] chore: fix strange corepack message Fix corepack claiming strange thing : UsageError: This project is configured to use yarn because /home/runner/work/it-tools/it-tools/package.json has a "packageManager" field --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 95db4279..2c938849 100644 --- a/package.json +++ b/package.json @@ -139,5 +139,6 @@ "vitest": "^0.34.0", "workbox-window": "^7.0.0", "zx": "^7.2.1" - } + }, + "packageManager": "pnpm@8.15.3" } From 933d824083dac4bfadb02e68d4076133cd2866d7 Mon Sep 17 00:00:00 2001 From: ShareVB Date: Sun, 7 Jul 2024 22:59:31 +0200 Subject: [PATCH 3/6] feat: enhance cleaned PII and custom regexes --- package.json | 2 +- pnpm-lock.yaml | 33 +++-------- .../sensitive-data-masker.service.test.ts | 56 +++++++++++++++++++ .../sensitive-data-masker.service.ts | 22 ++++++++ .../sensitive-data-masker.vue | 45 ++++++++++----- 5 files changed, 119 insertions(+), 39 deletions(-) create mode 100644 src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts create mode 100644 src/tools/sensitive-data-masker/sensitive-data-masker.service.ts diff --git a/package.json b/package.json index 2c938849..2dcaa749 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "cron-validator": "^1.3.1", "cronstrue": "^2.26.0", "crypto-js": "^4.1.1", + "data-guardian": "^1.1.3", "date-fns": "^2.29.3", "dompurify": "^3.0.6", "emojilib": "^3.0.10", @@ -70,7 +71,6 @@ "libphonenumber-js": "^1.10.28", "lodash": "^4.17.21", "marked": "^10.0.0", - "mask-sensitive-data": "^0.11.5", "mathjs": "^11.9.1", "mime-types": "^2.1.35", "monaco-editor": "^0.43.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1413fad..41699bc3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,9 @@ dependencies: crypto-js: specifier: ^4.1.1 version: 4.1.1 + data-guardian: + specifier: ^1.1.3 + version: 1.1.3 date-fns: specifier: ^2.29.3 version: 2.29.3 @@ -110,9 +113,6 @@ dependencies: marked: specifier: ^10.0.0 version: 10.0.0 - mask-sensitive-data: - specifier: ^0.11.5 - version: 0.11.5 mathjs: specifier: ^11.9.1 version: 11.9.1 @@ -4722,6 +4722,11 @@ packages: resolution: {integrity: sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==} dev: false + /data-guardian@1.1.3: + resolution: {integrity: sha512-8M9KHTopFp3MXo7NelcmF+8L77S5jeDy3Uv4RWuYIQSaBZTawvY6W3ad/eLe8db2FcLPoC44DHJb4zWNcpoueQ==} + engines: {node: '>=12'} + dev: false + /data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} @@ -6802,10 +6807,6 @@ packages: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: false - /map-or-similar@1.5.0: - resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} - dev: false - /map-stream@0.1.0: resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} dev: true @@ -6826,12 +6827,6 @@ packages: hasBin: true dev: false - /mask-sensitive-data@0.11.5: - resolution: {integrity: sha512-NBl/OC0kkKQaF5uo7dNnnNihidZM0TBCpxnKAHzTTmBnFPaWX9sZ2DHXOpnWRdrltgeTryTnrQ8pOutKIhkMgw==} - dependencies: - telejson: 7.2.0 - dev: false - /mathjs@11.9.1: resolution: {integrity: sha512-VdB9ELZ6Dwda13j5d1eCBETmPO8m9qIJETUdfZmTA9cPnXUiIk7UuoAmvxFqtfAe32XYuRugAec2Ndv0/RfRhg==} engines: {node: '>= 14'} @@ -6874,12 +6869,6 @@ packages: /mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} - /memoizerific@1.11.3: - resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} - dependencies: - map-or-similar: 1.5.0 - dev: false - /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -8392,12 +8381,6 @@ packages: tslib: 2.5.0 dev: true - /telejson@7.2.0: - resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} - dependencies: - memoizerific: 1.11.3 - dev: false - /temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts b/src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts new file mode 100644 index 00000000..e9143f4f --- /dev/null +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, it } from 'vitest'; +import { maskSensitiveData } from './sensitive-data-masker.service'; + +describe('sensitive-data-masker', () => { + describe('maskSensitiveData', () => { + const data = `{ + email: 'john.doe@example.com', + creditCard: '1234 5678 9000 9876', + id: '3f8a43fd-6489-4ec7-bd55-7a1ba172d77b', + name: 'John', + surname: 'Doe', + phone: '+358 40 1234567', + url: 'truc.google.com', + ip4: '83.24.45.56', + ip6: '2001:db8:0:85a3:0:0:ac1f:8001', + mac: '3D:F2:C9:A6:B3:4F', + token: 'eyJhbGciOiJIUzI1NiJ9.ew0KICAic3ViIjogIjEyMzQ1Njc4OTAiLA0KICAibmFtZSI6ICJBbGV4IEtvemxvdiIsDQogICJpYXQiOiAxNTE2MjM5MDIyDQp9.PNKysYFTCenU5bekHCmwIxCUXoYG41H_xc3uN3ZF_b8', +}`; + + it('should maks sensitive data', () => { + expect(maskSensitiveData( + data, + )).toBe(`{ + email: 'jo****************om', + creditCard: '12***************76', + id: '3f********************************7b', + name: 'John', + surname: 'Doe', + phone: '+35**********67', + url: 'tr***********om', + ip4: '83*******56', + ip6: '20*************************01', + mac: '3D*************4F', + token: 'ey*****************************************************************************************************************************************************************b8', +}`); + }); + it('should maks sensitive data (with custom regex)', () => { + expect(maskSensitiveData( + data, + 'John\nDoe', + )).toBe(`{ + email: 'jo****************om', + creditCard: '12***************76', + id: '3f********************************7b', + name: '****', + surname: '***', + phone: '+35**********67', + url: 'tr***********om', + ip4: '83*******56', + ip6: '20*************************01', + mac: '3D*************4F', + token: 'ey*****************************************************************************************************************************************************************b8', +}`); + }); + }); +}); diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts b/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts new file mode 100644 index 00000000..93a85621 --- /dev/null +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts @@ -0,0 +1,22 @@ +import { maskString } from 'data-guardian'; + +const jwtRegex = /\b([a-zA-Z0-9_=]+)\.([a-zA-Z0-9_=]+)\.([a-zA-Z0-9_\-\+\/=]*)\b/g; +const phoneRegex = /\b(?:(\+\d{1,4})[-.\s]?)?(?:[(](\d{1,3})[)][-.\s]?)?(\d{1,4})[-.\s]?(\d{1,4})[-.\s]?(\d{1,9})\b/g; +const macRegex = /\b([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})\b/g; +const ipv6Regex = /\b(?:(::|[0-9a-fA-F]{1,4}:{1,2})([0-9a-fA-F]{1,4}:{1,2}){0,6}([0-9a-fA-F]{1,4}|::)?)\b/g; +const urlWithOrWithoutPrefixRegex = /\b(https?:\/\/)?(www\\.)?[-a-zA-Z0-9@:%.\_\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%\_\\+.~#?&//=]\*)\b/g; + +export function maskSensitiveData(value: string, customRegex?: string) { + return maskString(value, null as never, { + customRegex: new RegExp((customRegex || '').split('\n').map(line => `(${line})`).join('|'), 'gi'), + macRegex, + ipv6Regex, + urlWithOrWithoutPrefixRegex, + jwtRegex, + phoneRegex, + }, { + excludeMatchers: [ + 'passwordMention', 'password', 'passwordSubstring', + ], + }); +} diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.vue b/src/tools/sensitive-data-masker/sensitive-data-masker.vue index 1cba1ad0..6636fe86 100644 --- a/src/tools/sensitive-data-masker/sensitive-data-masker.vue +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.vue @@ -1,29 +1,48 @@ From 80d87cb290c4af68f9a7ac3d8bba20e1ec0689d7 Mon Sep 17 00:00:00 2001 From: ShareVB Date: Fri, 12 Jul 2024 23:13:20 +0200 Subject: [PATCH 4/6] feat: disable some built-in regex --- .../sensitive-data-masker.service.test.ts | 37 ++++++++++++++----- .../sensitive-data-masker.service.ts | 36 ++++++++++++------ .../sensitive-data-masker.vue | 24 ++++++++++-- 3 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts b/src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts index e9143f4f..49c61137 100644 --- a/src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.service.test.ts @@ -18,15 +18,15 @@ describe('sensitive-data-masker', () => { }`; it('should maks sensitive data', () => { - expect(maskSensitiveData( - data, - )).toBe(`{ + expect(maskSensitiveData({ + value: data, + })).toBe(`{ email: 'jo****************om', creditCard: '12***************76', id: '3f********************************7b', name: 'John', surname: 'Doe', - phone: '+35**********67', + phone: '+3***********67', url: 'tr***********om', ip4: '83*******56', ip6: '20*************************01', @@ -35,21 +35,40 @@ describe('sensitive-data-masker', () => { }`); }); it('should maks sensitive data (with custom regex)', () => { - expect(maskSensitiveData( - data, - 'John\nDoe', - )).toBe(`{ + expect(maskSensitiveData({ + value: data, + customRegex: 'John\nDoe', + })).toBe(`{ email: 'jo****************om', creditCard: '12***************76', id: '3f********************************7b', name: '****', surname: '***', - phone: '+35**********67', + phone: '+3***********67', url: 'tr***********om', ip4: '83*******56', ip6: '20*************************01', mac: '3D*************4F', token: 'ey*****************************************************************************************************************************************************************b8', +}`); + }); + + it('should maks sensitive data (with excluded matchers)', () => { + expect(maskSensitiveData({ + value: data, + excludedMatchers: ['mac', 'ipv4'], + })).toBe(`{ + email: 'jo****************om', + creditCard: '12***************76', + id: '3f********************************7b', + name: 'John', + surname: 'Doe', + phone: '+3***********67', + url: 'tr***********om', + ip4: '83.24.45.56', + ip6: '20*************************01', + mac: '3D:F2:C9:A6:B3:4F', + token: 'ey*****************************************************************************************************************************************************************b8', }`); }); }); diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts b/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts index 93a85621..07090d2b 100644 --- a/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts @@ -1,22 +1,34 @@ import { maskString } from 'data-guardian'; +import ipRegex from 'ip-regex'; -const jwtRegex = /\b([a-zA-Z0-9_=]+)\.([a-zA-Z0-9_=]+)\.([a-zA-Z0-9_\-\+\/=]*)\b/g; -const phoneRegex = /\b(?:(\+\d{1,4})[-.\s]?)?(?:[(](\d{1,3})[)][-.\s]?)?(\d{1,4})[-.\s]?(\d{1,4})[-.\s]?(\d{1,9})\b/g; +const jwtRegex = /\b([a-zA-Z0-9_=]{5,})\.([a-zA-Z0-9_=]{5,})\.([a-zA-Z0-9_\-\+\/=]{5,})\b/g; +const phoneRegex = /(?:(\+\d{1,4})[-.\s]?)(?:[(](\d{1,3})[)][-.\s]?)?(\d{1,4})[-.\s]?(\d{1,4})[-.\s]?(\d{1,9})\b/g; const macRegex = /\b([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})\b/g; -const ipv6Regex = /\b(?:(::|[0-9a-fA-F]{1,4}:{1,2})([0-9a-fA-F]{1,4}:{1,2}){0,6}([0-9a-fA-F]{1,4}|::)?)\b/g; -const urlWithOrWithoutPrefixRegex = /\b(https?:\/\/)?(www\\.)?[-a-zA-Z0-9@:%.\_\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%\_\\+.~#?&//=]\*)\b/g; +const urlWithOrWithoutPrefixRegex = /\b(https?:\/\/)?(www\.)?[a-zA-Z0-9@:%._+~#=-]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&\/=]*)\b/g; -export function maskSensitiveData(value: string, customRegex?: string) { +export type MatcherNames = 'uuid' | 'creditCard' | 'ssn' | 'url' | 'ipv4' | 'email' | 'passwordInUri' | 'mac' | 'ipv6' | 'urlWithOrWithoutPrefix' | 'jwt' | 'phone'; + +export function maskSensitiveData({ + value, + customRegex = '', + excludedMatchers = [], +}: { + value: string + customRegex?: string + excludedMatchers?: Array +}) { + excludedMatchers = excludedMatchers || []; + const emptyRegex = /(?:)/g; return maskString(value, null as never, { customRegex: new RegExp((customRegex || '').split('\n').map(line => `(${line})`).join('|'), 'gi'), - macRegex, - ipv6Regex, - urlWithOrWithoutPrefixRegex, - jwtRegex, - phoneRegex, + macRegex: excludedMatchers.includes('mac') ? emptyRegex : macRegex, + ipv6Regex: excludedMatchers.includes('ipv6') ? emptyRegex : ipRegex.v6({ includeBoundaries: false }), + urlWithOrWithoutPrefixRegex: excludedMatchers.includes('urlWithOrWithoutPrefix') ? emptyRegex : urlWithOrWithoutPrefixRegex, + jwtRegex: excludedMatchers.includes('jwt') ? emptyRegex : jwtRegex, + phoneRegex: excludedMatchers.includes('phone') ? emptyRegex : phoneRegex, }, { - excludeMatchers: [ + excludeMatchers: [...excludedMatchers, ...[ 'passwordMention', 'password', 'passwordSubstring', - ], + ]], }); } diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.vue b/src/tools/sensitive-data-masker/sensitive-data-masker.vue index 6636fe86..7c9d970e 100644 --- a/src/tools/sensitive-data-masker/sensitive-data-masker.vue +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.vue @@ -1,5 +1,5 @@ @@ -35,6 +41,16 @@ function transformer(value: string) { raw-text multiline rows="4" + mb-2 + /> + + Date: Fri, 12 Jul 2024 23:15:56 +0200 Subject: [PATCH 5/6] fix: deps --- package.json | 1 + pnpm-lock.yaml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/package.json b/package.json index 2dcaa749..fd132bae 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "highlight.js": "^11.7.0", "iarna-toml-esm": "^3.0.5", "ibantools": "^4.3.3", + "ip-regex": "^5.0.0", "js-base64": "^3.7.6", "json5": "^2.2.3", "jwt-decode": "^3.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41699bc3..3bbb4ac2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -95,6 +95,9 @@ dependencies: ibantools: specifier: ^4.3.3 version: 4.3.3 + ip-regex: + specifier: ^5.0.0 + version: 5.0.0 js-base64: specifier: ^3.7.6 version: 3.7.7 @@ -6196,6 +6199,11 @@ packages: jsbn: 1.1.0 dev: false + /ip-regex@5.0.0: + resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + /is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} dev: true From ec6c5b40664eea67f34ed9d32b970974c8d31d74 Mon Sep 17 00:00:00 2001 From: ShareVB Date: Fri, 12 Jul 2024 23:24:09 +0200 Subject: [PATCH 6/6] fix: lint --- .../sensitive-data-masker/sensitive-data-masker.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts b/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts index 07090d2b..28e6aa71 100644 --- a/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts +++ b/src/tools/sensitive-data-masker/sensitive-data-masker.service.ts @@ -1,4 +1,4 @@ -import { maskString } from 'data-guardian'; +import { type SensitiveContentKey, maskString } from 'data-guardian'; import ipRegex from 'ip-regex'; const jwtRegex = /\b([a-zA-Z0-9_=]{5,})\.([a-zA-Z0-9_=]{5,})\.([a-zA-Z0-9_\-\+\/=]{5,})\b/g; @@ -29,6 +29,6 @@ export function maskSensitiveData({ }, { excludeMatchers: [...excludedMatchers, ...[ 'passwordMention', 'password', 'passwordSubstring', - ]], + ]] as SensitiveContentKey[], }); }