diff --git a/apps/cli/src/commands/project/import.project.ts b/apps/cli/src/commands/project/import.project.ts index 8c271c56..78dead5b 100644 --- a/apps/cli/src/commands/project/import.project.ts +++ b/apps/cli/src/commands/project/import.project.ts @@ -48,10 +48,12 @@ export default class ImportFromEnv extends BaseCommand { const [projectSlug] = args try { - const { envFilePath } = await this.parseOptions(options) - if (!envFilePath) return - const envFileContent = await fs.readFile(envFilePath, 'utf-8') - // Logger.info('File contents:\n' + envFileContent) + const parsedOptions = await this.parseOptions(options) + if (!parsedOptions) return + const envFileContent = await fs.readFile( + parsedOptions.envFilePath, + 'utf-8' + ) const envVariables = dotenv.parse(envFileContent) if (Object.keys(envVariables).length === 0) { @@ -59,13 +61,14 @@ export default class ImportFromEnv extends BaseCommand { return } - const secretsAndVariables = secretDetector.detectJsObject(envVariables) + const secretsAndVariables = secretDetector.scanJsObject(envVariables) Logger.info( 'Detected secrets:\n' + Object.entries(secretsAndVariables.secrets) .map(([key, value]) => key + ' = ' + JSON.stringify(value)) - .join('\n') + .join('\n') + + '\n' ) Logger.info( 'Detected variables:\n' + @@ -160,12 +163,12 @@ export default class ImportFromEnv extends BaseCommand { } private async parseOptions(options: CommandActionData['options']): Promise<{ - envFilePath: string | undefined - }> { + envFilePath: string + } | null> { const { envFile } = options if (!envFile) { Logger.error('No .env file path provided.') - return { envFilePath: undefined } + return null } const resolvedPath = path.resolve(envFile) const exists = await fs @@ -174,9 +177,8 @@ export default class ImportFromEnv extends BaseCommand { .catch(() => false) if (!exists) { Logger.error(`The .env file does not exist at path: ${resolvedPath}`) - return { envFilePath: undefined } + return null } - return { envFilePath: resolvedPath } } } diff --git a/apps/cli/src/commands/scan.command.ts b/apps/cli/src/commands/scan.command.ts index dd437d62..32ce21e6 100644 --- a/apps/cli/src/commands/scan.command.ts +++ b/apps/cli/src/commands/scan.command.ts @@ -10,6 +10,44 @@ import path from 'path' import secretDetector from '@keyshade/secret-scan' import { Logger } from '@/util/logger' +const ignoredExtensions = [ + 'png', + 'jpg', + 'jpeg', + 'gif', + 'svg', + 'ico', + 'woff', + 'woff2', + 'ttf', + 'eot', + 'pdf', + 'mp4', + 'mp3', + 'wav', + 'avi', + 'mov', + 'webm', + 'zip', + 'tar', + 'gz', + '7z', + 'rar', + 'iso', + 'bin', + 'exe', + 'dll', + 'so', + 'a', + 'o', + 'dylib', + 'lib', + 'obj', + 'jar', + 'war', + 'ear' +] + export default class ScanCommand extends BaseCommand { getOptions(): CommandOption[] { return [ @@ -65,6 +103,8 @@ export default class ScanCommand extends BaseCommand { for (const file of allFiles) { const stats = statSync(file) if (stats.isFile()) { + // Skip the file if it has an ignored extension like images, videos, etc. + if (ignoredExtensions.includes(file.split('.').pop())) continue const content = readFileSync(file, 'utf8').split(/\r?\n/) // Skip the file if ignore comment is found in the first line diff --git a/packages/secret-scan/src/index.ts b/packages/secret-scan/src/index.ts index 643bd3b8..8f25056c 100644 --- a/packages/secret-scan/src/index.ts +++ b/packages/secret-scan/src/index.ts @@ -1,5 +1,5 @@ import denylist from '@/denylist' -import type { SecretResult, ScanJsObjectResult } from '@/types' +import type { SecretResult, JsObjectScanResult } from '@/types' export type SecretConfig = Record @@ -26,15 +26,15 @@ class SecretDetector { /** * Detects if a given js object contains any secret patterns. * @param input - The object to scan for secret patterns. - * @returns A `ScanJsObjectResult` object containing the secrets and variables found in the object. + * @returns A `JsObjectScanResult` object containing the secrets and variables found in the object. */ - detectJsObject(input: Record): ScanJsObjectResult { - const result: ScanJsObjectResult = { + scanJsObject(input: Record): JsObjectScanResult { + const result: JsObjectScanResult = { secrets: {}, variables: {} } for (const [key, value] of Object.entries(input)) { - const secretResult = this.detect(value) + const secretResult = this.detect(key + '=' + value) if (secretResult.found) { result.secrets[key] = value } else { diff --git a/packages/secret-scan/src/test/detect-js-object.test.ts b/packages/secret-scan/src/test/scan-js-object.test.ts similarity index 89% rename from packages/secret-scan/src/test/detect-js-object.test.ts rename to packages/secret-scan/src/test/scan-js-object.test.ts index 14d3a582..5d6b2d4d 100644 --- a/packages/secret-scan/src/test/detect-js-object.test.ts +++ b/packages/secret-scan/src/test/scan-js-object.test.ts @@ -11,7 +11,7 @@ describe('Dectect Secrets and Variables from Object', () => { GOOGLE_ANALYTICS: 'UA-123456789-1', API_PORT: '3000' } - const result = secretDetector.detectJsObject(input) + const result = secretDetector.scanJsObject(input) expect(result.secrets).toEqual({ GITHUB_KEY: input.GITHUB_KEY, AWS_KEY: input.AWS_KEY, @@ -26,7 +26,7 @@ describe('Dectect Secrets and Variables from Object', () => { it('should return empty objects for secrets and variables when input is empty', () => { const input = {} - const result = secretDetector.detectJsObject(input) + const result = secretDetector.scanJsObject(input) expect(result.secrets).toEqual({}) expect(result.variables).toEqual({}) }) @@ -37,7 +37,7 @@ describe('Dectect Secrets and Variables from Object', () => { GOOGLE_ANALYTICS: 'UA-123456789-1', API_PORT: '3000' } - const result = secretDetector.detectJsObject(input) + const result = secretDetector.scanJsObject(input) expect(result.secrets).toEqual({}) expect(result.variables).toEqual({ NEXT_PUBLIC_API_KEY: input.NEXT_PUBLIC_API_KEY, @@ -52,7 +52,7 @@ describe('Dectect Secrets and Variables from Object', () => { AWS_KEY: aws.testcases[0].input, OPENAI_KEY: openAI.testcases[0].input } - const result = secretDetector.detectJsObject(input) + const result = secretDetector.scanJsObject(input) expect(result.secrets).toEqual({ GITHUB_KEY: input.GITHUB_KEY, AWS_KEY: input.AWS_KEY, diff --git a/packages/secret-scan/src/types/index.d.ts b/packages/secret-scan/src/types/index.d.ts index e52efe32..4f806320 100644 --- a/packages/secret-scan/src/types/index.d.ts +++ b/packages/secret-scan/src/types/index.d.ts @@ -8,7 +8,7 @@ export interface SecretResult { regex?: RegExp } -export interface ScanJsObjectResult { +export interface JsObjectScanResult { secrets: Record variables: Record }