hedra 1.0.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hedra
4
+ # Token bucket rate limiter
5
+ class RateLimiter
6
+ def initialize(rate_string)
7
+ @requests, period = parse_rate(rate_string)
8
+ @period = period_to_seconds(period)
9
+ @tokens = @requests
10
+ @last_refill = Time.now
11
+ @mutex = Mutex.new
12
+ end
13
+
14
+ def acquire
15
+ @mutex.synchronize do
16
+ refill_tokens
17
+
18
+ if @tokens >= 1
19
+ @tokens -= 1
20
+ return
21
+ end
22
+
23
+ # Wait until we have tokens
24
+ sleep_time = @period / @requests
25
+ sleep(sleep_time)
26
+ refill_tokens
27
+ @tokens -= 1
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def parse_rate(rate_string)
34
+ # Format: "10/s", "100/m", "1000/h"
35
+ match = rate_string.match(%r{^(\d+)/([smh])$})
36
+ raise Error, "Invalid rate format: #{rate_string}" unless match
37
+
38
+ [match[1].to_i, match[2]]
39
+ end
40
+
41
+ def period_to_seconds(period)
42
+ case period
43
+ when 's' then 1
44
+ when 'm' then 60
45
+ when 'h' then 3600
46
+ else
47
+ raise Error, "Invalid period: #{period}"
48
+ end
49
+ end
50
+
51
+ def refill_tokens
52
+ now = Time.now
53
+ elapsed = now - @last_refill
54
+
55
+ tokens_to_add = (elapsed / @period) * @requests
56
+ @tokens = [@tokens + tokens_to_add, @requests].min
57
+ @last_refill = now
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hedra
4
+ # Check for security.txt file (RFC 9116)
5
+ class SecurityTxtChecker
6
+ SECURITY_TXT_PATHS = [
7
+ '/.well-known/security.txt',
8
+ '/security.txt'
9
+ ].freeze
10
+
11
+ def check(url, http_client)
12
+ uri = URI.parse(url)
13
+ base_url = "#{uri.scheme}://#{uri.host}#{":#{uri.port}" if uri.port && ![80, 443].include?(uri.port)}"
14
+
15
+ findings = []
16
+ found = false
17
+
18
+ SECURITY_TXT_PATHS.each do |path|
19
+ response = http_client.get("#{base_url}#{path}")
20
+ if response.status.success?
21
+ found = true
22
+ findings.concat(validate_security_txt(response.body.to_s))
23
+ break
24
+ end
25
+ rescue StandardError
26
+ # Continue to next path
27
+ end
28
+
29
+ unless found
30
+ findings << {
31
+ header: 'security.txt',
32
+ issue: 'security.txt file not found',
33
+ severity: :info,
34
+ recommended_fix: 'Add security.txt file at /.well-known/security.txt'
35
+ }
36
+ end
37
+
38
+ findings
39
+ rescue StandardError => e
40
+ warn "security.txt check failed: #{e.message}"
41
+ []
42
+ end
43
+
44
+ private
45
+
46
+ def validate_security_txt(content)
47
+ findings = []
48
+ required_fields = %w[Contact]
49
+ recommended_fields = %w[Expires]
50
+
51
+ required_fields.each do |field|
52
+ next if content.match?(/^#{field}:/i)
53
+
54
+ findings << {
55
+ header: 'security.txt',
56
+ issue: "Missing required field: #{field}",
57
+ severity: :warning,
58
+ recommended_fix: "Add #{field} field to security.txt"
59
+ }
60
+ end
61
+
62
+ recommended_fields.each do |field|
63
+ next if content.match?(/^#{field}:/i)
64
+
65
+ findings << {
66
+ header: 'security.txt',
67
+ issue: "Missing recommended field: #{field}",
68
+ severity: :info,
69
+ recommended_fix: "Consider adding #{field} field to security.txt"
70
+ }
71
+ end
72
+
73
+ # Check expiry
74
+ if content =~ /^Expires:\s*(.+)$/i
75
+ begin
76
+ expiry = Time.parse(::Regexp.last_match(1))
77
+ if expiry < Time.now
78
+ findings << {
79
+ header: 'security.txt',
80
+ issue: 'security.txt has expired',
81
+ severity: :warning,
82
+ recommended_fix: 'Update Expires field in security.txt'
83
+ }
84
+ end
85
+ rescue StandardError
86
+ # Invalid date format
87
+ end
88
+ end
89
+
90
+ findings
91
+ end
92
+ end
93
+ end
data/lib/hedra/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hedra
4
- VERSION = '1.0.1'
4
+ VERSION = '2.0.1'
5
5
  end
data/lib/hedra.rb CHANGED
@@ -1,16 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'hedra/version'
4
- require_relative 'hedra/cli'
5
- require_relative 'hedra/analyzer'
6
- require_relative 'hedra/http_client'
7
- require_relative 'hedra/config'
8
- require_relative 'hedra/plugin_manager'
9
- require_relative 'hedra/exporter'
10
- require_relative 'hedra/scorer'
11
-
12
3
  module Hedra
13
4
  class Error < StandardError; end
14
5
  class NetworkError < Error; end
15
6
  class ConfigError < Error; end
16
7
  end
8
+
9
+ require_relative 'hedra/version'
10
+ require_relative 'hedra/config'
11
+ require_relative 'hedra/scorer'
12
+ require_relative 'hedra/circuit_breaker'
13
+ require_relative 'hedra/certificate_checker'
14
+ require_relative 'hedra/cache'
15
+ require_relative 'hedra/security_txt_checker'
16
+ require_relative 'hedra/progress_tracker'
17
+ require_relative 'hedra/baseline'
18
+ require_relative 'hedra/rate_limiter'
19
+ require_relative 'hedra/http_client'
20
+ require_relative 'hedra/plugin_manager'
21
+ require_relative 'hedra/exporter'
22
+ require_relative 'hedra/html_reporter'
23
+ require_relative 'hedra/analyzer'
24
+ require_relative 'hedra/cli'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hedra
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
- - BlackStack
7
+ - bl4ckstack
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-11-12 00:00:00.000000000 Z
10
+ date: 2025-11-20 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: concurrent-ruby
@@ -96,7 +96,7 @@ dependencies:
96
96
  description: A comprehensive security header analyzer with scanning, auditing, and
97
97
  monitoring capabilities
98
98
  email:
99
- - info@blackstack.com
99
+ - info@bl4ckstack.com
100
100
  executables:
101
101
  - hedra
102
102
  extensions: []
@@ -109,12 +109,20 @@ files:
109
109
  - config/example_rules.yml
110
110
  - lib/hedra.rb
111
111
  - lib/hedra/analyzer.rb
112
+ - lib/hedra/baseline.rb
113
+ - lib/hedra/cache.rb
114
+ - lib/hedra/certificate_checker.rb
115
+ - lib/hedra/circuit_breaker.rb
112
116
  - lib/hedra/cli.rb
113
117
  - lib/hedra/config.rb
114
118
  - lib/hedra/exporter.rb
119
+ - lib/hedra/html_reporter.rb
115
120
  - lib/hedra/http_client.rb
116
121
  - lib/hedra/plugin_manager.rb
122
+ - lib/hedra/progress_tracker.rb
123
+ - lib/hedra/rate_limiter.rb
117
124
  - lib/hedra/scorer.rb
125
+ - lib/hedra/security_txt_checker.rb
118
126
  - lib/hedra/version.rb
119
127
  homepage: https://github.com/bl4ckstack/hedra
120
128
  licenses: