valkyrie 3.6.1 → 3.6.2

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: 837b79c2c60f40a910f3aa60a9bc4a4ae66bd803d13c6ccbaac65d41ad060179
4
- data.tar.gz: f503d2fdadbb6eebd349e09d474736e786d6243a7277d9c9e23b7a55a8a0789c
3
+ metadata.gz: 6c19142683e0f4cfdc60b4da2e25a5e0caa37ba49916469e86c15fe89ea147d6
4
+ data.tar.gz: a62e7d67469524073b275e057c69fc3b532ea869779c4a11e80da88142f23a58
5
5
  SHA512:
6
- metadata.gz: 7995dcb171664fa75652e9493e20fcdb73a56737b53781a4cda51bb31ccf692b6430d2207ff6e9ac3b745c62b628b6c4f88bdb8927a9c7503befcc86b3d92105
7
- data.tar.gz: 3efdae4dabe1cc27f8ac2311c6a5dd9bd55f2b839699b677b4d7098c7c58cb65bc44fa1d3213053fdc984cfee4d9428444035a5f918945c97a69721f3eef5be3
6
+ metadata.gz: 7f2b508542a8c1b4b54273de73e37dafddeb453cfb26ececd8dc19f0600fecc140839c9cfe417d82f2dac25aa7d1f8a4c3f8907faf782dc5ec874ec8b4c8808d
7
+ data.tar.gz: f81fbbe0cafe17915422106dc8046ecd72225646a0cb747d62caa81c449f72c7f8d7674dbde8ac1d01683aa0b934392b63da2cddc19786bed33b7cfe7775c3dc
data/Appraisals CHANGED
@@ -5,8 +5,10 @@ end
5
5
 
6
6
  appraise "activerecord-8-0" do
7
7
  gem "activerecord", "~> 8.0.0"
8
+ gem "json", "< 3.0"
8
9
  end
9
10
 
10
11
  appraise "activerecord-7-2" do
11
12
  gem "activerecord", "~> 7.2.0"
13
+ gem "json", "< 3.0"
12
14
  end
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # v3.6.2 2026-10-30
2
+
3
+ * Prevent disk adapter from reading/writing outside base path. ([tpendragon](https://github.com/tpendragon))
4
+
1
5
  # v3.6.1 2026-07-30
2
6
 
3
7
  * Set binary encoding for fedora storage adapter responses. ([dlpierce](https://github.com/dlpierce))
@@ -7,5 +7,6 @@ gem "activerecord", "~> 7.2.0"
7
7
  gem "ldp"
8
8
  gem "pg"
9
9
  gem "rsolr"
10
+ gem "json", "< 3.0"
10
11
 
11
12
  gemspec path: "../"
@@ -7,5 +7,6 @@ gem "activerecord", "~> 8.0.0"
7
7
  gem "ldp"
8
8
  gem "pg"
9
9
  gem "rsolr"
10
+ gem "json", "< 3.0"
10
11
 
11
12
  gemspec path: "../"
@@ -18,6 +18,7 @@ module Valkyrie::Storage
18
18
  # @return [Valkyrie::StorageAdapter::File]
19
19
  def upload(file:, original_filename:, resource: nil, **_extra_arguments)
20
20
  new_path = path_generator.generate(resource: resource, file: file, original_filename: original_filename)
21
+ raise ArgumentError, "path must be within base_path" unless within_base_path?(new_path)
21
22
  FileUtils.mkdir_p(new_path.parent)
22
23
  file_mover.call(file.path, new_path)
23
24
  find_by(id: Valkyrie::ID.new("#{protocol}#{new_path}"))
@@ -26,7 +27,7 @@ module Valkyrie::Storage
26
27
  # @param id [Valkyrie::ID]
27
28
  # @return [Boolean] true if this adapter can handle this type of identifer
28
29
  def handles?(id:)
29
- id.to_s.start_with?("#{protocol}#{base_path}")
30
+ id.to_s.start_with?(protocol) && within_base_path?(id.to_s.delete_prefix(protocol))
30
31
  end
31
32
 
32
33
  # @param feature [Symbol] Feature to test for.
@@ -41,7 +42,9 @@ module Valkyrie::Storage
41
42
  end
42
43
 
43
44
  def file_path(id)
44
- id.to_s.delete_prefix(protocol)
45
+ path = id.to_s.delete_prefix(protocol)
46
+ raise Valkyrie::StorageAdapter::FileNotFound unless within_base_path?(path)
47
+ path
45
48
  end
46
49
 
47
50
  # Return the file associated with the given identifier
@@ -54,6 +57,12 @@ module Valkyrie::Storage
54
57
  raise Valkyrie::StorageAdapter::FileNotFound
55
58
  end
56
59
 
60
+ def within_base_path?(path)
61
+ expanded_base_path = File.expand_path(base_path)
62
+ expanded_path = File.expand_path(path)
63
+ expanded_path == expanded_base_path || expanded_path.start_with?("#{expanded_base_path}/")
64
+ end
65
+
57
66
  ## LazyFile takes File.open parameters but doesn't leave a file handle open on
58
67
  # instantiation. This way StorageAdapter#find_by doesn't open a handle
59
68
  # silently and never clean up after itself.
@@ -23,6 +23,7 @@ module Valkyrie::Storage
23
23
  def upload(file:, original_filename:, resource: nil, paused: false, **extra_arguments)
24
24
  version_timestamp = current_timestamp
25
25
  new_path = path_generator.generate(resource: resource, file: file, original_filename: "v-#{version_timestamp}-#{original_filename}")
26
+ raise ArgumentError, "path must be within base_path" unless within_base_path?(new_path)
26
27
  # If we've gone faster than milliseconds here, pause a millisecond and
27
28
  # re-call. Probably only an issue for test suites.
28
29
  return sleep(0.001) && upload(file: file, original_filename: original_filename, resource: resource, paused: true, **extra_arguments) if !paused && File.exist?(new_path)
@@ -58,7 +59,7 @@ module Valkyrie::Storage
58
59
  # @param id [Valkyrie::ID]
59
60
  # @return [Boolean] true if this adapter can handle this type of identifer
60
61
  def handles?(id:)
61
- id.to_s.start_with?("#{protocol}#{base_path}")
62
+ id.to_s.start_with?(protocol) && within_base_path?(id.to_s.delete_prefix(protocol))
62
63
  end
63
64
 
64
65
  # @param feature [Symbol] Feature to test for.
@@ -113,13 +114,22 @@ module Valkyrie::Storage
113
114
  end
114
115
 
115
116
  def file_path(version_id)
116
- version_id.to_s.gsub(/^#{Regexp.escape(protocol)}/, '')
117
+ path = version_id.to_s.gsub(/^#{Regexp.escape(protocol)}/, '')
118
+ raise Valkyrie::StorageAdapter::FileNotFound unless within_base_path?(path)
119
+ path
120
+ end
121
+
122
+ def within_base_path?(path)
123
+ expanded_base_path = File.expand_path(base_path)
124
+ expanded_path = File.expand_path(path)
125
+ expanded_path == expanded_base_path || expanded_path.start_with?("#{expanded_base_path}/")
117
126
  end
118
127
 
119
128
  # @return VersionId A VersionId value that's resolved a current reference,
120
129
  # so we can access the `version_id` and current reference.
121
130
  def version_id(id)
122
131
  id = VersionId.new(id)
132
+ raise Valkyrie::StorageAdapter::FileNotFound unless within_base_path?(id.file_path)
123
133
  return id unless id.versioned?
124
134
  id.resolve_current
125
135
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie
3
- VERSION = "3.6.1"
3
+ VERSION = "3.6.2"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valkyrie
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.1
4
+ version: 3.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trey Pendragon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-30 00:00:00.000000000 Z
11
+ date: 2026-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct