Issues (1844)

Security Analysis    not enabled

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

  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.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  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.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  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.
  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.
  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.
  Header Injection
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.

vendor/composer/InstalledVersions.php (1 issue)

Labels
Severity
1
<?php
2
3
/*
4
 * This file is part of Composer.
5
 *
6
 * (c) Nils Adermann <[email protected]>
7
 *     Jordi Boggiano <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Composer;
14
15
use Composer\Autoload\ClassLoader;
16
use Composer\Semver\VersionParser;
17
18
/**
19
 * This class is copied in every Composer installed project and available to all
20
 *
21
 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
22
 *
23
 * To require its presence, you can require `composer-runtime-api ^2.0`
24
 */
25
class InstalledVersions
26
{
27
    /**
28
     * @var mixed[]|null
29
     * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
30
     */
31
    private static $installed;
32
33
    /**
34
     * @var bool|null
35
     */
36
    private static $canGetVendors;
37
38
    /**
39
     * @var array[]
40
     * @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
41
     */
42
    private static $installedByVendor = array();
43
44
    /**
45
     * Returns a list of all package names which are present, either by being installed, replaced or provided
46
     *
47
     * @return string[]
48
     * @psalm-return list<string>
49
     */
50
    public static function getInstalledPackages()
51
    {
52
        $packages = array();
53
        foreach (self::getInstalled() as $installed) {
54
            $packages[] = array_keys($installed['versions']);
55
        }
56
57
        if (1 === \count($packages)) {
58
            return $packages[0];
59
        }
60
61
        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
62
    }
63
64
    /**
65
     * Returns a list of all package names with a specific type e.g. 'library'
66
     *
67
     * @param  string   $type
68
     * @return string[]
69
     * @psalm-return list<string>
70
     */
71
    public static function getInstalledPackagesByType($type)
72
    {
73
        $packagesByType = array();
74
75
        foreach (self::getInstalled() as $installed) {
76
            foreach ($installed['versions'] as $name => $package) {
77
                if (isset($package['type']) && $package['type'] === $type) {
78
                    $packagesByType[] = $name;
79
                }
80
            }
81
        }
82
83
        return $packagesByType;
84
    }
85
86
    /**
87
     * Checks whether the given package is installed
88
     *
89
     * This also returns true if the package name is provided or replaced by another package
90
     *
91
     * @param  string $packageName
92
     * @param  bool   $includeDevRequirements
93
     * @return bool
94
     */
95
    public static function isInstalled($packageName, $includeDevRequirements = true)
96
    {
97
        foreach (self::getInstalled() as $installed) {
98
            if (isset($installed['versions'][$packageName])) {
99
                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
100
            }
101
        }
102
103
        return false;
104
    }
105
106
    /**
107
     * Checks whether the given package satisfies a version constraint
108
     *
109
     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
110
     *
111
     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
112
     *
113
     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
114
     * @param  string        $packageName
115
     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
0 ignored issues
show
The type Composer\Semver\VersionParser was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
116
     * @return bool
117
     */
118
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
119
    {
120
        $constraint = $parser->parseConstraints($constraint);
121
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
122
123
        return $provided->matches($constraint);
124
    }
125
126
    /**
127
     * Returns a version constraint representing all the range(s) which are installed for a given package
128
     *
129
     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
130
     * whether a given version of a package is installed, and not just whether it exists
131
     *
132
     * @param  string $packageName
133
     * @return string Version constraint usable with composer/semver
134
     */
135
    public static function getVersionRanges($packageName)
136
    {
137
        foreach (self::getInstalled() as $installed) {
138
            if (!isset($installed['versions'][$packageName])) {
139
                continue;
140
            }
141
142
            $ranges = array();
143
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
144
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
145
            }
146
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
147
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
148
            }
149
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
150
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
151
            }
152
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
153
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
154
            }
155
156
            return implode(' || ', $ranges);
157
        }
158
159
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
160
    }
161
162
    /**
163
     * @param  string      $packageName
164
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
165
     */
166
    public static function getVersion($packageName)
167
    {
168
        foreach (self::getInstalled() as $installed) {
169
            if (!isset($installed['versions'][$packageName])) {
170
                continue;
171
            }
172
173
            if (!isset($installed['versions'][$packageName]['version'])) {
174
                return null;
175
            }
176
177
            return $installed['versions'][$packageName]['version'];
178
        }
179
180
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
181
    }
182
183
    /**
184
     * @param  string      $packageName
185
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
186
     */
187
    public static function getPrettyVersion($packageName)
188
    {
189
        foreach (self::getInstalled() as $installed) {
190
            if (!isset($installed['versions'][$packageName])) {
191
                continue;
192
            }
193
194
            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
195
                return null;
196
            }
197
198
            return $installed['versions'][$packageName]['pretty_version'];
199
        }
200
201
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
202
    }
203
204
    /**
205
     * @param  string      $packageName
206
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
207
     */
208
    public static function getReference($packageName)
209
    {
210
        foreach (self::getInstalled() as $installed) {
211
            if (!isset($installed['versions'][$packageName])) {
212
                continue;
213
            }
214
215
            if (!isset($installed['versions'][$packageName]['reference'])) {
216
                return null;
217
            }
218
219
            return $installed['versions'][$packageName]['reference'];
220
        }
221
222
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
223
    }
224
225
    /**
226
     * @param  string      $packageName
227
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
228
     */
229
    public static function getInstallPath($packageName)
230
    {
231
        foreach (self::getInstalled() as $installed) {
232
            if (!isset($installed['versions'][$packageName])) {
233
                continue;
234
            }
235
236
            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
237
        }
238
239
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
240
    }
241
242
    /**
243
     * @return array
244
     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
245
     */
246
    public static function getRootPackage()
247
    {
248
        $installed = self::getInstalled();
249
250
        return $installed[0]['root'];
251
    }
252
253
    /**
254
     * Returns the raw installed.php data for custom implementations
255
     *
256
     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
257
     * @return array[]
258
     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
259
     */
260
    public static function getRawData()
261
    {
262
        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
263
264
        if (null === self::$installed) {
265
            // only require the installed.php file if this file is loaded from its dumped location,
266
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
267
            if (substr(__DIR__, -8, 1) !== 'C') {
268
                self::$installed = include __DIR__ . '/installed.php';
269
            } else {
270
                self::$installed = array();
271
            }
272
        }
273
274
        return self::$installed;
275
    }
276
277
    /**
278
     * Returns the raw data of all installed.php which are currently loaded for custom implementations
279
     *
280
     * @return array[]
281
     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
282
     */
283
    public static function getAllRawData()
284
    {
285
        return self::getInstalled();
286
    }
287
288
    /**
289
     * Lets you reload the static array from another file
290
     *
291
     * This is only useful for complex integrations in which a project needs to use
292
     * this class but then also needs to execute another project's autoloader in process,
293
     * and wants to ensure both projects have access to their version of installed.php.
294
     *
295
     * A typical case would be PHPUnit, where it would need to make sure it reads all
296
     * the data it needs from this class, then call reload() with
297
     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
298
     * the project in which it runs can then also use this class safely, without
299
     * interference between PHPUnit's dependencies and the project's dependencies.
300
     *
301
     * @param  array[] $data A vendor/composer/installed.php data set
302
     * @return void
303
     *
304
     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
305
     */
306
    public static function reload($data)
307
    {
308
        self::$installed = $data;
309
        self::$installedByVendor = array();
310
    }
311
312
    /**
313
     * @return array[]
314
     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
315
     */
316
    private static function getInstalled()
317
    {
318
        if (null === self::$canGetVendors) {
319
            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
320
        }
321
322
        $installed = array();
323
324
        if (self::$canGetVendors) {
325
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
326
                if (isset(self::$installedByVendor[$vendorDir])) {
327
                    $installed[] = self::$installedByVendor[$vendorDir];
328
                } elseif (is_file($vendorDir.'/composer/installed.php')) {
329
                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
330
                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
331
                        self::$installed = $installed[count($installed) - 1];
332
                    }
333
                }
334
            }
335
        }
336
337
        if (null === self::$installed) {
338
            // only require the installed.php file if this file is loaded from its dumped location,
339
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
340
            if (substr(__DIR__, -8, 1) !== 'C') {
341
                self::$installed = require __DIR__ . '/installed.php';
342
            } else {
343
                self::$installed = array();
344
            }
345
        }
346
        $installed[] = self::$installed;
347
348
        return $installed;
349
    }
350
}
351