Skip to content

Commit cff13ff

Browse files
duncanmccleanclaudejasonvarga
authored
[6.x] Fix validation bypass via spoofed Precognition-Validate-Only header (#14557)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent 01a3af6 commit cff13ff

2 files changed

Lines changed: 29 additions & 5 deletions

File tree

src/Fields/Validator.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Statamic\Fields;
44

5-
use Illuminate\Support\Collection;
65
use Illuminate\Support\Facades\Validator as LaravelValidator;
76
use Statamic\Support\Arr;
87
use Statamic\Support\Str;
@@ -186,12 +185,10 @@ public function filterPrecognitiveRules($rules)
186185
{
187186
$request = request();
188187

189-
if (! $request->headers->has('Precognition-Validate-Only')) {
188+
if (! $request->isPrecognitive()) {
190189
return $rules;
191190
}
192191

193-
return Collection::make($rules)
194-
->only(explode(',', $request->header('Precognition-Validate-Only')))
195-
->all();
192+
return $request->filterPrecognitiveRules($rules);
196193
}
197194
}

tests/Tags/Form/FormCreateAlpineTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Tests\Tags\Form;
44

55
use PHPUnit\Framework\Attributes\Test;
6+
use Statamic\Facades\Form;
67
use Statamic\Statamic;
78

89
class FormCreateAlpineTest extends FormTestCase
@@ -932,6 +933,32 @@ public function it_dynamically_renders_precognition_text_field_x_on_change()
932933
$this->assertFieldRendersHtml(['<input id="[[form-handle]]-form-name-field" type="text" name="name" value="" x-model="form.name" @change="form.validate(\'name\')">'], $config, [], ['js' => 'alpine_precognition']);
933934
}
934935

936+
#[Test]
937+
public function it_validates_precognitive_requests()
938+
{
939+
$this
940+
->withPrecognition()
941+
->withHeaders(['Precognition-Validate-Only' => 'email'])
942+
->postJson('/!/forms/contact', ['email' => ''])
943+
->assertStatus(422)
944+
->assertJsonValidationErrors(['email'])
945+
->assertJsonMissingValidationErrors(['message']);
946+
}
947+
948+
#[Test]
949+
public function it_wont_submit_form_when_precognition_validate_only_header_is_spoofed()
950+
{
951+
$this->assertEmpty(Form::find('contact')->submissions());
952+
953+
$this
954+
->withHeaders(['Precognition-Validate-Only' => 'foo'])
955+
->post('/!/forms/contact', [])
956+
->assertSessionHasErrors(['email'], null, 'form.contact')
957+
->assertLocation('/');
958+
959+
$this->assertEmpty(Form::find('contact')->submissions());
960+
}
961+
935962
private function jsonEncode($data)
936963
{
937964
return Statamic::modify($data)->toJson()->entities();

0 commit comments

Comments
 (0)