Issues (20)

Security Analysis    1 potential vulnerability

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/CRUDlex/Controller.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of the CRUDlex package.
5
 *
6
 * (c) Philip Lehmann-Böhm <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CRUDlex;
13
14
use League\Flysystem\FilesystemInterface;
15
use League\Flysystem\Util\MimeType;
16
use Symfony\Component\HttpFoundation\RedirectResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpFoundation\Session\SessionInterface;
20
use Symfony\Component\HttpFoundation\StreamedResponse;
21
use Symfony\Component\Translation\TranslatorInterface;
22
use Twig_Environment;
23
24
25
/**
26
 * Default implementation of the ControllerInterface.
27
 */
28
class Controller implements ControllerInterface {
29
30
    /**
31
     * Often used i18n key.
32
     */
33
    const TR_RESOURCE_NOT_FOUND = 'crudlex.resourceNotFound';
34
35
    /**
36
     * Often used i18n key.
37
     */
38
    const TR_INSTANCE_NOT_FOUND = 'crudlex.instanceNotFound';
39
40
    /**
41
     * Holds the filesystme.
42
     * @var FilesystemInterface
43
     */
44
    protected $filesystem;
45
46
    /**
47
     * Holds the session.
48
     * @var SessionInterface
49
     */
50
    protected $session;
51
52
    /**
53
     * Holds the translator.
54
     * @var TranslatorInterface
55
     */
56
    protected $translator;
57
58
    /**
59
     * Holds the service.
60
     * @var Service
61
     */
62
    protected $service;
63
64
    /**
65
     * Holds the Twig instance.
66
     * @var Twig_Environment
67
     */
68
    protected $twig;
69
70
    /**
71
     * Postprocesses the entity after modification by handling the uploaded
72
     * files and setting the flash.
73
     *
74
     * @param Request $request
75
     * the current request
76
     * @param AbstractData $crudData
77
     * the data instance of the entity
78
     * @param Entity $instance
79
     * the entity
80
     * @param string $entity
81
     * the name of the entity
82
     * @param string $mode
83
     * whether to 'edit' or to 'create' the entity
84
     *
85
     * @return null|\Symfony\Component\HttpFoundation\RedirectResponse
86
     * the HTTP response of this modification
87
     */
88 4
    protected function modifyFilesAndSetFlashBag(Request $request, AbstractData $crudData, Entity $instance, $entity, $mode)
89
    {
90 4
        $id          = $instance->get('id');
91 4
        $fileHandler = new FileHandler($this->filesystem, $crudData->getDefinition());
92 4
        $result      = $mode == 'edit' ? $fileHandler->updateFiles($crudData, $request, $instance, $entity) : $fileHandler->createFiles($crudData, $request, $instance, $entity);
93 4
        if (!$result) {
94 2
            return null;
95
        }
96 4
        $this->session->getFlashBag()->add('success', $this->translator->trans('crudlex.'.$mode.'.success', [
97 4
            '%label%' => $crudData->getDefinition()->getLabel(),
98 4
            '%id%' => $id
99
        ]));
100 4
        return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
101
    }
102
103
    /**
104
     * Sets the flashes of a failed entity modification.
105
     *
106
     * @param boolean $optimisticLocking
107
     * whether the optimistic locking failed
108
     * @param string $mode
109
     * the modification mode, either 'create' or 'edit'
110
     */
111 2
    protected function setValidationFailedFlashes($optimisticLocking, $mode)
112
    {
113 2
        $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.'.$mode.'.error'));
114 2
        if ($optimisticLocking) {
115 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.edit.locked'));
116
        }
117 2
    }
118
119
    /**
120
     * Validates and saves the new or updated entity and returns the appropriate HTTP
121
     * response.
122
     *
123
     * @param Request $request
124
     * the current request
125
     * @param AbstractData $crudData
126
     * the data instance of the entity
127
     * @param Entity $instance
128
     * the entity
129
     * @param string $entity
130
     * the name of the entity
131
     * @param boolean $edit
132
     * whether to edit (true) or to create (false) the entity
133
     *
134
     * @return Response
135
     * the HTTP response of this modification
136
     */
137 4
    protected function modifyEntity(Request $request, AbstractData $crudData, Entity $instance, $entity, $edit)
138
    {
139 4
        $fieldErrors = [];
140 4
        $mode        = $edit ? 'edit' : 'create';
141 4
        if ($request->getMethod() == 'POST') {
142 4
            $instance->populateViaRequest($request);
143 4
            $validator  = new EntityValidator($instance);
144 4
            $validation = $validator->validate($crudData, intval($request->get('version')));
145
146 4
            $fieldErrors = $validation['errors'];
147 4
            if (!$validation['valid']) {
148 2
                $optimisticLocking = isset($fieldErrors['version']);
149 2
                $this->setValidationFailedFlashes($optimisticLocking, $mode);
150
            } else {
151 4
                $modified = $edit ? $crudData->update($instance) : $crudData->create($instance);
152 4
                $response = $modified ? $this->modifyFilesAndSetFlashBag($request, $crudData, $instance, $entity, $mode) : false;
153 4
                if ($response) {
154 4
                    return $response;
155
                }
156 2
                $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.'.$mode.'.failed'));
157
            }
158
        }
159
160 2
        return new Response($this->twig->render($this->service->getTemplate('template', 'form', $entity), [
161 2
            'crud' => $this->service,
162 2
            'crudEntity' => $entity,
163 2
            'crudData' => $crudData,
164 2
            'entity' => $instance,
165 2
            'mode' => $mode,
166 2
            'fieldErrors' => $fieldErrors,
167 2
            'layout' => $this->service->getTemplate('layout', $mode, $entity)
168
        ]));
169
    }
170
171
    /**
172
     * Gets the parameters for the redirection after deleting an entity.
173
     *
174
     * @param Request $request
175
     * the current request
176
     * @param string $entity
177
     * the entity name
178
     * @param string $redirectPage
179
     * reference, where the page to redirect to will be stored
180
     *
181
     * @return array<string,string>
182
     * the parameters of the redirection, entity and id
183
     */
184 1
    protected function getAfterDeleteRedirectParameters(Request $request, $entity, &$redirectPage)
185
    {
186 1
        $redirectPage       = 'crudList';
187 1
        $redirectParameters = ['entity' => $entity];
188 1
        $redirectEntity     = $request->get('redirectEntity');
189 1
        $redirectId         = $request->get('redirectId');
190 1
        if ($redirectEntity && $redirectId) {
191 1
            $redirectPage       = 'crudShow';
192
            $redirectParameters = [
193 1
                'entity' => $redirectEntity,
194 1
                'id' => $redirectId
195
            ];
196
        }
197 1
        return $redirectParameters;
198
    }
199
200
    /**
201
     * Builds up the parameters of the list page filters.
202
     *
203
     * @param Request $request
204
     * the current request
205
     * @param EntityDefinition $definition
206
     * the current entity definition
207
     * @param array &$filter
208
     * will hold a map of fields to request parameters for the filters
209
     * @param boolean $filterActive
210
     * reference, will be true if at least one filter is active
211
     * @param array $filterToUse
212
     * reference, will hold a map of fields to integers (0 or 1) which boolean filters are active
213
     * @param array $filterOperators
214
     * reference, will hold a map of fields to operators for AbstractData::listEntries()
215
     *
216
     * @return array
217
     * the raw filter query parameters
218
     */
219 2
    protected function buildUpListFilter(Request $request, EntityDefinition $definition, &$filter, &$filterActive, &$filterToUse, &$filterOperators)
220
    {
221 2
        $rawFilter = [];
222 2
        foreach ($definition->getFilter() as $filterField) {
223 2
            $type                    = $definition->getType($filterField);
224 2
            $filter[$filterField]    = $request->get('crudFilter'.$filterField);
225 2
            $rawFilter[$filterField] = $filter[$filterField];
226 2
            if ($filter[$filterField]) {
227 1
                $filterActive                  = true;
228 1
                $filterToUse[$filterField]     = $filter[$filterField];
229 1
                $filterOperators[$filterField] = '=';
230 1
                if ($type === 'boolean') {
231 1
                    $filterToUse[$filterField] = $filter[$filterField] == 'true' ? 1 : 0;
232 1
                } else if ($type === 'reference') {
233 1
                    $filter[$filterField] = ['id' => $filter[$filterField]];
234 1
                } else if ($type === 'many') {
235
                    $filter[$filterField] = array_map(function($value) {
236 1
                        return ['id' => $value];
237 1
                    }, $filter[$filterField]);
238 1
                    $filterToUse[$filterField] = $filter[$filterField];
239 1
                } else if (in_array($type, ['text', 'multiline', 'fixed'])) {
240 1
                    $filterToUse[$filterField]     = '%'.$filter[$filterField].'%';
241 1
                    $filterOperators[$filterField] = 'LIKE';
242
                }
243
            }
244
        }
245 2
        return $rawFilter;
246
    }
247
248
    /**
249
     * Generates the not found page.
250
     *
251
     * @param string $error
252
     * the cause of the not found error
253
     *
254
     * @return Response
255
     * the rendered not found page with the status code 404
256
     */
257 10
    protected function getNotFoundPage($error)
258
    {
259 10
        return new Response($this->twig->render('@crud/notFound.twig', [
260 10
            'crud' => $this->service,
261 10
            'error' => $error,
262 10
            'crudEntity' => '',
263 10
            'layout' => $this->service->getTemplate('layout', '', '')
264 10
        ]), 404);
265
    }
266
267
    /**
268
     * Controller constructor.
269
     *
270
     * @param Service $service
271
     * the CRUDlex service
272
     * @param FilesystemInterface $filesystem
273
     * the used filesystem
274
     * @param \Twig\Environment $twig
275
     * the Twig environment
276
     * @param SessionInterface $session
277
     * the session service
278
     * @param TranslatorInterface $translator
279
     * the translation service
280
     */
281 10
    public function __construct(Service $service, FilesystemInterface $filesystem, \Twig\Environment $twig, SessionInterface $session, TranslatorInterface $translator)
282
    {
283 10
        $this->service    = $service;
284 10
        $this->filesystem = $filesystem;
285 10
        $this->twig       = $twig;
0 ignored issues
show
Documentation Bug introduced by
It seems like $twig of type object<Twig\Environment> is incompatible with the declared type object<Twig_Environment> of property $twig.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
286 10
        $this->session    = $session;
287 10
        $this->translator = $translator;
288 10
    }
289
290
    /**
291
     * {@inheritdoc}
292
     */
293 2
    public function setLocaleAndCheckEntity(Request $request)
294
    {
295 2
        $locale = $this->translator->getLocale();
296 2
        $this->service->setLocale($locale);
297 2
        if (!$this->service->getData($request->get('entity'))) {
298 2
            return $this->getNotFoundPage($this->translator->trans('crudlex.entityNotFound'));
299
        }
300 1
        return null;
301
    }
302
303
    /**
304
     * {@inheritdoc}
305
     */
306 3
    public function create(Request $request, $entity)
307
    {
308 3
        $crudData = $this->service->getData($entity);
309 3
        if (!$crudData) {
310 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
311
        }
312 3
        $instance = $crudData->createEmpty();
313 3
        $instance->populateViaRequest($request);
314 3
        return $this->modifyEntity($request, $crudData, $instance, $entity, false);
315
    }
316
317
    /**
318
     * {@inheritdoc}
319
     */
320 2
    public function showList(Request $request, $entity)
321
    {
322 2
        $crudData = $this->service->getData($entity);
323 2
        if (!$crudData) {
324 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
325
        }
326 2
        $definition = $crudData->getDefinition();
327
328 2
        $filter          = [];
329 2
        $filterActive    = false;
330 2
        $filterToUse     = [];
331 2
        $filterOperators = [];
332 2
        $rawFilter       = $this->buildUpListFilter($request, $definition, $filter, $filterActive, $filterToUse, $filterOperators);
333
334 2
        $pageSize = $definition->getPageSize();
335 2
        $total    = $crudData->countBy($definition->getTable(), $filterToUse, $filterOperators, true);
336 2
        $page     = abs(intval($request->get('crudPage', 0)));
337 2
        $maxPage  = intval($total / $pageSize);
338 2
        if ($total % $pageSize == 0) {
339 2
            $maxPage--;
340
        }
341 2
        if ($page > $maxPage) {
342 1
            $page = $maxPage;
343
        }
344 2
        $skip = $page * $pageSize;
345
346 2
        $sortField            = $request->get('crudSortField', $definition->getInitialSortField());
347 2
        $sortAscendingRequest = $request->get('crudSortAscending');
348 2
        $sortAscending        = $sortAscendingRequest !== null ? $sortAscendingRequest === 'true' : $definition->isInitialSortAscending();
349
350 2
        $entities = $crudData->listEntries($filterToUse, $filterOperators, $skip, $pageSize, $sortField, $sortAscending);
351
352 2
        return new Response($this->twig->render($this->service->getTemplate('template', 'list', $entity), [
353 2
            'crud' => $this->service,
354 2
            'crudEntity' => $entity,
355 2
            'crudData' => $crudData,
356 2
            'definition' => $definition,
357 2
            'entities' => $entities,
358 2
            'pageSize' => $pageSize,
359 2
            'maxPage' => $maxPage,
360 2
            'page' => $page,
361 2
            'total' => $total,
362 2
            'filter' => $filter,
363 2
            'rawFilter' => $rawFilter,
364 2
            'filterActive' => $filterActive,
365 2
            'sortField' => $sortField,
366 2
            'sortAscending' => $sortAscending,
367 2
            'layout' => $this->service->getTemplate('layout', 'list', $entity)
368
        ]));
369
    }
370
371
    /**
372
     * {@inheritdoc}
373
     */
374 1
    public function show($entity, $id)
375
    {
376 1
        $crudData = $this->service->getData($entity);
377 1
        if (!$crudData) {
378 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
379
        }
380 1
        $instance = $crudData->get($id);
381 1
        if (!$instance) {
382 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_INSTANCE_NOT_FOUND));
383
        }
384 1
        $definition = $crudData->getDefinition();
385
386 1
        $childrenLabelFields = $definition->getChildrenLabelFields();
387 1
        $children            = [];
388 1
        if (count($childrenLabelFields) > 0) {
389 1
            foreach ($definition->getChildren() as $child) {
390 1
                $childField      = $child[1];
391 1
                $childEntity     = $child[2];
392 1
                $childLabelField = array_key_exists($childEntity, $childrenLabelFields) ? $childrenLabelFields[$childEntity] : 'id';
393 1
                $childCrud       = $this->service->getData($childEntity);
394 1
                $children[]      = [
395 1
                    $childCrud->getDefinition()->getLabel(),
396 1
                    $childEntity,
397 1
                    $childLabelField,
398 1
                    $childCrud->listEntries([$childField => $instance->get('id')]),
399 1
                    $childField
400
                ];
401
            }
402
        }
403
404 1
        return new Response($this->twig->render($this->service->getTemplate('template', 'show', $entity), [
405 1
            'crud' => $this->service,
406 1
            'crudEntity' => $entity,
407 1
            'entity' => $instance,
408 1
            'children' => $children,
409 1
            'layout' => $this->service->getTemplate('layout', 'show', $entity)
410
        ]));
411
    }
412
413
    /**
414
     * {@inheritdoc}
415
     */
416 1
    public function edit(Request $request, $entity, $id)
417
    {
418 1
        $crudData = $this->service->getData($entity);
419 1
        if (!$crudData) {
420 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
421
        }
422 1
        $instance = $crudData->get($id);
423 1
        if (!$instance) {
424 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_INSTANCE_NOT_FOUND));
425
        }
426
427 1
        return $this->modifyEntity($request, $crudData, $instance, $entity, true);
428
    }
429
430
    /**
431
     * {@inheritdoc}
432
     */
433 1
    public function delete(Request $request, $entity, $id)
434
    {
435 1
        $crudData = $this->service->getData($entity);
436 1
        if (!$crudData) {
437 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
438
        }
439 1
        $instance = $crudData->get($id);
440 1
        if (!$instance) {
441 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_INSTANCE_NOT_FOUND));
442
        }
443
444 1
        $fileHandler  = new FileHandler($this->filesystem, $crudData->getDefinition());
445 1
        $filesDeleted = $fileHandler->deleteFiles($crudData, $instance, $entity);
446 1
        $deleted      = $filesDeleted ? $crudData->delete($instance) : AbstractData::DELETION_FAILED_EVENT;
447
448 1
        if ($deleted === AbstractData::DELETION_FAILED_EVENT) {
449 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.delete.failed'));
450 1
            return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
451 1
        } elseif ($deleted === AbstractData::DELETION_FAILED_STILL_REFERENCED) {
452 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.delete.error', [
453 1
                '%label%' => $crudData->getDefinition()->getLabel()
454
            ]));
455 1
            return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
456
        }
457
458 1
        $redirectPage       = 'crudList';
459 1
        $redirectParameters = $this->getAfterDeleteRedirectParameters($request, $entity, $redirectPage);
460
461 1
        $this->session->getFlashBag()->add('success', $this->translator->trans('crudlex.delete.success', [
462 1
            '%label%' => $crudData->getDefinition()->getLabel()
463
        ]));
464 1
        return new RedirectResponse($this->service->generateURL($redirectPage, $redirectParameters));
465
    }
466
467
    /**
468
     * {@inheritdoc}
469
     */
470 1
    public function renderFile($entity, $id, $field)
471
    {
472 1
        $crudData = $this->service->getData($entity);
473 1
        if (!$crudData) {
474 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
475
        }
476 1
        $instance   = $crudData->get($id);
477 1
        $definition = $crudData->getDefinition();
478 1
        if (!$instance || $definition->getType($field) != 'file' || !$instance->get($field)) {
479 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_INSTANCE_NOT_FOUND));
480
        }
481 1
        $fileHandler = new FileHandler($this->filesystem, $definition);
482 1
        return $fileHandler->renderFile($instance, $entity, $field);
483
    }
484
485
    /**
486
     * {@inheritdoc}
487
     */
488 1
    public function deleteFile($entity, $id, $field)
489
    {
490 1
        $crudData = $this->service->getData($entity);
491 1
        if (!$crudData) {
492 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
493
        }
494 1
        $instance = $crudData->get($id);
495 1
        if (!$instance) {
496 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_INSTANCE_NOT_FOUND));
497
        }
498 1
        $fileHandler = new FileHandler($this->filesystem, $crudData->getDefinition());
499 1
        if (!$crudData->getDefinition()->getField($field, 'required', false) && $fileHandler->deleteFile($crudData, $instance, $entity, $field)) {
500 1
            $instance->set($field, '');
501 1
            $crudData->update($instance);
502 1
            $this->session->getFlashBag()->add('success', $this->translator->trans('crudlex.file.deleted'));
503
        } else {
504 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.file.notDeleted'));
505
        }
506 1
        return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
507
    }
508
509
    /**
510
     * {@inheritdoc}
511
     */
512 1
    public function staticFile(Request $request)
513
    {
514 1
        $fileParam = str_replace('..', '', $request->get('file'));
515 1
        $file      = __DIR__.'/../static/'.$fileParam;
516 1
        if (!$fileParam || !file_exists($file)) {
517 1
            return $this->getNotFoundPage($this->translator->trans(static::TR_RESOURCE_NOT_FOUND));
518
        }
519
520 1
        $mimeType = MimeType::detectByFilename($file);
521 1
        $size     = filesize($file);
522
523 1
        $streamedFileResponse = new StreamedFileResponse();
524 1
        $response             = new StreamedResponse($streamedFileResponse->getStreamedFileFunction($file), 200, [
525 1
            'Content-Type' => $mimeType,
526 1
            'Content-Disposition' => 'attachment; filename="'.basename($file).'"',
527 1
            'Content-length' => $size
528
        ]);
529
530 1
        $response->setETag(filemtime($file))->setPublic()->isNotModified($request);
531 1
        $response->send();
532
533 1
        return $response;
534
    }
535
536
    /**
537
     * {@inheritdoc}
538
     */
539 1
    public function setLocale(Request $request, $locale)
540
    {
541
542 1
        if (!in_array($locale, $this->service->getLocales())) {
543 1
            return $this->getNotFoundPage('Locale '.$locale.' not found.');
544
        }
545
546 1
        $manageI18n = $this->service->isManageI18n();
547 1
        if ($manageI18n) {
548 1
            $this->session->set('locale', $locale);
549
        }
550 1
        $redirect = $request->get('redirect');
551 1
        return new RedirectResponse($redirect);
0 ignored issues
show
Security Cross-Site Scripting introduced by
$redirect can contain request data and is used in output context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: $this->parameters['HTTP_AUTHORIZATION'] seems to return tainted data, and $authorizationHeader is assigned in ServerBag.php on line 59
  1. $this->parameters['HTTP_AUTHORIZATION'] seems to return tainted data, and $authorizationHeader is assigned
    in vendor/ServerBag.php on line 59
  2. ParameterBag::$parameters is assigned
    in vendor/ServerBag.php on line 74
  3. Tainted property ParameterBag::$parameters is read
    in vendor/ParameterBag.php on line 77
  4. ParameterBag::get() returns tainted data, and $result is assigned
    in vendor/Request.php on line 707
  5. Request::get() returns tainted data, and $redirect is assigned
    in src/CRUDlex/Controller.php on line 550
  2. Path: Read from $_POST, and $_POST is passed to Request::createRequestFromFactory() in Request.php on line 293
  1. Read from $_POST, and $_POST is passed to Request::createRequestFromFactory()
    in vendor/Request.php on line 293
  2. $request is passed to Request::__construct()
    in vendor/Request.php on line 1988
  3. $request is passed to Request::initialize()
    in vendor/Request.php on line 247
  4. $request is passed to ParameterBag::__construct()
    in vendor/Request.php on line 265
  5. ParameterBag::$parameters is assigned
    in vendor/ParameterBag.php on line 28
  6. Tainted property ParameterBag::$parameters is read
    in vendor/ParameterBag.php on line 77
  7. ParameterBag::get() returns tainted data, and $result is assigned
    in vendor/Request.php on line 707
  8. Request::get() returns tainted data, and $redirect is assigned
    in src/CRUDlex/Controller.php on line 550

Used in output context

  1. RedirectResponse::__construct() uses RedirectResponse::setTargetUrl() ($url)
    in vendor/RedirectResponse.php on line 39
  2. RedirectResponse::setTargetUrl() uses Response::setContent() ($content)
    in vendor/RedirectResponse.php on line 92
  3. Response::setContent() uses property Response::$content for writing
    in vendor/Response.php on line 397
  4. Property Response::$content is used in echo
    in vendor/Response.php on line 356

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
552
    }
553
}
554