Issues (283)

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/ConsoleApplication.php (5 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 webmozart/console package.
5
 *
6
 * (c) Bernhard Schussek <[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 Webmozart\Console;
13
14
use Exception;
15
use LogicException;
16
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
17
use Webmozart\Assert\Assert;
18
use Webmozart\Console\Api\Application\Application;
19
use Webmozart\Console\Api\Args\Format\ArgsFormat;
20
use Webmozart\Console\Api\Args\RawArgs;
21
use Webmozart\Console\Api\Command\CannotAddCommandException;
22
use Webmozart\Console\Api\Command\Command;
23
use Webmozart\Console\Api\Command\CommandCollection;
24
use Webmozart\Console\Api\Config\ApplicationConfig;
25
use Webmozart\Console\Api\Config\CommandConfig;
26
use Webmozart\Console\Api\Event\ConfigEvent;
27
use Webmozart\Console\Api\Event\ConsoleEvents;
28
use Webmozart\Console\Api\Event\PreResolveEvent;
29
use Webmozart\Console\Api\IO\InputStream;
30
use Webmozart\Console\Api\IO\IO;
31
use Webmozart\Console\Api\IO\OutputStream;
32
use Webmozart\Console\Args\ArgvArgs;
33
use Webmozart\Console\IO\ConsoleIO;
34
use Webmozart\Console\UI\Component\ExceptionTrace;
35
36
/**
37
 * A console application.
38
 *
39
 * @since  1.0
40
 *
41
 * @author Bernhard Schussek <[email protected]>
42
 */
43
class ConsoleApplication implements Application
44
{
45
    /**
46
     * @var ApplicationConfig
47
     */
48
    private $config;
49
50
    /**
51
     * @var CommandCollection
52
     */
53
    private $commands;
54
55
    /**
56
     * @var CommandCollection
57
     */
58
    private $namedCommands;
59
60
    /**
61
     * @var CommandCollection
62
     */
63
    private $defaultCommands;
64
65
    /**
66
     * @var ArgsFormat
67
     */
68
    private $globalArgsFormat;
69
70
    /**
71
     * @var EventDispatcherInterface
72
     */
73
    private $dispatcher;
74
75
    /**
76
     * @var ConsoleIO
77
     */
78
    private $preliminaryIo;
79
80
    /**
81
     * Creates a new console application.
82
     *
83
     * @param ApplicationConfig|callable $config The application configuration
84
     *                                           or a callable that creates the
85
     *                                           configuration.
86
     */
87 138
    public function __construct($config)
88
    {
89 138
        $this->preliminaryIo = new ConsoleIO();
90
91
        // Enable trace output for exceptions thrown during boot
92 138
        $this->preliminaryIo->setVerbosity(IO::VERY_VERBOSE);
93
94 138
        if (is_callable($config)) {
95
            try {
96 1
                $config = $config();
97
            } catch (Exception $e) {
98
                $trace = new ExceptionTrace($e);
99
                $trace->render($this->preliminaryIo);
100
101
                exit($this->exceptionToExitCode($e->getCode()));
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
102
            }
103
        }
104
105 138
        Assert::isInstanceOf($config, 'Webmozart\Console\Api\Config\ApplicationConfig', 'The $config argument must be an ApplicationConfig or a callable. Got: %s');
106
107
        try {
108 137
            $dispatcher = $config->getEventDispatcher();
109
110 137
            if ($dispatcher && $dispatcher->hasListeners(ConsoleEvents::CONFIG)) {
111 1
                $dispatcher->dispatch(ConsoleEvents::CONFIG,
112 1
                    new ConfigEvent($config));
113
            }
114
115 137
            $this->config = $config;
116 137
            $this->dispatcher = $config->getEventDispatcher();
117 137
            $this->commands = new CommandCollection();
118 137
            $this->namedCommands = new CommandCollection();
119 137
            $this->defaultCommands = new CommandCollection();
120
121 137
            $this->globalArgsFormat = new ArgsFormat(array_merge(
122 137
                $config->getOptions(),
123 137
                $config->getArguments()
124
            ));
125
126 137
            foreach ($config->getCommandConfigs() as $commandConfig) {
127 137
                $this->addCommand($commandConfig);
128
            }
129 2
        } catch (Exception $e) {
130 2
            if (!$config->isExceptionCaught()) {
131 2
                throw $e;
132
            }
133
134
            // Render the trace to the preliminary IO
135
            $trace = new ExceptionTrace($e);
136
            $trace->render($this->preliminaryIo);
137
138
            // Ignore isTerminatedAfterRun() setting. This is a fatal error.
139
            exit($this->exceptionToExitCode($e->getCode()));
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
140
        }
141 135
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146 130
    public function getConfig()
147
    {
148 130
        return $this->config;
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154 130
    public function getGlobalArgsFormat()
155
    {
156 130
        return $this->globalArgsFormat;
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     */
162 76
    public function getCommand($name)
163
    {
164 76
        return $this->commands->get($name);
165
    }
166
167
    /**
168
     * {@inheritdoc}
169
     */
170 17
    public function getCommands()
171
    {
172 17
        return clone $this->commands;
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178 1
    public function hasCommand($name)
179
    {
180 1
        return $this->commands->contains($name);
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186 2
    public function hasCommands()
187
    {
188 2
        return !$this->commands->isEmpty();
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194 235
    public function getNamedCommands()
195
    {
196 235
        return $this->namedCommands;
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202 2
    public function hasNamedCommands()
203
    {
204 2
        return count($this->namedCommands) > 0;
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210 18
    public function getDefaultCommands()
211
    {
212 18
        return $this->defaultCommands;
213
    }
214
215
    /**
216
     * {@inheritdoc}
217
     */
218 2
    public function hasDefaultCommands()
219
    {
220 2
        return count($this->defaultCommands) > 0;
221
    }
222
223
    /**
224
     * {@inheritdoc}
225
     */
226 43
    public function resolveCommand(RawArgs $args)
227
    {
228 43 View Code Duplication
        if ($this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::PRE_RESOLVE)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229 32
            $event = new PreResolveEvent($args, $this);
230 32
            $this->dispatcher->dispatch(ConsoleEvents::PRE_RESOLVE, $event);
231
232 32
            if ($resolvedCommand = $event->getResolvedCommand()) {
233 9
                return $resolvedCommand;
234
            }
235
        }
236
237 34
        return $this->config->getCommandResolver()->resolveCommand($args, $this);
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243 42
    public function run(RawArgs $args = null, InputStream $inputStream = null, OutputStream $outputStream = null, OutputStream $errorStream = null)
244
    {
245
        // Render errors to the preliminary IO until the final IO is created
246 42
        $io = $this->preliminaryIo;
247
248
        try {
249 42
            if (null === $args) {
250
                $args = new ArgvArgs();
251
            }
252
253 42
            $ioFactory = $this->config->getIOFactory();
254
255 42
            if (null === $ioFactory) {
256 1
                throw new LogicException('The IO factory must be set.');
257
            }
258
259
            /** @var IO $io */
260 41
            $io = call_user_func($ioFactory, $this, $args, $inputStream, $outputStream, $errorStream);
261
262 41
            $resolvedCommand = $this->resolveCommand($args);
263 41
            $command = $resolvedCommand->getCommand();
264 41
            $parsedArgs = $resolvedCommand->getArgs();
265
266 41
            $statusCode = $command->handle($parsedArgs, $io);
0 ignored issues
show
$parsedArgs is of type object<Webmozart\Console\Api\Args\RawArgs>, but the function expects a object<Webmozart\Console\Api\Args\Args>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
267 5
        } catch (Exception $e) {
268 5
            if (!$this->config->isExceptionCaught()) {
269 2
                throw $e;
270
            }
271
272 3
            $trace = new ExceptionTrace($e);
273 3
            $trace->render($io);
274
275 3
            $statusCode = $this->exceptionToExitCode($e->getCode());
276
        }
277
278 40
        if ($this->config->isTerminatedAfterRun()) {
279
            exit($statusCode);
0 ignored issues
show
Coding Style Compatibility introduced by
The method run() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
280
        }
281
282 40
        return $statusCode;
283
    }
284
285
    /**
286
     * Converts an exception code to an exit code.
287
     *
288
     * @param int $code The exception code.
289
     *
290
     * @return int The exit code.
291
     */
292 3
    private function exceptionToExitCode($code)
293
    {
294 3
        if (!is_numeric($code)) {
295
            return 1;
296
        }
297
298 3
        return min(max((int) $code, 1), 255);
299
    }
300
301 121
    private function addCommand(CommandConfig $config)
302
    {
303 121
        if (!$config->isEnabled()) {
304 1
            return;
305
        }
306
307 121
        $this->validateCommandName($config);
308
309 120
        $command = new Command($config, $this);
310
311 120
        $this->commands->add($command);
312
313 120
        if ($config->isDefault()) {
314 83
            $this->defaultCommands->add($command);
315
        }
316
317 120
        if (!$config->isAnonymous()) {
318 119
            $this->namedCommands->add($command);
319
        }
320 120
    }
321
322 121
    private function validateCommandName(CommandConfig $config)
323
    {
324 121
        $name = $config->getName();
325
326 121
        if (!$name) {
327 1
            throw CannotAddCommandException::nameEmpty();
328
        }
329
330 120
        if ($this->commands->contains($name)) {
331 1
            throw CannotAddCommandException::nameExists($name);
332
        }
333 120
    }
334
}
335