Merge pull request #4350 from Infisical/misc/added-entropy-check-for-params-secret-scanning

misc: added entropy check for params secret scanning
This commit is contained in:
Maidul Islam
2025-08-11 11:34:24 -07:00
committed by GitHub
2 changed files with 31 additions and 5 deletions
@@ -58,9 +58,9 @@ export function scanDirectory(inputPath: string, outputPath: string, configPath?
}); });
} }
export function scanFile(inputPath: string): Promise<void> { export function scanFile(inputPath: string, configPath?: string): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const command = `infisical scan --exit-code=77 --source "${inputPath}" --no-git`; const command = `infisical scan --exit-code=77 --source "${inputPath}" --no-git ${configPath ? `-c ${configPath}` : ""}`;
exec(command, (error) => { exec(command, (error) => {
if (error && error.code === 77) { if (error && error.code === 77) {
reject(error); reject(error);
@@ -166,6 +166,20 @@ export const parseScanErrorMessage = (err: unknown): string => {
: `${errorMessage.substring(0, MAX_MESSAGE_LENGTH - 3)}...`; : `${errorMessage.substring(0, MAX_MESSAGE_LENGTH - 3)}...`;
}; };
const generateSecretValuePolicyConfiguration = (entropy: number): string => `
# Extend default configuration to preserve existing rules
[extend]
useDefault = true
# Add custom high-entropy rule
[[rules]]
id = "high-entropy"
description = "Will scan for high entropy secrets"
regex = '''.*'''
entropy = ${entropy}
keywords = []
`;
export const scanSecretPolicyViolations = async ( export const scanSecretPolicyViolations = async (
projectId: string, projectId: string,
secretPath: string, secretPath: string,
@@ -188,14 +202,25 @@ export const scanSecretPolicyViolations = async (
const tempFolder = await createTempFolder(); const tempFolder = await createTempFolder();
try { try {
const configPath = join(tempFolder, "infisical-scan.toml");
const secretPolicyConfiguration = generateSecretValuePolicyConfiguration(
appCfg.PARAMS_FOLDER_SECRET_DETECTION_ENTROPY
);
await writeTextToFile(configPath, secretPolicyConfiguration);
const scanPromises = secrets const scanPromises = secrets
.filter((secret) => !ignoreValues.includes(secret.secretValue)) .filter((secret) => !ignoreValues.includes(secret.secretValue))
.map(async (secret) => { .map(async (secret) => {
const secretFilePath = join(tempFolder, `${crypto.nativeCrypto.randomUUID()}.txt`); const secretKeyValueFilePath = join(tempFolder, `${crypto.nativeCrypto.randomUUID()}.txt`);
await writeTextToFile(secretFilePath, `${secret.secretKey}=${secret.secretValue}`); const secretValueOnlyFilePath = join(tempFolder, `${crypto.nativeCrypto.randomUUID()}.txt`);
await writeTextToFile(secretKeyValueFilePath, `${secret.secretKey}=${secret.secretValue}`);
await writeTextToFile(secretValueOnlyFilePath, secret.secretValue);
try { try {
await scanFile(secretFilePath); await scanFile(secretKeyValueFilePath);
await scanFile(secretValueOnlyFilePath, configPath);
} catch (error) { } catch (error) {
throw new BadRequestError({ throw new BadRequestError({
message: `Secret value detected in ${secret.secretKey}. Please add this instead to the designated secrets path in the project.`, message: `Secret value detected in ${secret.secretKey}. Please add this instead to the designated secrets path in the project.`,
+1
View File
@@ -215,6 +215,7 @@ const envSchema = z
return JSON.parse(val) as { secretPath: string; projectId: string }[]; return JSON.parse(val) as { secretPath: string; projectId: string }[];
}) })
), ),
PARAMS_FOLDER_SECRET_DETECTION_ENTROPY: z.coerce.number().optional().default(4.5),
// HSM // HSM
HSM_LIB_PATH: zpStr(z.string().optional()), HSM_LIB_PATH: zpStr(z.string().optional()),