Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Fix guarded to return always true #2082

Merged
merged 5 commits into from
Aug 20, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/Jenssegers/Mongodb/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,17 @@ protected function getRelationsWithoutParent()
return $relations;
}

/**
* Checks if column exists on a table. As this is a document model, just return true. This also
* prevents calls to non-existent function Grammar::compileColumnListing()
* @param string $key
* @return bool
*/
protected function isGuardableColumn($key)
{
return true;
}

/**
* @inheritdoc
*/
Expand Down
8 changes: 0 additions & 8 deletions src/Jenssegers/Mongodb/Schema/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@

class Builder extends \Illuminate\Database\Schema\Builder
{
/**
* @inheritdoc
*/
public function __construct(Connection $connection)
{
$this->connection = $connection;
}

/**
* @inheritdoc
*/
Expand Down
8 changes: 8 additions & 0 deletions tests/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function tearDown(): void
Soft::truncate();
Book::truncate();
Item::truncate();
Guarded::truncate();
}

public function testNewModel(): void
Expand Down Expand Up @@ -722,4 +723,11 @@ public function testTruncateModel()

$this->assertEquals(0, User::count());
}

public function testGuardedModel()
{
Guarded::create(['var' => 'val']);

$this->assertEquals(1, Guarded::count());
Copy link
Contributor

@Smolevich Smolevich Aug 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not related test case, i think that we should test that model Guarded doesn't set fields in guarded attribute of Model

$model = Guarded::create(['var' => 'val', 'foobar' => 'bar']);
$this->assertFalse(isset($model->foobar));

See tests in laravel

Copy link

@roelofr roelofr Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error this PR refers to, occurs when Laravel checks using an isGuardedColumn method.
This method however doesn't perform the actual guard checks, it checks if "the given column is a valid, guardable column" (whatever that may mean), which means returning true on this makes sense in a MongoDB scope, given the free nature of documents.

It's easy to add the test, but it's not strictly neccessary as the isGuarded method checks for this (code from Laravel 7.25.0):

return $this->getGuarded() == ['*'] ||
        ! empty(preg_grep('/^'.preg_quote($key).'$/i', $this->getGuarded())) ||
        ! $this->isGuardableColumn($key);

Edit: I looked at the exploit, but since it specifically mentions foo->bar assignments, maybe add a test for json statements too? Adding 'foobar->foo' => true and ensure it's not set?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change test case, please, we can show that test will be broken if laravel changes behavior with guarded fields

}
}
11 changes: 11 additions & 0 deletions tests/models/Guarded.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Guarded extends Eloquent
{
protected $connection = 'mongodb';
protected $collection = 'guarded';
protected $guarded = ['foobar'];
}