Class: Ace::Git::Secrets::Molecules::HistoryScanner

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/git/secrets/molecules/history_scanner.rb

Overview

Scans Git history for authentication tokens using gitleaks

This is a thin wrapper around GitleaksRunner that adds:

  • File exclusion filtering

  • Confidence level filtering

  • ScanReport generation

Gitleaks is required - install with: brew install gitleaks

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repository_path: ".", gitleaks_config: nil, exclusions: nil) ⇒ HistoryScanner

Returns a new instance of HistoryScanner.

Parameters:

  • repository_path (String) (defaults to: ".")

    Path to git repository

  • gitleaks_config (String, nil) (defaults to: nil)

    Path to gitleaks config

  • exclusions (Array<String>, nil) (defaults to: nil)

    Glob patterns for files to exclude



23
24
25
26
27
# File 'lib/ace/git/secrets/molecules/history_scanner.rb', line 23

def initialize(repository_path: ".", gitleaks_config: nil, exclusions: nil)
  @repository_path = File.expand_path(repository_path)
  @gitleaks_runner = Atoms::GitleaksRunner.new(config_path: gitleaks_config)
  @exclusions = exclusions || Ace::Git::Secrets.exclusions
end

Instance Attribute Details

#exclusionsObject (readonly)

Returns the value of attribute exclusions.



18
19
20
# File 'lib/ace/git/secrets/molecules/history_scanner.rb', line 18

def exclusions
  @exclusions
end

#gitleaks_runnerObject (readonly)

Returns the value of attribute gitleaks_runner.



18
19
20
# File 'lib/ace/git/secrets/molecules/history_scanner.rb', line 18

def gitleaks_runner
  @gitleaks_runner
end

#repository_pathObject (readonly)

Returns the value of attribute repository_path.



18
19
20
# File 'lib/ace/git/secrets/molecules/history_scanner.rb', line 18

def repository_path
  @repository_path
end

Instance Method Details

#scan(since: nil, min_confidence: "low") ⇒ Models::ScanReport

Scan repository history for tokens

Parameters:

  • since (String, nil) (defaults to: nil)

    Start commit or date

  • min_confidence (String) (defaults to: "low")

    Minimum confidence level

Returns:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/ace/git/secrets/molecules/history_scanner.rb', line 33

def scan(since: nil, min_confidence: "low")
  # Ensure gitleaks is available
  Atoms::GitleaksRunner.ensure_available!

  result = gitleaks_runner.scan_history(
    path: repository_path,
    since: since
  )

  detected_tokens = result[:findings].map do |f|
    # Apply exclusions
    next if excluded_file?(f[:file_path])

    Models::DetectedToken.new(
      token_type: f[:token_type],
      pattern_name: f[:pattern_name],
      confidence: f[:confidence],
      commit_hash: f[:commit_hash],
      file_path: f[:file_path],
      line_number: f[:line_number],
      raw_value: f[:matched_value],
      detected_by: "gitleaks"
    )
  end.compact

  # Filter by confidence
  detected_tokens = filter_by_confidence(detected_tokens, min_confidence)

  Models::ScanReport.new(
    tokens: detected_tokens,
    repository_path: repository_path,
    scanned_at: Time.now,
    scan_options: {since: since, min_confidence: min_confidence},
    commits_scanned: count_commits(since: since),
    detection_method: "gitleaks"
  )
end

#scan_files(min_confidence: "low") ⇒ Models::ScanReport

Scan only current files (no history)

Parameters:

  • min_confidence (String) (defaults to: "low")

    Minimum confidence level

Returns:



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ace/git/secrets/molecules/history_scanner.rb', line 74

def scan_files(min_confidence: "low")
  # Ensure gitleaks is available
  Atoms::GitleaksRunner.ensure_available!

  result = gitleaks_runner.scan_files(path: repository_path)

  detected_tokens = result[:findings].map do |f|
    # Apply exclusions
    next if excluded_file?(f[:file_path])

    Models::DetectedToken.new(
      token_type: f[:token_type],
      pattern_name: f[:pattern_name],
      confidence: f[:confidence],
      commit_hash: "HEAD",
      file_path: f[:file_path],
      line_number: f[:line_number],
      raw_value: f[:matched_value],
      detected_by: "gitleaks"
    )
  end.compact

  detected_tokens = filter_by_confidence(detected_tokens, min_confidence)

  Models::ScanReport.new(
    tokens: detected_tokens,
    repository_path: repository_path,
    scanned_at: Time.now,
    scan_options: {files_only: true, min_confidence: min_confidence},
    commits_scanned: 0,
    detection_method: "gitleaks"
  )
end