Skip to content

Commit e2702c9

Browse files
committed
feat: merge the gileaks secret feature
2 parents 2fd5255 + 647eb28 commit e2702c9

File tree

6 files changed

+265
-1
lines changed

6 files changed

+265
-1
lines changed

gitleaks.toml

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
version = 1
2+
3+
# Rule for AWS Access Key
4+
[[rules]]
5+
id = "aws-access-key"
6+
description = "AWS Access Key"
7+
regex = '''AKIA[A-Z0-9]{16}'''
8+
tags = ["aws", "access_key"]
9+
10+
# Rule for AWS Secret Key
11+
[[rules]]
12+
id = "aws-secret-key"
13+
description = "AWS Secret Key"
14+
regex = '''(?i)aws(.{0,20})?['\"][0-9a-zA-Z/+]{40}['\"]'''
15+
tags = ["aws", "secret_key"]
16+
17+
# Rule for Google Cloud API Key
18+
[[rules]]
19+
id = "google-api-key"
20+
description = "Google API Key"
21+
regex = '''AIza[0-9A-Za-z\\-_]{35}'''
22+
tags = ["google", "api_key"]
23+
24+
# Rule for Slack Token
25+
[[rules]]
26+
id = "slack-api-token"
27+
description = "Slack API Token"
28+
regex = '''xox[baprs]-[0-9]{12}-[0-9]{12}-[a-zA-Z0-9]{24}'''
29+
tags = ["slack", "api_token"]
30+
31+
# Rule for GitHub Token
32+
[[rules]]
33+
id = "github-token"
34+
description = "GitHub Personal Access Token"
35+
regex = '''ghp_[0-9A-Za-z]{36}'''
36+
tags = ["github", "token"]
37+
38+
# Rule for Basic Authentication in URL
39+
[[rules]]
40+
id = "basic-auth-url"
41+
description = "Basic Authentication in URL"
42+
regex = '''[a-zA-Z0-9]+:[a-zA-Z0-9]+@'''
43+
tags = ["auth", "basic_auth", "url"]
44+
45+
# Rule for Private Key
46+
[[rules]]
47+
id = "private-key"
48+
description = "Private Key"
49+
regex = '''-----BEGIN (EC|RSA|DSA|OPENSSH|PGP|ENCRYPTED) PRIVATE KEY-----'''
50+
tags = ["key", "private_key"]
51+
52+
# Rule for Database URL
53+
[[rules]]
54+
id = "database-url"
55+
description = "Database Connection String"
56+
regex = '''(mongodb|postgres|mysql|redis|mssql|oracle|sqlite)://[^\\s:@]+:[^\\s:@]+@[^\\s:@]+:[0-9]+/[^\\s:@]+'''
57+
tags = ["database", "connection_string"]
58+
59+
# Rule for Generic API Key (alphanumeric 32+ chars)
60+
[[rules]]
61+
id = "generic-api-key"
62+
description = "Generic API Key (alphanumeric, 32+ characters)"
63+
regex = '''[A-Za-z0-9_]{32,}'''
64+
tags = ["generic", "api_key"]
65+
66+
# Rule for Heroku API Key
67+
[[rules]]
68+
id = "heroku-api-key"
69+
description = "Heroku API Key"
70+
regex = '''(?i)heroku(.{0,20})?['\"][0-9a-fA-F]{32}['\"]'''
71+
tags = ["heroku", "api_key"]
72+
73+
# Rule for Stripe API Key
74+
[[rules]]
75+
id = "stripe-api-key"
76+
description = "Stripe API Key"
77+
regex = '''sk_live_[0-9a-zA-Z]{24}'''
78+
tags = ["stripe", "api_key"]
79+
80+
# Rule for Twilio API Key
81+
[[rules]]
82+
id = "twilio-api-key"
83+
description = "Twilio API Key"
84+
regex = '''AC[a-zA-Z0-9_\\-]{32}'''
85+
tags = ["twilio", "api_key"]
86+
87+
# Rule for Mailgun API Key
88+
[[rules]]
89+
id = "mailgun-api-key"
90+
description = "Mailgun API Key"
91+
regex = '''key-[0-9a-zA-Z]{32}'''
92+
tags = ["mailgun", "api_key"]
93+
94+
# Rule for Passwords (generic patterns like "password=")
95+
[[rules]]
96+
id = "generic-password"
97+
description = "Potential Password Assignment"
98+
regex = '''(?i)password\\s*=\\s*['"][^'"]+['"]'''
99+
tags = ["password"]
100+
101+
# Rule for Salesforce OAuth Token
102+
[[rules]]
103+
id = "salesforce-oauth-token"
104+
description = "Salesforce OAuth Token"
105+
regex = '''00D[A-Za-z0-9]{15,18}'''
106+
tags = ["salesforce", "oauth_token"]
107+
108+
# Rule for PayPal Braintree Access Token
109+
[[rules]]
110+
id = "braintree-access-token"
111+
description = "PayPal Braintree Access Token"
112+
regex = '''access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}'''
113+
tags = ["braintree", "access_token"]
114+
115+
# Rule for SendGrid API Key
116+
[[rules]]
117+
id = "sendgrid-api-key"
118+
description = "SendGrid API Key"
119+
regex = '''SG\\.[0-9A-Za-z\\-_]{22}\\.[0-9A-Za-z\\-_]{43}'''
120+
tags = ["sendgrid", "api_key"]
121+
122+
123+
# additional rules can be added here

proxy.config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,12 @@
8686

8787

8888
}
89+
},
90+
"checkForSecrets": {
91+
"enabled": false
8992
}
9093

94+
9195
},
9296
"attestationConfig": {
9397
"questions": [

src/proxy/processors/push-action/checkCommitMessages.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const Step = require('../../actions').Step;
22
const config = require('../../../config');
3-
3+
const { exec: eexec } = require('./checkForSecrets');
4+
console.log(eexec);
45
const commitConfig = config.getCommitConfig();
56

67
function isMessageAllowed(commitMessage) {
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
const { Step } = require('../../actions');
2+
const { exec: cexec } = require('child_process');
3+
4+
const path = require('path');
5+
const config = require('../../../config');
6+
const commitConfig = config.getCommitConfig();
7+
8+
// Function to extract relevant file paths from Git diff content
9+
// go to proxyconfig.json and enable the feature
10+
// gitleaks.report.json will show the secrets found and in which file they are found
11+
// Function to extract relevant file paths and their parent directories
12+
13+
// 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"
14+
// use the command to run gitleaks from terminal
15+
// Function to extract relevant directories from Git diff content
16+
function extractRelevantDirectories(diffContent) {
17+
const relevantDirectories = [];
18+
const relevantExtensions = ['.json', '.yaml', '.yml', '.js', '.ts', '.txt'];
19+
const lines = diffContent.split('\n');
20+
21+
lines.forEach((line) => {
22+
const match = line.match(/^diff --git a\/(.+?) b\/(.+?)$/);
23+
if (match) {
24+
const filePath = match[1];
25+
const fileExtension = `.${filePath.split('.').pop()}`;
26+
27+
if (relevantExtensions.includes(fileExtension)) {
28+
const dirPath = path.dirname(filePath);
29+
if (!relevantDirectories.includes(dirPath)) {
30+
relevantDirectories.push(dirPath);
31+
}
32+
}
33+
}
34+
});
35+
36+
return relevantDirectories;
37+
}
38+
39+
// Function to run Gitleaks with directory paths
40+
function runGitleaks(filePaths) {
41+
return new Promise((resolve, reject) => {
42+
const filesToCheck = filePaths
43+
.map((filePath) => `"${path.resolve(filePath).replace(/\\/g, '/')}"`)
44+
.join(' ');
45+
46+
const configPath = path.resolve(__dirname, '../../../../gitleaks.toml').replace(/\\/g, '/');
47+
const reportPath = path
48+
.resolve(__dirname, '../../../../gitleaks_report.json')
49+
.replace(/\\/g, '/');
50+
51+
const command = `gitleaks dir ${filesToCheck} --config="${configPath}" --report-format json --log-level error --report-path="${reportPath}"`;
52+
console.log(`Executing Gitleaks Command: ${command}`);
53+
54+
cexec(command, (error, stdout, stderr) => {
55+
if (error) {
56+
console.error(`Error executing gitleaks: ${error.message}`);
57+
reject(new Error(`Error executing gitleaks: ${error.message}`));
58+
} else if (stderr) {
59+
console.error(`stderr: ${stderr}`);
60+
reject(new Error(`stderr: ${stderr}`));
61+
} else {
62+
resolve(stdout);
63+
}
64+
});
65+
});
66+
}
67+
68+
// Function to check for sensitive secrets in the Gitleaks output
69+
function checkForSensitiveSecrets(output) {
70+
try {
71+
const findings = JSON.parse(output);
72+
73+
if (findings.length > 0) {
74+
findings.forEach((finding) => {
75+
console.log(`Secret found in file: ${finding.file}`);
76+
console.log(` Rule: ${finding.rule_id}`);
77+
console.log(` Secret: ${finding.secret}`);
78+
});
79+
return true;
80+
}
81+
return false;
82+
} catch (error) {
83+
console.error('Error parsing Gitleaks output:', error);
84+
return false;
85+
}
86+
}
87+
88+
// Example usage in exec function
89+
const exec = async (req, action) => {
90+
const diffStep = action.steps.find((s) => s.stepName === 'diff');
91+
const step = new Step('checkforSecrets');
92+
const commitinfo = commitConfig.checkForSecrets;
93+
94+
if (!commitinfo.enabled) {
95+
action.addStep(step);
96+
return action;
97+
}
98+
99+
if (diffStep && diffStep.content) {
100+
const dirPaths = extractRelevantDirectories(diffStep.content);
101+
102+
if (dirPaths.length > 0) {
103+
try {
104+
const result = await runGitleaks(dirPaths);
105+
const hasSensitiveSecrets = checkForSensitiveSecrets(result);
106+
107+
if (hasSensitiveSecrets) {
108+
step.blocked = true;
109+
step.blockedMessage = 'Sensitive secrets detected in the diff.';
110+
console.log('Sensitive secrets detected! Push blocked.');
111+
} else {
112+
console.log('No sensitive secrets detected.');
113+
}
114+
action.addStep(step);
115+
} catch (err) {
116+
console.error('Error during Gitleaks execution:', err);
117+
}
118+
} else {
119+
console.log('No relevant directories found in the diff.');
120+
}
121+
} else {
122+
console.log('No diff content available.');
123+
}
124+
125+
return action;
126+
};
127+
128+
exec.displayName = 'checkforSecrets.exec';
129+
130+
131+
132+

src/proxy/processors/push-action/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ exports.scanDiff = require('./scanDiff').exec;
88
exports.blockForAuth = require('./blockForAuth').exec;
99
exports.checkIfWaitingAuth = require('./checkIfWaitingAuth').exec;
1010
exports.checkCommitMessages = require('./checkCommitMessages').exec;
11+
console.log(__dirname);
1112
exports.checkAuthorEmails = require('./checkAuthorEmails').exec;
1213
exports.checkUserPushPermission = require('./checkUserPushPermission').exec;
1314
exports.clearBareClone = require('./clearBareClone').exec;

test/test_data/sensitive_data.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// File containing sensitive AWS Access Key
2+
const secret = 'AKIAIOSFODNN8EXAMPLE'; // Example AWS access key
3+
console.log(secret);

0 commit comments

Comments
 (0)