statamic / eloquent-driver

Provides support for storing your Statamic data in a database, rather than flat files.
https://statamic.dev/tips/storing-content-in-a-database
MIT License
104 stars 72 forks source link

[Fix] Encode uri for use in blink key #209

Closed dnwjn closed 9 months ago

dnwjn commented 9 months ago

Hi everyone,

This fix will prevent Blink::once() from unexpectedly returning an array when the URI contains certain special characters. I encountered this issue because on one of our sites, visitors have tried navigating to the following URL: https://example.com/blog/skale-v-2-(select(0)from(select(sleep(15)))v)%2f*'+(select(0)from(select(sleep(15)))v)+'%22+(select(0)from(select(sleep(15)))v)+%22*%2f. This in turn triggered the following error: Error: Call to a member function id() on array.

Currently, a URI like above makes Blink::once() return the following:

array:1 [ // vendor/statamic/eloquent-driver/src/Entries/EntryRepository.php:45
  "eloquent-entry-/blog/skale-v-2-(select(0)from(select(sleep(15)))v)%2f*'+(select(0)from(select(sleep(15)))v)+'%22+(select(0)from(select(sleep(15)))v)+%22*%2f-default" => null
]

After applying the fix in this PR, the URI is encoded safely, and the return format of Blink::once() is back to what's expected.

I hope this fix is in line with your standards. If not, feel free to modify or request changes.

Stack trace ``` Error: Call to a member function id() on array #80 /vendor/statamic/eloquent-driver/src/Entries/EntryRepository.php(49): Statamic\Eloquent\Entries\EntryRepository::findByUri #79 /vendor/statamic/cms/src/Data/DataRepository.php(70): Statamic\Data\DataRepository::attemptAllRepositories #78 /vendor/statamic/cms/src/Data/DataRepository.php(41): Statamic\Data\DataRepository::findByUri #77 /vendor/statamic/cms/src/Data/DataRepository.php(60): Statamic\Data\DataRepository::findByRequestUrl #76 /vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(338): Illuminate\Support\Facades\Facade::__callStatic #75 /vendor/statamic/cms/src/Http/Controllers/FrontendController.php(30): Statamic\Http\Controllers\FrontendController::index #74 /vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): Illuminate\Routing\Controller::callAction #73 /vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(43): Illuminate\Routing\ControllerDispatcher::dispatch #72 /vendor/sentry/sentry-laravel/src/Sentry/Laravel/Tracing/Routing/TracingControllerDispatcherTracing.php(21): Sentry\Laravel\Tracing\Routing\TracingControllerDispatcherTracing::Sentry\Laravel\Tracing\Routing\{closure} #71 /vendor/sentry/sentry-laravel/src/Sentry/Laravel/Tracing/Routing/TracingRoutingDispatcher.php(19): Sentry\Laravel\Tracing\Routing\TracingRoutingDispatcher::wrapRouteDispatch #70 /vendor/sentry/sentry-laravel/src/Sentry/Laravel/Tracing/Routing/TracingControllerDispatcherTracing.php(20): Sentry\Laravel\Tracing\Routing\TracingControllerDispatcherTracing::dispatch #69 /vendor/laravel/framework/src/Illuminate/Routing/Route.php(260): Illuminate\Routing\Route::runController #68 /vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\Routing\Route::run #67 /vendor/laravel/framework/src/Illuminate/Routing/Router.php(798): Illuminate\Routing\Router::Illuminate\Routing\{closure} #66 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #65 /vendor/statamic/cms/src/StaticCaching/Middleware/Cache.php(60): Statamic\StaticCaching\Middleware\Cache::handle #64 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #63 /vendor/statamic/cms/src/Http/Middleware/AuthGuard.php(14): Statamic\Http\Middleware\AuthGuard::handle #62 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #61 /vendor/statamic/cms/src/Http/Middleware/AddViewPaths.php(19): Statamic\Http\Middleware\AddViewPaths::handle #60 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #59 /vendor/statamic/cms/src/Http/Middleware/Localize.php(37): Statamic\Http\Middleware\Localize::handle #58 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #57 /vendor/statamic/cms/src/Http/Middleware/HandleToken.php(13): Statamic\Http\Middleware\HandleToken::handle #56 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #55 /vendor/statamic/cms/src/Http/Middleware/StacheLock.php(29): Statamic\Http\Middleware\StacheLock::handle #54 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #53 /vendor/aryehraber/statamic-impersonator/src/ImpersonatorMiddleware.php(15): AryehRaber\Impersonator\ImpersonatorMiddleware::handle #52 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #51 /vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Routing\Middleware\SubstituteBindings::handle #50 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #49 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::handle #48 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #47 /vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\View\Middleware\ShareErrorsFromSession::handle #46 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #45 /vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Session\Middleware\StartSession::handleStatefulRequest #44 /vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession::handle #43 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #42 /vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::handle #41 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #40 /vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Cookie\Middleware\EncryptCookies::handle #39 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #38 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline::then #37 /vendor/laravel/framework/src/Illuminate/Routing/Router.php(799): Illuminate\Routing\Router::runRouteWithinStack #36 /vendor/laravel/framework/src/Illuminate/Routing/Router.php(776): Illuminate\Routing\Router::runRoute #35 /vendor/laravel/framework/src/Illuminate/Routing/Router.php(740): Illuminate\Routing\Router::dispatchToRoute #34 /vendor/laravel/framework/src/Illuminate/Routing/Router.php(729): Illuminate\Routing\Router::dispatch #33 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(190): Illuminate\Foundation\Http\Kernel::Illuminate\Foundation\Http\{closure} #32 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #31 /vendor/statamic/cms/src/Http/Middleware/DisableFloc.php(17): Statamic\Http\Middleware\DisableFloc::handle #30 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #29 /vendor/statamic/cms/src/Http/Middleware/CheckMultisite.php(14): Statamic\Http\Middleware\CheckMultisite::handle #28 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #27 /vendor/statamic/cms/src/Http/Middleware/CheckComposerJsonScripts.php(14): Statamic\Http\Middleware\CheckComposerJsonScripts::handle #26 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #25 /vendor/statamic/cms/src/Http/Middleware/PoweredByHeader.php(18): Statamic\Http\Middleware\PoweredByHeader::handle #24 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #23 /vendor/sentry/sentry-laravel/src/Sentry/Laravel/Http/SetRequestIpMiddleware.php(45): Sentry\Laravel\Http\SetRequestIpMiddleware::handle #22 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #21 /vendor/sentry/sentry-laravel/src/Sentry/Laravel/Http/SetRequestMiddleware.php(30): Sentry\Laravel\Http\SetRequestMiddleware::handle #20 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #19 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Foundation\Http\Middleware\TransformsRequest::handle #18 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::handle #17 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #16 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Foundation\Http\Middleware\TransformsRequest::handle #15 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\Foundation\Http\Middleware\TrimStrings::handle #14 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #13 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Foundation\Http\Middleware\ValidatePostSize::handle #12 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #11 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::handle #10 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #9 /vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(49): Illuminate\Http\Middleware\HandleCors::handle #8 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #7 /vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\Http\Middleware\TrustProxies::handle #6 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #5 /vendor/sentry/sentry-laravel/src/Sentry/Laravel/Tracing/Middleware.php(78): Sentry\Laravel\Tracing\Middleware::handle #4 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Pipeline\Pipeline::Illuminate\Pipeline\{closure} #3 /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline::then #2 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(165): Illuminate\Foundation\Http\Kernel::sendRequestThroughRouter #1 /vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(134): Illuminate\Foundation\Http\Kernel::handle #0 /public/index.php(52): null ```
ryanmitchell commented 9 months ago

Thanks for this - I'd be happy to merge as is, but what about also md5()-ing it so the key is never big?

dnwjn commented 9 months ago

Thanks for this - I'd be happy to merge as is, but what about also md5()-ing it so the key is never big?

I think that's a great idea, I'll implement it right away!