Skip to content

Commit

Permalink
feat: merge the gileaks secret feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Psingle20 committed Nov 27, 2024
2 parents 2fd5255 + 647eb28 commit e2702c9
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 1 deletion.
123 changes: 123 additions & 0 deletions gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
version = 1

# Rule for AWS Access Key
[[rules]]
id = "aws-access-key"
description = "AWS Access Key"
regex = '''AKIA[A-Z0-9]{16}'''
tags = ["aws", "access_key"]

# Rule for AWS Secret Key
[[rules]]
id = "aws-secret-key"
description = "AWS Secret Key"
regex = '''(?i)aws(.{0,20})?['\"][0-9a-zA-Z/+]{40}['\"]'''
tags = ["aws", "secret_key"]

# Rule for Google Cloud API Key
[[rules]]
id = "google-api-key"
description = "Google API Key"
regex = '''AIza[0-9A-Za-z\\-_]{35}'''
tags = ["google", "api_key"]

# Rule for Slack Token
[[rules]]
id = "slack-api-token"
description = "Slack API Token"
regex = '''xox[baprs]-[0-9]{12}-[0-9]{12}-[a-zA-Z0-9]{24}'''
tags = ["slack", "api_token"]

# Rule for GitHub Token
[[rules]]
id = "github-token"
description = "GitHub Personal Access Token"
regex = '''ghp_[0-9A-Za-z]{36}'''
tags = ["github", "token"]

# Rule for Basic Authentication in URL
[[rules]]
id = "basic-auth-url"
description = "Basic Authentication in URL"
regex = '''[a-zA-Z0-9]+:[a-zA-Z0-9]+@'''
tags = ["auth", "basic_auth", "url"]

# Rule for Private Key
[[rules]]
id = "private-key"
description = "Private Key"
regex = '''-----BEGIN (EC|RSA|DSA|OPENSSH|PGP|ENCRYPTED) PRIVATE KEY-----'''
tags = ["key", "private_key"]

# Rule for Database URL
[[rules]]
id = "database-url"
description = "Database Connection String"
regex = '''(mongodb|postgres|mysql|redis|mssql|oracle|sqlite)://[^\\s:@]+:[^\\s:@]+@[^\\s:@]+:[0-9]+/[^\\s:@]+'''
tags = ["database", "connection_string"]

# Rule for Generic API Key (alphanumeric 32+ chars)
[[rules]]
id = "generic-api-key"
description = "Generic API Key (alphanumeric, 32+ characters)"
regex = '''[A-Za-z0-9_]{32,}'''
tags = ["generic", "api_key"]

# Rule for Heroku API Key
[[rules]]
id = "heroku-api-key"
description = "Heroku API Key"
regex = '''(?i)heroku(.{0,20})?['\"][0-9a-fA-F]{32}['\"]'''
tags = ["heroku", "api_key"]

# Rule for Stripe API Key
[[rules]]
id = "stripe-api-key"
description = "Stripe API Key"
regex = '''sk_live_[0-9a-zA-Z]{24}'''
tags = ["stripe", "api_key"]

# Rule for Twilio API Key
[[rules]]
id = "twilio-api-key"
description = "Twilio API Key"
regex = '''AC[a-zA-Z0-9_\\-]{32}'''
tags = ["twilio", "api_key"]

# Rule for Mailgun API Key
[[rules]]
id = "mailgun-api-key"
description = "Mailgun API Key"
regex = '''key-[0-9a-zA-Z]{32}'''
tags = ["mailgun", "api_key"]

# Rule for Passwords (generic patterns like "password=")
[[rules]]
id = "generic-password"
description = "Potential Password Assignment"
regex = '''(?i)password\\s*=\\s*['"][^'"]+['"]'''
tags = ["password"]

# Rule for Salesforce OAuth Token
[[rules]]
id = "salesforce-oauth-token"
description = "Salesforce OAuth Token"
regex = '''00D[A-Za-z0-9]{15,18}'''
tags = ["salesforce", "oauth_token"]

# Rule for PayPal Braintree Access Token
[[rules]]
id = "braintree-access-token"
description = "PayPal Braintree Access Token"
regex = '''access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}'''
tags = ["braintree", "access_token"]

# Rule for SendGrid API Key
[[rules]]
id = "sendgrid-api-key"
description = "SendGrid API Key"
regex = '''SG\\.[0-9A-Za-z\\-_]{22}\\.[0-9A-Za-z\\-_]{43}'''
tags = ["sendgrid", "api_key"]


# additional rules can be added here
4 changes: 4 additions & 0 deletions proxy.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,12 @@


}
},
"checkForSecrets": {
"enabled": false
}


},
"attestationConfig": {
"questions": [
Expand Down
3 changes: 2 additions & 1 deletion src/proxy/processors/push-action/checkCommitMessages.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Step = require('../../actions').Step;
const config = require('../../../config');

const { exec: eexec } = require('./checkForSecrets');
console.log(eexec);
const commitConfig = config.getCommitConfig();

function isMessageAllowed(commitMessage) {
Expand Down
132 changes: 132 additions & 0 deletions src/proxy/processors/push-action/checkForSecrets
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
const { Step } = require('../../actions');
const { exec: cexec } = require('child_process');

const path = require('path');
const config = require('../../../config');
const commitConfig = config.getCommitConfig();

// Function to extract relevant file paths from Git diff content
// go to proxyconfig.json and enable the feature
// gitleaks.report.json will show the secrets found and in which file they are found
// Function to extract relevant file paths and their parent directories

// gitleaks dir "C:/Users/ingle/Desktop/CitiHackthon/git-proxy/test/test_data/sensitive_data.js" --config="c:/Users/ingle/Desktop/CitiHackthon/git-proxy/gitleaks.toml" --report-format json --log-level debug --report-path="c:/Users/ingle/Desktop/CitiHackthon/git-proxy/gitleaks_report.json"
// use the command to run gitleaks from terminal
// Function to extract relevant directories from Git diff content
function extractRelevantDirectories(diffContent) {
const relevantDirectories = [];
const relevantExtensions = ['.json', '.yaml', '.yml', '.js', '.ts', '.txt'];
const lines = diffContent.split('\n');

lines.forEach((line) => {
const match = line.match(/^diff --git a\/(.+?) b\/(.+?)$/);
if (match) {
const filePath = match[1];
const fileExtension = `.${filePath.split('.').pop()}`;

if (relevantExtensions.includes(fileExtension)) {
const dirPath = path.dirname(filePath);
if (!relevantDirectories.includes(dirPath)) {
relevantDirectories.push(dirPath);
}
}
}
});

return relevantDirectories;
}

// Function to run Gitleaks with directory paths
function runGitleaks(filePaths) {
return new Promise((resolve, reject) => {
const filesToCheck = filePaths
.map((filePath) => `"${path.resolve(filePath).replace(/\\/g, '/')}"`)
.join(' ');

const configPath = path.resolve(__dirname, '../../../../gitleaks.toml').replace(/\\/g, '/');
const reportPath = path
.resolve(__dirname, '../../../../gitleaks_report.json')
.replace(/\\/g, '/');

const command = `gitleaks dir ${filesToCheck} --config="${configPath}" --report-format json --log-level error --report-path="${reportPath}"`;
console.log(`Executing Gitleaks Command: ${command}`);

cexec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing gitleaks: ${error.message}`);
reject(new Error(`Error executing gitleaks: ${error.message}`));
} else if (stderr) {
console.error(`stderr: ${stderr}`);
reject(new Error(`stderr: ${stderr}`));
} else {
resolve(stdout);
}
});
});
}

// Function to check for sensitive secrets in the Gitleaks output
function checkForSensitiveSecrets(output) {
try {
const findings = JSON.parse(output);

if (findings.length > 0) {
findings.forEach((finding) => {
console.log(`Secret found in file: ${finding.file}`);
console.log(` Rule: ${finding.rule_id}`);
console.log(` Secret: ${finding.secret}`);
});
return true;
}
return false;
} catch (error) {
console.error('Error parsing Gitleaks output:', error);
return false;
}
}

// Example usage in exec function
const exec = async (req, action) => {
const diffStep = action.steps.find((s) => s.stepName === 'diff');
const step = new Step('checkforSecrets');
const commitinfo = commitConfig.checkForSecrets;

if (!commitinfo.enabled) {
action.addStep(step);
return action;
}

if (diffStep && diffStep.content) {
const dirPaths = extractRelevantDirectories(diffStep.content);

if (dirPaths.length > 0) {
try {
const result = await runGitleaks(dirPaths);
const hasSensitiveSecrets = checkForSensitiveSecrets(result);

if (hasSensitiveSecrets) {
step.blocked = true;
step.blockedMessage = 'Sensitive secrets detected in the diff.';
console.log('Sensitive secrets detected! Push blocked.');
} else {
console.log('No sensitive secrets detected.');
}
action.addStep(step);
} catch (err) {
console.error('Error during Gitleaks execution:', err);
}
} else {
console.log('No relevant directories found in the diff.');
}
} else {
console.log('No diff content available.');
}

return action;
};

exec.displayName = 'checkforSecrets.exec';




1 change: 1 addition & 0 deletions src/proxy/processors/push-action/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ exports.scanDiff = require('./scanDiff').exec;
exports.blockForAuth = require('./blockForAuth').exec;
exports.checkIfWaitingAuth = require('./checkIfWaitingAuth').exec;
exports.checkCommitMessages = require('./checkCommitMessages').exec;
console.log(__dirname);
exports.checkAuthorEmails = require('./checkAuthorEmails').exec;
exports.checkUserPushPermission = require('./checkUserPushPermission').exec;
exports.clearBareClone = require('./clearBareClone').exec;
Expand Down
3 changes: 3 additions & 0 deletions test/test_data/sensitive_data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// File containing sensitive AWS Access Key
const secret = 'AKIAIOSFODNN8EXAMPLE'; // Example AWS access key
console.log(secret);

0 comments on commit e2702c9

Please sign in to comment.