google-site-verification: google61fe8ba583a51912.html
Gitleaks Configuration for Java Projects

Gitleaks is a SAST (Static Application Security Testing) tool for detecting and preventing hardcoded secrets like passwords, API keys, and tokens in git repositories. Here's a comprehensive guide to configuring Gitleaks for Java projects.

Basic Gitleaks Setup

Installation

# Using Homebrew (macOS) brew install gitleaks # Using Docker docker pull zricethezav/gitleaks:latest # Using Go install go install github.com/gitleaks/gitleaks/v8@latest # Download binary from releases wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.0/gitleaks_8.18.0_linux_x64.tar.gz tar -xzf gitleaks_8.18.0_linux_x64.tar.gz sudo mv gitleaks /usr/local/bin/

Basic Usage

# Scan current directory gitleaks detect --source . -v # Scan with report output gitleaks detect --source . --report-format json --report-path gitleaks-report.json # Scan specific file types gitleaks detect --source . --config-path .gitleaks.toml --no-git # Pre-commit hook gitleaks protect --staged

Comprehensive Gitleaks Configuration for Java

Example 1: Basic .gitleaks.toml for Java

# .gitleaks.toml - Basic Java configuration title = "Gitleaks Configuration for Java Project" [[rules]] id = "java-properties-secrets" description = "Detect secrets in Java properties files" regex = '''(?i)(password|passwd|pwd|secret|key|token|auth)(\s*=\s*|\s*:\s*|\"\\s*\"\\s*:?\s*\"?)([a-zA-Z0-9+/=]{8,128})''' tags = ["key", "Java", "properties"] [[rules]] id = "java-connection-strings" description = "Detect database connection strings in Java" regex = '''(jdbc:(mysql|postgresql|oracle|sqlserver)://[^/]+/[^?]+\\?.*?(password|user)=[^&]+)''' tags = ["database", "Java", "JDBC"] [[rules]] id = "java-spring-security" description = "Detect Spring Security secrets" regex = '''(?i)security\\.oauth2\\.client\\.(secret|client-secret)[\\s=:\"]+([a-zA-Z0-9+/=]{8,128})''' tags = ["Spring", "OAuth2", "security"] [[rules]] id = "java-api-keys" description = "Detect API keys in Java code" regex = '''(?i)(api[_-]?key|apikey)[\\s=:\"]+[\"']?([a-zA-Z0-9]{32,64})[\"']?''' tags = ["api", "key", "Java"] # Allowlist common false positives [[allowlist]] description = "Allow example and test credentials" regexes = [ '''example\\.com''', '''localhost''', '''127\\.0\\.0\\.1''', '''test|demo''', '''dummy''', '''placeholder''', '''changeme''', '''password''', '''123456''', '''admin''', '''root''' ] paths = [ "**/test/**", "**/Test/**", "**/testdata/**", "**/examples/**", "**/docs/**", "**/README.md", "**/*.test.*", "**/*Test.*", "**/*test.*" ] commits = [ "commit-hash-1", "commit-hash-2" ]

Example 2: Advanced Java-Specific Configuration

# .gitleaks.toml - Advanced Java configuration title = "Advanced Gitleaks Configuration for Java Microservices" version = "8.18.0" [[rules]] id = "java-spring-boot-application-properties" description = "Secrets in Spring Boot application.properties/yml" regex = '''(?i)((spring|security|management)\\.\\w+\\.(secret|key|token|password))\\s*[=:]\\s*['\"]?([a-zA-Z0-9+/=]{8,128})['\"]?''' tags = ["Spring Boot", "application.properties", "secrets"] [[rules]] id = "java-environment-variables" description = "Hardcoded environment variables in Java" regex = '''System\\.getenv\\([\"']([^\"']+)[\"']\\)|System\\.getProperty\\([\"']([^\"']+)[\"']\\)''' entropy = 3.5 tags = ["environment", "System.getenv"] [[rules]] id = "java-aws-credentials" description = "AWS credentials in Java code" regex = '''(aws\\.(accessKeyId|secretAccessKey)|AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY)[\\s=:\"]+['\"]?([A-Z0-9]{20})['\"]?''' tags = ["AWS", "cloud", "credentials"] [[rules]] id = "java-google-cloud-keys" description = "Google Cloud service account keys" regex = '''\"type\": \"service_account\",\s*\"project_id\": \"[^\"]+\",\s*\"private_key_id\": \"[^\"]+\",\s*\"private_key\": \"-----BEGIN PRIVATE KEY-----''' tags = ["GCP", "service-account", "JSON"] [[rules]] id = "java-jwt-secrets" description = "JWT secrets in Java applications" regex = '''(JWT|jwt)\\.(secret|key|signature)[\\s=:\"]+['\"]?([a-zA-Z0-9+/=]{32,})['\"]?''' tags = ["JWT", "authentication", "security"] [[rules]] id = "java-encryption-keys" description = "Encryption keys in Java code" regex = '''(SecretKeySpec|KeyGenerator|Cipher)\\.getInstance\\([\"']([^\"']+)[\"']\\).*?([a-zA-Z0-9+/=]{16,})''' tags = ["encryption", "crypto", "keys"] [[rules]] id = "java-database-passwords" description = "Database passwords in Java configuration" regex = '''(datasource|database|db)\\.(password|pwd)[\\s=:\"]+['\"]?([a-zA-Z0-9+/=@!]{4,128})['\"]?''' tags = ["database", "password", "JDBC"] [[rules]] id = "java-email-credentials" description = "Email server credentials" regex = '''(mail|email)\\.(smtp|password|auth)[\\s=:\"]+['\"]?([a-zA-Z0-9+/=]{4,128})['\"]?''' tags = ["email", "SMTP", "credentials"] [[rules]] id = "java-payment-keys" description = "Payment gateway API keys" regex = '''(stripe|paypal|braintree)\\.(secret|key|token)[\\s=:\"]+['\"]?(sk_[a-zA-Z0-9]{24}|[a-zA-Z0-9]{32,64})['\"]?''' tags = ["payment", "Stripe", "PayPal"] # Java-specific allowlists [[allowlist]] description = "Allow common test and example patterns in Java" regexes = [ '''jdbc:mysql://localhost:3306/test''', '''jdbc:h2:mem:testdb''', '''spring.datasource.password=password''', '''test.*[Kk]ey''', '''example.*[Tt]oken''', '''mock.*[Ss]ecret''', '''dummy.*[Pp]assword''', '''placeholder.*[Cc]redential''' ] paths = [ "**/src/test/**", "**/test/**", "**/testdata/**", "**/test-resources/**", "**/mock/**", "**/stub/**", "**/*Test.java", "**/*test.java", "**/*IT.java", "**/*IntegrationTest.java", "**/application-test.properties", "**/application-test.yml" ] [[allowlist]] description = "Allow specific comments and documentation" regexes = [ '''//.*[Ee]xample.*[Kk]ey''', '''/\\*.*[Tt]est.*[Tt]oken.*\\*/''', '''#.*[Dd]ummy.*[Pp]assword''', '''<!--.*[Mm]ock.*[Ss]ecret.*-->''' ]

Integration with Java Build Tools

Example 3: Maven Integration

<!-- pom.xml - Gitleaks Maven integration --> <project> <build> <plugins> <!-- Gitleaks Maven Plugin --> <plugin> <groupId>com.github.zricethezav</groupId> <artifactId>gitleaks-maven-plugin</artifactId> <version>1.0.0</version> <configuration> <configPath>${project.basedir}/.gitleaks.toml</configPath> <reportFormat>json</reportFormat> <reportPath>${project.build.directory}/gitleaks-report.json</reportPath> <verbose>true</verbose> <redact>true</redact> </configuration> <executions> <execution> <id>gitleaks-scan</id> <phase>verify</phase> <goals> <goal>protect</goal> </goals> </execution> </executions> </plugin> <!-- Alternatively, use exec-maven-plugin --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>gitleaks-scan</id> <phase>validate</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>gitleaks</executable> <arguments> <argument>detect</argument> <argument>--source</argument> <argument>.</argument> <argument>--config</argument> <argument>.gitleaks.toml</argument> <argument>--report-format</argument> <argument>json</argument> <argument>--report-path</argument> <argument>${project.build.directory}/gitleaks-report.json</argument> </arguments> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>

Example 4: Gradle Integration

// build.gradle - Gitleaks Gradle integration plugins { id 'java' } task gitleaksScan(type: Exec) { commandLine 'gitleaks', 'detect', '--source', '.', '--config', '.gitleaks.toml', '--report-format', 'json', '--report-path', 'build/reports/gitleaks-report.json', '--verbose' doFirst { println "Running Gitleaks secret detection..." } doLast { println "Gitleaks scan completed. Report available at build/reports/gitleaks-report.json" } } task gitleaksProtect(type: Exec) { commandLine 'gitleaks', 'protect', '--staged', '--verbose' doFirst { println "Checking staged files for secrets..." } } // Add as dependency to check task check.dependsOn gitleaksScan // For pre-commit hooks task installGitHooks(type: Copy) { from new File(rootProject.rootDir, 'scripts/pre-commit') into { new File(rootProject.rootDir, '.git/hooks') } fileMode 0755 } build.dependsOn installGitHooks

Git Hooks Integration

Example 5: Pre-commit Hook

#!/bin/bash # .githooks/pre-commit echo "Running Gitleaks secret detection..." # Run gitleaks on staged files GITLEAKS_RESULT=$(gitleaks protect --staged --config=.gitleaks.toml --verbose) if [ $? -eq 0 ]; then echo "✅ Gitleaks scan passed - no secrets detected in staged files" exit 0 else echo "❌ Gitleaks scan failed - potential secrets detected" echo "$GITLEAKS_RESULT" echo "" echo "Please remove the detected secrets before committing." echo "If these are false positives, update .gitleaks.toml allowlist." exit 1 fi

Example 6: Pre-push Hook

#!/bin/bash # .githooks/pre-push echo "Running comprehensive Gitleaks scan..." # Scan entire repository gitleaks detect --source=. --config=.gitleaks.toml --verbose --report-format=json --report-path=./gitleaks-report.json if [ $? -eq 0 ]; then echo "✅ Gitleaks repository scan passed" exit 0 else echo "❌ Gitleaks repository scan failed" echo "Secrets detected in repository history." echo "Check gitleaks-report.json for details." exit 1 fi

CI/CD Pipeline Integration

Example 7: GitHub Actions Workflow

# .github/workflows/gitleaks.yml name: Gitleaks Secret Detection on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] schedule: - cron: '0 0 * * 0' # Weekly scan jobs: gitleaks: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 # Full history for complete scan - name: Run Gitleaks uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: config-path: .gitleaks.toml report-format: sarif report-path: gitleaks-report.sarif redact: true verbose: true - name: Upload Gitleaks Report uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: gitleaks-report.sarif - name: Fail if secrets detected run: | if [ -f gitleaks-report.sarif ]; then echo "❌ Secrets detected in codebase" echo "Please check the Security tab for details" exit 1 else echo "✅ No secrets detected" fi

Example 8: GitLab CI Configuration

# .gitlab-ci.yml stages: - security gitleaks_scan: stage: security image: name: zricethezav/gitleaks:latest entrypoint: [""] script: - gitleaks detect --source=. --config=.gitleaks.toml --report-format=json --report-path=gitleaks-report.json --verbose artifacts: when: always paths: - gitleaks-report.json reports: secret_detection: gitleaks-report.json allow_failure: false rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Example 9: Jenkins Pipeline

// Jenkinsfile pipeline { agent any stages { stage('Secret Detection') { steps { script { sh ''' echo "Running Gitleaks secret detection..." gitleaks detect --source=. \ --config=.gitleaks.toml \ --report-format=json \ --report-path=gitleaks-report.json \ --verbose ''' } } post { always { archiveArtifacts artifacts: 'gitleaks-report.json', fingerprint: true publishJSON target: [ reportDir: '.', reportFiles: 'gitleaks-report.json', reportName: 'Gitleaks Report' ] } failure { emailext ( subject: "🚨 SECRETS DETECTED in ${env.JOB_NAME}", body: """ Gitleaks has detected potential secrets in the codebase. Build: ${env.BUILD_URL} Project: ${env.JOB_NAME} Please check the attached report and remove any detected secrets. """, to: "${env.CHANGE_AUTHOR_EMAIL}", attachmentsPattern: 'gitleaks-report.json' ) } } } } }

Custom Rules for Java-Specific Patterns

Example 10: Java-Specific Secret Patterns

# java-specific-rules.toml [[rules]] id = "java-spring-cloud-config" description = "Spring Cloud Config secrets" regex = '''spring\\.cloud\\.config\\.(token|password|username)[\\s=:\"]+['\"]?([a-zA-Z0-9+/=]{8,128})['\"]?''' tags = ["Spring Cloud", "config", "secrets"] [[rules]] id = "java-microprofile-config" description = "MicroProfile Config secrets" regex = '''@ConfigProperty\\(name\\s*=\\s*\"([^\"]+)\"\\s*\\)\\s*.*?=\\s*[\"']([a-zA-Z0-9+/=]{8,128})[\"']''' tags = ["MicroProfile", "config", "secrets"] [[rules]] id = "java-quarkus-config" description = "Quarkus configuration secrets" regex = '''quarkus\\.\\w+\\.(secret|key|token|password)[\\s=:\"]+['\"]?([a-zA-Z0-9+/=]{8,128})['\"]?''' tags = ["Quarkus", "configuration", "secrets"] [[rules]] id = "java-micronaut-config" description = "Micronaut configuration secrets" regex = '''micronaut\\.\\w+\\.(secret|key|token|password)[\\s=:\"]+['\"]?([a-zA-Z0-9+/=]{8,128})['\"]?''' tags = ["Micronaut", "configuration", "secrets"] [[rules]] id = "java-actuator-endpoints" description = "Spring Boot Actuator secrets" regex = '''management\\.endpoint\\.\\w+\\.(key|secret|token)[\\s=:\"]+['\"]?([a-zA-Z0-9+/=]{8,128})['\"]?''' tags = ["Spring Boot", "Actuator", "security"] [[rules]] id = "java-encrypted-properties" description = "Jasypt encrypted properties" regex = '''ENC\\(([a-zA-Z0-9+/=]+)\\)''' tags = ["Jasypt", "encryption", "properties"] [[rules]] id = "java-keystore-passwords" description = "Java keystore passwords" regex = '''(keyStore|trustStore)Password[\\s=:\"]+['\"]?([a-zA-Z0-9+/=@!]{6,128})['\"]?''' tags = ["Java", "keystore", "SSL", "TLS"] [[rules]] id = "java-logging-sensitivedata" description = "Potential sensitive data in log statements" regex = '''(LOGGER|log|logger)\\.(info|debug|warn|error)\\(.*?(password|token|secret|key).*?\\).*?''' tags = ["logging", "sensitive data", "security"]

Monitoring and Reporting

Example 11: Custom Reporting Script

// GitleaksReportParser.java import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.Map; public class GitleaksReportParser { private static final ObjectMapper mapper = new ObjectMapper(); public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: java GitleaksReportParser <gitleaks-report.json>"); System.exit(1); } String reportPath = args[0]; parseAndAnalyzeReport(reportPath); } public static void parseAndAnalyzeReport(String reportPath) throws Exception { String jsonContent = new String(Files.readAllBytes(Paths.get(reportPath))); Map<String, Object> report = mapper.readValue(jsonContent, Map.class); @SuppressWarnings("unchecked") List<Map<String, Object>> findings = (List<Map<String, Object>>) report.get("Findings"); System.out.println("=== GITLEAKS REPORT ANALYSIS ==="); System.out.println("Total findings: " + findings.size()); // Group by rule ID Map<String, Long> findingsByRule = findings.stream() .collect(Collectors.groupingBy( finding -> (String) finding.get("RuleID"), Collectors.counting() )); System.out.println("\nFindings by rule:"); findingsByRule.entrySet().stream() .sorted(Map.Entry.<String, Long>comparingByValue().reversed()) .forEach(entry -> System.out.printf(" %s: %d findings%n", entry.getKey(), entry.getValue()) ); // Group by file Map<String, Long> findingsByFile = findings.stream() .collect(Collectors.groupingBy( finding -> (String) finding.get("File"), Collectors.counting() )); System.out.println("\nTop files with findings:"); findingsByFile.entrySet().stream() .sorted(Map.Entry.<String, Long>comparingByValue().reversed()) .limit(10) .forEach(entry -> System.out.printf(" %s: %d findings%n", entry.getKey(), entry.getValue()) ); // Print details for critical findings System.out.println("\nCritical findings details:"); findings.stream() .filter(finding -> isCriticalFinding(finding)) .forEach(finding -> { System.out.printf(" File: %s%n", finding.get("File")); System.out.printf(" Rule: %s%n", finding.get("RuleID")); System.out.printf(" Line: %s%n", finding.get("StartLine")); System.out.printf(" Secret: %s%n", redactSecret((String) finding.get("Secret"))); System.out.println(" ---"); }); } private static boolean isCriticalFinding(Map<String, Object> finding) { String ruleId = (String) finding.get("RuleID"); return ruleId.contains("aws") || ruleId.contains("jwt") || ruleId.contains("private_key") || ruleId.contains("database"); } private static String redactSecret(String secret) { if (secret == null || secret.length() <= 8) { return "***"; } return secret.substring(0, 4) + "***" + secret.substring(secret.length() - 4); } }

Best Practices for Java Projects

  1. Scan Early and Often: Integrate into pre-commit hooks and CI/CD
  2. Customize Rules: Tailor rules for your Java framework (Spring, Quarkus, etc.)
  3. Regular Updates: Keep Gitleaks and rules updated
  4. Educate Team: Train developers on secret management
  5. Use Secret Management: Integrate with HashiCorp Vault, AWS Secrets Manager, etc.
  6. Monitor and Alert: Set up alerts for detected secrets

Conclusion

Gitleaks provides robust secret detection for Java projects when properly configured. Key recommendations:

  • Comprehensive Configuration: Use Java-specific rules and allowlists
  • CI/CD Integration: Automate scanning in pipelines
  • Developer Workflow: Integrate with pre-commit hooks
  • Regular Maintenance: Update rules and configurations
  • Security Culture: Combine tools with education and processes

By implementing these configurations, Java teams can effectively prevent secret leakage and maintain strong security posture throughout the development lifecycle.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper