diff --git a/src/git.ts b/src/git.ts index d08833842..a8dd2fc7a 100644 --- a/src/git.ts +++ b/src/git.ts @@ -25,7 +25,7 @@ import { BASEURL } from './constants' import { GitPullError, HttpError, ValidationError } from './error' import { Core } from './otomi-models' import { FileMap, getFilePath, getResourceName, renderManifest, renderManifestForSecrets } from './repo' -import { getSanitizedErrorMessage, removeBlankAttributes } from './utils' +import { getSanitizedErrorMessage, removeBlankAttributes, sanitizeGitPassword } from './utils' const debug = Debug('otomi:repo') @@ -473,7 +473,8 @@ export class Git { } } catch (e) { const sanitizedMessage = getSanitizedErrorMessage(e) - debug(`${sanitizedMessage} for command ${JSON.stringify(e.task?.commands).replace(env.GIT_PASSWORD, '****')}`) + const sanitizedCommands = sanitizeGitPassword(JSON.stringify(e.task?.commands)) + debug(`${sanitizedMessage} for command ${sanitizedCommands}`) debug('Git save error') throw new GitPullError() } diff --git a/src/utils.test.ts b/src/utils.test.ts index 7faf7f033..fe95d9f10 100644 --- a/src/utils.test.ts +++ b/src/utils.test.ts @@ -1,5 +1,6 @@ import { Cluster } from 'src/otomi-models' -import { getServiceUrl } from 'src/utils' +import { getSanitizedErrorMessage, getServiceUrl, sanitizeGitPassword } from 'src/utils' +import { cleanEnv, GIT_PASSWORD } from './validators' describe('Utils', () => { const cluster: Cluster = { @@ -57,4 +58,28 @@ describe('Utils', () => { expect(service.subdomain).toEqual('aa') expect(service.domain).toEqual('bb.cc.dd.ee') }) + + describe('sanitizeGitPassword should remove git credentials', () => { + const env = cleanEnv({ + GIT_PASSWORD, + }) + test('from strings', () => { + expect(sanitizeGitPassword('test string')).toBe('test string') + expect(sanitizeGitPassword(`${env.GIT_PASSWORD} test string ${env.GIT_PASSWORD}`)).toBe('**** test string ****') + }) + test('from objects', () => { + expect(sanitizeGitPassword(JSON.stringify({ test: 'some string' }))).toEqual('{"test":"some string"}') + expect(sanitizeGitPassword(JSON.stringify({ test: `some string ${env.GIT_PASSWORD}` }))).toEqual( + '{"test":"some string ****"}', + ) + }) + test('return empty string on empty or undefined input', () => { + expect(sanitizeGitPassword('')).toEqual('') + expect(sanitizeGitPassword(undefined)).toEqual('') + }) + test('extract message from exception', () => { + expect(getSanitizedErrorMessage(new Error('test error'))).toEqual('test error') + expect(getSanitizedErrorMessage(new Error(`test error ${env.GIT_PASSWORD}`))).toEqual('test error ****') + }) + }) }) diff --git a/src/utils.ts b/src/utils.ts index 4d1853e54..0113108aa 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -201,7 +201,14 @@ export const objectToYaml = (obj: Record, indent = 4, lineWidth = 2 return isEmpty(obj) ? '' : stringify(obj, { indent, lineWidth }) } +export function sanitizeGitPassword(str?: string) { + return str ? str.replaceAll(env.GIT_PASSWORD, '****') : '' +} + export function getSanitizedErrorMessage(error) { - const errorMessage = typeof error?.message === 'string' ? error.message.replace(env.GIT_PASSWORD, '****') : '' - return errorMessage + const message = error?.message + if (!message) { + return '' + } + return typeof message === 'string' ? sanitizeGitPassword(message) : `[unprocessable message type ${typeof message}]` }