nostr-zap 0.2.1 → 0.2.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8adf3c935487b6598f64c224fe196c8cf2b2e7c120dd9ef1c478b15570e2e6a3
4
- data.tar.gz: 107fb7009537702c271f4205443286ba136090a1a6d14ac6e01826d654c43731
3
+ metadata.gz: b1feece47ab5f8862dd5c46ffce079eb5499fd850056bb3d71c4460142099fa6
4
+ data.tar.gz: 91712e7614befeec32b360b409cc6e16c2ad555499fcffa1f2e785302eab28c1
5
5
  SHA512:
6
- metadata.gz: 6b7e8aad4a7824cdc850d73c6099b3e80723c3873d4f9930c1bc79ee4c8554693d1be28fbb768e7cff7f2939368270688fa2a75dd28953094c7a63a33e551ecb
7
- data.tar.gz: 3f9c7119b791b8ec79c7a39e9d7e79b30576af5bb1c8f9e121099658a363fb29a44e612fe0e33d130579b08a130927b80fa339aefb0332d064bff46e78e4005b
6
+ metadata.gz: f361d7b5d2204aeec5224251403595f868e50921859b7da12bd0c7e16cb6c575e76e2a9290bf6a2d73d1745ec177ecf1a6470ad71e6a1152c108fe7e609c1cb2
7
+ data.tar.gz: b25fc3739c5e1412960b09c5a33109f0f7dcc2f5c3816b4b2492a0c63cbdab95fc0ad55f1ee5b83c49a24cacff032ecffd53438305f01624efda12e85e94c58b
data/README.md CHANGED
@@ -127,10 +127,16 @@ error = NostrZap::RelayUrlValidator.validate("wss://relay.example.com")
127
127
  # => nil (valid)
128
128
 
129
129
  error = NostrZap::RelayUrlValidator.validate("ws://localhost")
130
- # => "Invalid relay URL scheme 'ws' (only wss is allowed): ws://localhost"
130
+ # => "Relay URL points to a private/reserved address: ws://localhost"
131
+
132
+ error = NostrZap::RelayUrlValidator.validate("ws://localhost:4848", check_private: false)
133
+ # => nil
131
134
 
132
135
  error = NostrZap::RelayUrlValidator.validate("wss://192.168.1.1")
133
136
  # => "Relay URL points to a private/reserved address: wss://192.168.1.1"
137
+
138
+ error = NostrZap::RelayUrlValidator.validate("wss://relay.nostr.bg")
139
+ # => nil (hostnames that do not currently resolve are accepted)
134
140
  ```
135
141
 
136
142
  Blocked IP ranges: `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `169.254.0.0/16`, `0.0.0.0/8`, `::1`, `fc00::/7`, `fe80::/10`.
@@ -5,8 +5,11 @@ require 'resolv'
5
5
  require 'uri'
6
6
 
7
7
  module NostrZap
8
- # Validates that a relay URL is safe to connect to.
9
- # Enforces wss:// scheme and blocks private/reserved IP ranges to prevent SSRF.
8
+ # Validates relay URLs for zap flows.
9
+ #
10
+ # By default, accepts ws:// and wss:// schemes and blocks private/reserved
11
+ # hosts to prevent SSRF. Private host checks can be disabled when validating
12
+ # relay tags in incoming zap requests.
10
13
  #
11
14
  # Returns nil if valid, or an error message string if invalid.
12
15
  #
@@ -15,7 +18,7 @@ module NostrZap
15
18
  # error # => nil (valid)
16
19
  #
17
20
  # error = NostrZap::RelayUrlValidator.validate('ws://localhost')
18
- # error # => "Invalid relay URL scheme 'ws' (only wss is allowed): ws://localhost"
21
+ # error # => "Relay URL points to a private/reserved address: ws://localhost"
19
22
  #
20
23
  class RelayUrlValidator
21
24
  PRIVATE_IP_RANGES = [
@@ -27,15 +30,16 @@ module NostrZap
27
30
  IPAddr.new('0.0.0.0/8'),
28
31
  IPAddr.new('::1/128'),
29
32
  IPAddr.new('fc00::/7'),
30
- IPAddr.new('fe80::/10'),
33
+ IPAddr.new('fe80::/10')
31
34
  ].freeze
32
35
 
33
- def self.validate(url)
34
- new(url).validate
36
+ def self.validate(url, check_private: true)
37
+ new(url, check_private: check_private).validate
35
38
  end
36
39
 
37
- def initialize(url)
40
+ def initialize(url, check_private: true)
38
41
  @url = url
42
+ @check_private = check_private
39
43
  end
40
44
 
41
45
  def validate
@@ -46,12 +50,14 @@ module NostrZap
46
50
  "Invalid relay URL: #{@url}"
47
51
  end
48
52
 
49
- private
53
+ private
54
+
55
+ attr_reader :check_private
50
56
 
51
57
  def validate_scheme(uri)
52
- return if uri.scheme == 'wss'
58
+ return if %w[ws wss].include?(uri.scheme)
53
59
 
54
- "Invalid relay URL scheme '#{uri.scheme}' (only wss is allowed): #{@url}"
60
+ "Invalid relay URL scheme '#{uri.scheme}' (only ws or wss is allowed): #{@url}"
55
61
  end
56
62
 
57
63
  def validate_host(uri)
@@ -61,18 +67,32 @@ module NostrZap
61
67
  end
62
68
 
63
69
  def validate_not_private(uri)
70
+ return unless check_private
64
71
  return unless private_host?(uri.host)
65
72
 
66
73
  "Relay URL points to a private/reserved address: #{@url}"
67
74
  end
68
75
 
69
76
  def private_host?(host)
77
+ ip = parse_ip_literal(host)
78
+ return private_ip?(ip) if ip
79
+
70
80
  addresses = Resolv.getaddresses(host)
71
- return true if addresses.empty?
81
+ return false if addresses.empty?
72
82
 
73
- addresses.any? { |addr| PRIVATE_IP_RANGES.any? { |range| range.include?(addr) } }
83
+ addresses.any? { |addr| private_ip?(addr) }
74
84
  rescue Resolv::ResolvError
75
- true
85
+ false
86
+ end
87
+
88
+ def parse_ip_literal(host)
89
+ IPAddr.new(host)
90
+ rescue IPAddr::InvalidAddressError
91
+ nil
92
+ end
93
+
94
+ def private_ip?(ip)
95
+ PRIVATE_IP_RANGES.any? { |range| range.include?(ip) }
76
96
  end
77
97
  end
78
98
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NostrZap
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.3'
5
5
  end
@@ -139,7 +139,7 @@ module NostrZap
139
139
  return fail_with("Missing required 'relays' tag with at least one relay URL") if urls.nil? || urls.empty?
140
140
 
141
141
  urls.all? do |url|
142
- (error = RelayUrlValidator.validate(url)) ? fail_with(error) : true
142
+ (error = RelayUrlValidator.validate(url, check_private: false)) ? fail_with(error) : true
143
143
  end
144
144
  end
145
145
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nostr-zap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Zykov
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-02-07 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bip-schnorr
@@ -68,7 +67,6 @@ metadata:
68
67
  source_code_uri: https://github.com/sashazykov/nostr-zap
69
68
  changelog_uri: https://github.com/sashazykov/nostr-zap/blob/main/CHANGELOG.md
70
69
  rubygems_mfa_required: 'true'
71
- post_install_message:
72
70
  rdoc_options: []
73
71
  require_paths:
74
72
  - lib
@@ -83,8 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
81
  - !ruby/object:Gem::Version
84
82
  version: '0'
85
83
  requirements: []
86
- rubygems_version: 3.1.6
87
- signing_key:
84
+ rubygems_version: 3.6.9
88
85
  specification_version: 4
89
86
  summary: NIP-57 Zaps for NOSTR — validate zap requests, build zap receipts, publish
90
87
  to relays