Issues (6)

Security Analysis    no request data  

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

  Cross-Site Scripting
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/Drest/Route/Matcher.php (1 issue)

Labels
Severity

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
 * This file is part of the Drest package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author Lee Davis
9
 * @copyright Copyright (c) Lee Davis <@leedavis81>
10
 * @link https://github.com/leedavis81/drest/blob/master/LICENSE
11
 * @license http://opensource.org/licenses/MIT The MIT X License (MIT)
12
 */
13
namespace Drest\Route;
14
15
use Drest\Mapping\RouteMetaData;
16
use DrestCommon\Request\Request;
17
18
19
/**
20
 * Class Matcher takes a request object and finds matching routes
21
 * @package Drest\Route
22
 */
23
class Matcher
24
{
25
26
    /**
27
     * The route meta data this matcher should operate on
28
     * @var RouteMetaData $routeMetaData
29
     */
30
    protected $routeMetaData;
31
32
    /**
33
     * Key-value array of URL parameter names
34
     * @var array $param_names
35
     */
36
    protected $param_names = [];
37
38
    /**
39
     * Key-value array of URL parameters with + at the end
40
     * @var array $param_names_path
41
     */
42
    protected $param_names_path = [];
43
44
    /**
45
     * Key-value array of URL parameters populated after a match has been successful
46
     * - or directly by using available setter
47
     * @var array $route_params
48
     */
49
    protected $route_params;
50
51
    /**
52
     * An index array of URL parameters that exist but didn't match a route pattern parameter
53
     * Eg: pattern: /user/:id+  with url: /user/1/some/additional/params.
54
     * The value id => 1 will go into $route_params
55
     * All the rest will go in here.
56
     * @var array $unmapped_route_params
57
     */
58
    protected $unmapped_route_params;
59
60
    /**
61
     * Route meta data to test a match on
62
     * @param RouteMetaData|null $routeMetaData
63
     */
64 30
    public function __construct(RouteMetaData $routeMetaData = null)
65
    {
66 30
        if (!is_null($routeMetaData))
67 30
        {
68 30
            $this->setRouteMetaData($routeMetaData);
69 30
        }
70 30
    }
71
72
    /**
73
     * Set the route meta data
74
     * @param RouteMetaData $routeMetaData
75
     */
76 30
    public function setRouteMetaData(RouteMetaData $routeMetaData)
77
    {
78 30
        $this->routeMetaData = $routeMetaData;
79 30
    }
80
81
    /**
82
     * Does this request match the route pattern
83
     * @param  Request $request
84
     * @param  boolean $matchVerb - Whether you want to match the route using the request HTTP verb
85
     *                            - useful for OPTIONS requests to provide route info
86
     * @param  string  $basePath  - add a base path to the route pattern
87
     * @return boolean $result
88
     */
89 30
    public function matches(Request $request, $matchVerb = true, $basePath = null)
90
    {
91
        // If we're matching the verb and we've defined them, ensure the method used is in our list of registered verbs
92 30
        if ($matchVerb &&
93 30
            $this->routeMetaData->usesHttpVerbs() &&
94 30
            !$this->methodIsInOurListOfAllowedVerbs($request->getHttpMethod())) {
95 28
            return false;
96
        }
97
98 29
        $patternAsRegex = $this->getMatchRegexPattern($basePath);
99
100
        //Cache URL params' names and values if this route matches the current HTTP request
101 29
        if (!preg_match('#^' . $patternAsRegex . '$#', $request->getPath(), $paramValues)) {
102 26
            return false;
103
        }
104
105
        // Process the param names and save them on the route params
106 27
        $this->processRouteParams($paramValues);
107
108
        // Check the route conditions
109 27
        if (!$this->routeConditionsAreValid())
110 27
        {
111
            return false;
112
        }
113
114 27
        return true;
115
    }
116
117
    /**
118
     * Get the determined route parameters
119
     * @return array
120
     */
121 27
    public function getRouteParams()
122
    {
123 27
        return $this->route_params;
124
    }
125
126
127
    /**
128
     * Get the param names
129
     * @return array
130
     */
131 27
    public function getParamNames()
132
    {
133 27
        return $this->param_names;
134
    }
135
136
    /**
137
     * Get the params names path
138
     * @return array
139
     */
140 27
    public function getParamNamesPath()
141
    {
142 27
        return $this->param_names_path;
143
    }
144
145
    /**
146
     * Get any unmapped route parameters
147
     * @return array $params
148
     */
149 27
    public function getUnmappedRouteParams()
150
    {
151 27
        return $this->unmapped_route_params;
152
    }
153
154
    /**
155
     * Get the regex pattern to match the request path
156
     * @param $basePath
157
     * @return string
158
     */
159 29
    protected function getMatchRegexPattern($basePath)
160
    {
161
        // Convert URL params into regex patterns, construct a regex for this route, init params
162 29
        $routePattern = (is_null($basePath))
163 29
            ? (string) $this->routeMetaData->getRoutePattern()
164 29
            : '/' . $basePath . '/' . ltrim((string) $this->routeMetaData->getRoutePattern(), '/');
165 29
        $patternAsRegex = preg_replace_callback(
166 29
            '#:([\w]+)\+?#',
167 29
            [$this, 'matchesCallback'],
168 29
            str_replace(')', ')?', $routePattern)
169 29
        );
170 29
        if (substr($this->routeMetaData->getRoutePattern(), -1) === '/') {
171
            $patternAsRegex .= '?';
172
        }
173 29
        return $patternAsRegex;
174
    }
175
176
177
    /**
178
     * Convert a URL parameter (e.g. ":id", ":id+") into a regular expression
179
     * @param array - url parameters
180
     * @return string - Regular expression for URL parameter
181
     */
182 28
    protected function matchesCallback($m)
183
    {
184 28
        $this->param_names[] = $m[1];
185
186 28
        if (substr($m[0], -1) === '+') {
187
            $this->param_names_path[$m[1]] = 1;
188
189
            return '(?P<' . $m[1] . '>.+)';
190
        }
191
192 28
        return '(?P<' . $m[1] . '>[^/]+)';
193
    }
194
195
    /**
196
     * Process the route names and add them as parameters
197
     * @param array $paramValues
198
     */
199 27
    protected function processRouteParams(array $paramValues)
200
    {
201 27
        foreach ($this->param_names as $name) {
202 11
            if (isset($paramValues[$name])) {
203 11
                if (isset($this->param_names_path[$name])) {
204
                    $parts = explode('/', urldecode($paramValues[$name]));
205
                    $this->route_params[$name] = array_shift($parts);
206
                    $this->unmapped_route_params = $parts;
207
                } else {
208 11
                    $this->route_params[$name] = urldecode($paramValues[$name]);
209
                }
210 11
            }
211 27
        }
212 27
    }
213
214
    /**
215
     * Are the given route conditions matching
216
     * @return bool
217
     */
218 27
    protected function routeConditionsAreValid()
219
    {
220 27
        foreach ($this->routeMetaData->getRouteConditions() as $key => $condition) {
0 ignored issues
show
The expression $this->routeMetaData->getRouteConditions() of type array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
221 3
            if (!preg_match('/^' . $condition . '$/', $this->route_params[$key])) {
222
                $this->param_names_path = $this->route_params = $this->unmapped_route_params = [];
223
                return false;
224
            }
225 27
        }
226 27
        return true;
227
    }
228
229
    /**
230
     * Ensure our method is in out list of allowed verbs
231
     * @param $httpMethod
232
     * @return bool
233
     */
234 28
    protected function methodIsInOurListOfAllowedVerbs($httpMethod)
235
    {
236 28
        if (!in_array($httpMethod, $this->routeMetaData->getVerbs())) {
237 28
            return false;
238
        }
239 25
        return true;
240
    }
241
}