Skip to content

Commit 7edd698

Browse files
authored
Merge pull request #47 from rawilk/unserialize-whitelist
Add safelist for object unserialization
2 parents c5d0663 + 8a63299 commit 7edd698

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

config/settings.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,23 @@
175175
|
176176
*/
177177
'cache_default_value' => true,
178+
179+
/*
180+
|--------------------------------------------------------------------------
181+
| Unserialize Safelist
182+
|--------------------------------------------------------------------------
183+
|
184+
| When using the default value serializer class from this package, we
185+
| will only unserialize objects that have their classes whitelisted here.
186+
| Any other objects will be unserialized to something like:
187+
| __PHP_Incomplete_Class(App\Models\User) {...}
188+
|
189+
| To prevent any objects from being unserialized, simply set this to
190+
| an empty array.
191+
*/
192+
'unserialize_safelist' => [
193+
\Carbon\Carbon::class,
194+
\Carbon\CarbonImmutable::class,
195+
\Illuminate\Support\Carbon::class,
196+
],
178197
];

src/Support/ValueSerializers/ValueSerializer.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Rawilk\Settings\Support\ValueSerializers;
66

7+
use Illuminate\Support\Arr;
78
use Rawilk\Settings\Contracts\ValueSerializer as ValueSerializerContract;
89

910
class ValueSerializer implements ValueSerializerContract
@@ -15,6 +16,8 @@ public function serialize($value): string
1516

1617
public function unserialize(string $serialized): mixed
1718
{
18-
return unserialize($serialized, ['allowed_classes' => false]);
19+
$safelistedClasses = Arr::wrap(config('settings.unserialize_safelist', []));
20+
21+
return unserialize($serialized, ['allowed_classes' => $safelistedClasses]);
1922
}
2023
}

tests/Unit/ValueSerializers/ValueSerializerTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
declare(strict_types=1);
44

5+
use Carbon\Carbon;
6+
use Illuminate\Support\Facades\Date;
57
use Rawilk\Settings\Support\ValueSerializers\ValueSerializer;
68

79
it('serializes values', function (mixed $value) {
@@ -22,6 +24,38 @@
2224
}
2325
})->with('values');
2426

27+
test('certain objects can be safelisted for unserialization', function () {
28+
config(['settings.unserialize_safelist' => [
29+
Carbon::class,
30+
]]);
31+
32+
$serializer = new ValueSerializer;
33+
34+
Date::setTestNow('2023-01-01 10:00:00');
35+
36+
$now = Carbon::now();
37+
38+
$serialized = serialize($now);
39+
$unserialized = $serializer->unserialize($serialized);
40+
41+
expect($unserialized)->toBeInstanceOf(Carbon::class)
42+
->and($unserialized->eq($now))->toBeTrue()
43+
->and($unserialized->toDateTimeString())->toBe('2023-01-01 10:00:00');
44+
});
45+
46+
test('objects not in the safelist will be unserialized to __PHP_Incomplete_Class', function () {
47+
config(['settings.unserialize_safelist' => []]);
48+
49+
$serializer = new ValueSerializer;
50+
51+
$serialized = serialize(Carbon::now());
52+
$unserialized = $serializer->unserialize($serialized);
53+
54+
expect($unserialized)->toBeObject()
55+
->and($unserialized)->not->toBeInstanceOf(Carbon::class)
56+
->and($unserialized)->toBeInstanceOf(__PHP_Incomplete_Class::class);
57+
});
58+
2559
dataset('values', [
2660
null,
2761
1,

0 commit comments

Comments
 (0)