This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 Superdesk Web Publisher Core Bundle. |
||
5 | * |
||
6 | * Copyright 2015 Sourcefabric z.u. and contributors. |
||
7 | * |
||
8 | * For the full copyright and license information, please see the |
||
9 | * AUTHORS and LICENSE files distributed with this source code. |
||
10 | * |
||
11 | * @copyright 2015 Sourcefabric z.ú |
||
12 | * @license http://www.superdesk.org/license |
||
13 | */ |
||
14 | |||
15 | namespace SWP\Bundle\CoreBundle\Controller; |
||
16 | |||
17 | use Hoa\File\Read; |
||
18 | use Hoa\Mime\Mime; |
||
19 | use Sylius\Bundle\ThemeBundle\HierarchyProvider\ThemeHierarchyProviderInterface; |
||
20 | use Symfony\Component\Routing\Annotation\Route; |
||
21 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
||
22 | use Symfony\Component\HttpFoundation\Response; |
||
23 | use Symfony\Component\HttpFoundation\ResponseHeaderBag; |
||
24 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
||
25 | |||
26 | class StaticThemeAssetsController extends Controller |
||
0 ignored issues
–
show
|
|||
27 | { |
||
28 | /** |
||
29 | * Directory with assets inside theme. |
||
30 | */ |
||
31 | const ASSETS_DIRECTORY = 'public'; |
||
32 | |||
33 | /** |
||
34 | * @Route("/{fileName}.{fileExtension}", methods={"GET"}, name="static_theme_assets_root", requirements={"fileName": "sw|manifest|favicon|ads|OneSignalSDKWorker|OneSignalSDKUpdaterWorker|amp-web-push-helper-frame|amp-web-push-permission-dialog"}) |
||
35 | * @Route("/public-{fileName}.{fileExtension}", methods={"GET"}, name="static_theme_assets_root_public", requirements={"fileName"=".+"}) |
||
36 | * @Route("/public/{fileName}.{fileExtension}", methods={"GET"}, name="static_theme_assets_public", requirements={"fileName"=".+"}) |
||
37 | */ |
||
38 | public function rootAction($fileName, $fileExtension) |
||
39 | 1 | { |
|
40 | $themes = $this->get(ThemeHierarchyProviderInterface::class)->getThemeHierarchy( |
||
41 | 1 | $this->get('swp_core.theme.context.tenant_aware')->getTheme() |
|
42 | 1 | ); |
|
43 | 1 | ||
44 | 1 | $fileName = (null === $fileExtension) ? basename($fileName) : $fileName.'.'.$fileExtension; |
|
45 | foreach ($themes as $theme) { |
||
46 | $filePath = $theme->getPath().'/'.self::ASSETS_DIRECTORY.'/'.$fileName; |
||
47 | if (null !== $response = $this->handleFileLoading($filePath)) { |
||
48 | return $response; |
||
49 | } |
||
50 | } |
||
51 | |||
52 | throw new NotFoundHttpException('File was not found.'); |
||
53 | } |
||
54 | 1 | ||
55 | /** |
||
56 | 1 | * @Route("/themes/{type}/{themeName}/screenshots/{fileName}", methods={"GET"}, name="static_theme_screenshots", requirements={ |
|
57 | 1 | * "type": "organization|tenant" |
|
58 | 1 | * }) |
|
59 | 1 | */ |
|
60 | public function screenshotsAction(string $type, string $themeName, $fileName) |
||
61 | { |
||
62 | 1 | if ('organization' === $type) { |
|
63 | $theme = $this->loadOrganizationTheme(str_replace('__', '/', $themeName)); |
||
64 | } elseif ('tenant' === $type) { |
||
65 | $theme = $this->loadTenantTheme(str_replace('__', '/', $themeName)); |
||
66 | } else { |
||
67 | throw new NotFoundHttpException('File was not found.'); |
||
68 | } |
||
69 | |||
70 | 2 | $filePath = $theme->getPath().'/screenshots/'.$fileName; |
|
71 | if (null !== $response = $this->handleFileLoading($filePath)) { |
||
72 | 2 | return $response; |
|
73 | 2 | } |
|
74 | 2 | ||
75 | 2 | throw new NotFoundHttpException('File was not found.'); |
|
76 | } |
||
77 | |||
78 | 2 | /** |
|
79 | 2 | * @param $filePath |
|
80 | 2 | * |
|
81 | 2 | * @return Response |
|
82 | 2 | */ |
|
83 | private function handleFileLoading($filePath) |
||
84 | 2 | { |
|
85 | if (file_exists($filePath)) { |
||
86 | 1 | $response = new Response(file_get_contents($filePath)); |
|
0 ignored issues
–
show
$filePath can contain request data and is used in file inclusion context(s) leading to a potential security vulnerability.
2 paths for user data to reach this point
1. Path:
Entered via action parameter
$fileName
in src/SWP/Bundle/CoreBundle/Controller/StaticThemeAssetsController.php on line 38
2. Path:
Entered via action parameter
$fileName
in src/SWP/Bundle/CoreBundle/Controller/StaticThemeAssetsController.php on line 60
General Strategies to prevent injectionIn 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;
![]() Security
Cross-Site Scripting
introduced
by
file_get_contents($filePath) 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:
Entered via action parameter
$fileName
in src/SWP/Bundle/CoreBundle/Controller/StaticThemeAssetsController.php on line 38
2. Path:
Entered via action parameter
$fileName
in src/SWP/Bundle/CoreBundle/Controller/StaticThemeAssetsController.php on line 60
Used in output context
Preventing Cross-Site-Scripting AttacksCross-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 injectionIn 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;
![]() |
|||
87 | $disposition = $response->headers->makeDisposition( |
||
88 | ResponseHeaderBag::DISPOSITION_INLINE, |
||
89 | basename($filePath) |
||
90 | ); |
||
91 | $response->headers->set('Content-Disposition', $disposition); |
||
92 | |||
93 | try { |
||
94 | $type = new Mime(new Read($filePath)); |
||
95 | $mime = str_replace('/x-', '/', Mime::getMimeFromExtension($type->getExtension())); |
||
96 | } catch (\Exception $e) { |
||
97 | $mime = 'text/plain'; |
||
98 | } |
||
99 | |||
100 | $response->headers->set('Content-Type', $mime); |
||
101 | $response->setStatusCode(Response::HTTP_OK); |
||
102 | $response->setPublic(); |
||
103 | $response->setMaxAge(3600); |
||
104 | $response->setSharedMaxAge(7200); |
||
105 | |||
106 | return $response; |
||
107 | } |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * @param string $themeName |
||
112 | * |
||
113 | * @return mixed |
||
114 | */ |
||
115 | private function loadOrganizationTheme(string $themeName) |
||
116 | { |
||
117 | $loadedThemes = $this->get('swp_core.loader.organization.theme')->load(); |
||
118 | |||
119 | return $this->filterThemes($loadedThemes, $themeName); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * @param string $themeName |
||
124 | * |
||
125 | * @return mixed |
||
126 | */ |
||
127 | private function loadTenantTheme(string $themeName) |
||
128 | { |
||
129 | $loadedThemes = $this->get('sylius.repository.theme')->findAll(); |
||
130 | |||
131 | return $this->filterThemes($loadedThemes, $themeName); |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * @param array $loadedThemes |
||
136 | * @param string $themeName |
||
137 | * |
||
138 | * @return mixed |
||
139 | */ |
||
140 | private function filterThemes($loadedThemes, string $themeName) |
||
141 | { |
||
142 | $themes = array_filter( |
||
143 | $loadedThemes, |
||
144 | function ($element) use (&$themeName) { |
||
145 | return $element->getName() === $themeName; |
||
146 | } |
||
147 | ); |
||
148 | |||
149 | if (0 === count($themes)) { |
||
150 | throw new NotFoundHttpException(sprintf('Theme with name "%s" was not found in organization themes.', $themeName)); |
||
151 | } |
||
152 | |||
153 | return reset($themes); |
||
154 | } |
||
155 | } |
||
156 |
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.