Issues (32)

Security Analysis    not enabled

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/Whoops/Handler/PlainTextHandler.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
* Whoops - php errors for cool kids
4
* @author Filipe Dobreira <http://github.com/filp>
5
* Plaintext handler for command line and logs.
6
* @author Pierre-Yves Landuré <https://howto.biapy.com/>
7
*/
8
9
namespace Whoops\Handler;
10
11
use InvalidArgumentException;
12
use Psr\Log\LoggerInterface;
13
use Whoops\Exception\Frame;
14
15
/**
16
* Handler outputing plaintext error messages. Can be used
17
* directly, or will be instantiated automagically by Whoops\Run
18
* if passed to Run::pushHandler
19
*/
20
class PlainTextHandler extends Handler
21
{
22
    const VAR_DUMP_PREFIX = '   | ';
23
24
    /**
25
     * @var \Psr\Log\LoggerInterface
26
     */
27
    protected $logger;
28
29
    /**
30
     * @var callable
31
     */
32
    protected $dumper;
33
34
    /**
35
     * @var bool
36
     */
37
    private $addTraceToOutput = true;
38
39
    /**
40
     * @var bool|integer
41
     */
42
    private $addTraceFunctionArgsToOutput = false;
43
44
    /**
45
     * @var integer
46
     */
47
    private $traceFunctionArgsOutputLimit = 1024;
48
49
    /**
50
     * @var bool
51
     */
52
    private $addPreviousToOutput = true;
53
54
    /**
55
     * @var bool
56
     */
57
    private $loggerOnly = false;
58
59
    /**
60
     * Constructor.
61
     * @throws InvalidArgumentException     If argument is not null or a LoggerInterface
62
     * @param  \Psr\Log\LoggerInterface|null $logger
63
     */
64 3
    public function __construct($logger = null)
65
    {
66 3
        $this->setLogger($logger);
67 2
    }
68
69
    /**
70
     * Set the output logger interface.
71
     * @throws InvalidArgumentException     If argument is not null or a LoggerInterface
72
     * @param  \Psr\Log\LoggerInterface|null $logger
73
     */
74 4
    public function setLogger($logger = null)
75
    {
76 4
        if (! (is_null($logger)
77 4
            || $logger instanceof LoggerInterface)) {
78 2
            throw new InvalidArgumentException(
79 2
                'Argument to ' . __METHOD__ .
80 2
                " must be a valid Logger Interface (aka. Monolog), " .
81 2
                get_class($logger) . ' given.'
82 2
            );
83
        }
84
85 3
        $this->logger = $logger;
86 3
    }
87
88
    /**
89
     * @return \Psr\Log\LoggerInterface|null
90
     */
91 2
    public function getLogger()
92
    {
93 2
        return $this->logger;
94
    }
95
96
    /**
97
     * Set var dumper callback function.
98
     *
99
     * @param  callable $dumper
100
     * @return static
101
     */
102
    public function setDumper(callable $dumper)
103
    {
104
        $this->dumper = $dumper;
105
        return $this;
106
    }
107
108
    /**
109
     * Add error trace to output.
110
     * @param  bool|null  $addTraceToOutput
111
     * @return bool|static
112
     */
113 6
    public function addTraceToOutput($addTraceToOutput = null)
114
    {
115 6
        if (func_num_args() == 0) {
116 6
            return $this->addTraceToOutput;
117
        }
118
119 6
        $this->addTraceToOutput = (bool) $addTraceToOutput;
120 6
        return $this;
121
    }
122
123
    /**
124
     * Add previous exceptions to output.
125
     * @param  bool|null $addPreviousToOutput
126
     * @return bool|static
127
     */
128 2
    public function addPreviousToOutput($addPreviousToOutput = null)
129
    {
130 2
        if (func_num_args() == 0) {
131
            return $this->addPreviousToOutput;
132
        }
133
134 2
        $this->addPreviousToOutput = (bool) $addPreviousToOutput;
135 2
        return $this;
136
    }
137
138
    /**
139
     * Add error trace function arguments to output.
140
     * Set to True for all frame args, or integer for the n first frame args.
141
     * @param  bool|integer|null $addTraceFunctionArgsToOutput
142
     * @return static|bool|integer
143
     */
144 4
    public function addTraceFunctionArgsToOutput($addTraceFunctionArgsToOutput = null)
145
    {
146 4
        if (func_num_args() == 0) {
147 2
            return $this->addTraceFunctionArgsToOutput;
148
        }
149
150 4
        if (! is_integer($addTraceFunctionArgsToOutput)) {
151 3
            $this->addTraceFunctionArgsToOutput = (bool) $addTraceFunctionArgsToOutput;
152 3
        } else {
153 2
            $this->addTraceFunctionArgsToOutput = $addTraceFunctionArgsToOutput;
154
        }
155 4
        return $this;
156
    }
157
158
    /**
159
     * Set the size limit in bytes of frame arguments var_dump output.
160
     * If the limit is reached, the var_dump output is discarded.
161
     * Prevent memory limit errors.
162
     * @var integer
163
     * @return static
164
     */
165 3
    public function setTraceFunctionArgsOutputLimit($traceFunctionArgsOutputLimit)
166
    {
167 3
        $this->traceFunctionArgsOutputLimit = (integer) $traceFunctionArgsOutputLimit;
168 3
        return $this;
169
    }
170
171
    /**
172
     * Create plain text response and return it as a string
173
     * @return string
174
     */
175 2
    public function generateResponse()
176
    {
177 2
        $exception = $this->getException();
178 2
        $message = $this->getExceptionOutput($exception);
179
180 2
        if ($this->addPreviousToOutput) {
181 1
            $previous = $exception->getPrevious();
182 1
            while ($previous) {
183 1
                $message .= "\n\nCaused by\n" . $this->getExceptionOutput($previous);
184 1
                $previous = $previous->getPrevious();
185 1
            }
186 1
        }
187
188
189 2
        return $message . $this->getTraceOutput() . "\n";
190
    }
191
192
    /**
193
     * Get the size limit in bytes of frame arguments var_dump output.
194
     * If the limit is reached, the var_dump output is discarded.
195
     * Prevent memory limit errors.
196
     * @return integer
197
     */
198 1
    public function getTraceFunctionArgsOutputLimit()
199
    {
200 1
        return $this->traceFunctionArgsOutputLimit;
201
    }
202
203
    /**
204
     * Only output to logger.
205
     * @param  bool|null $loggerOnly
206
     * @return static|bool
207
     */
208 3
    public function loggerOnly($loggerOnly = null)
209
    {
210 3
        if (func_num_args() == 0) {
211 3
            return $this->loggerOnly;
212
        }
213
214 3
        $this->loggerOnly = (bool) $loggerOnly;
215 3
        return $this;
216
    }
217
218
    /**
219
     * Test if handler can output to stdout.
220
     * @return bool
221
     */
222 4
    private function canOutput()
223
    {
224 4
        return !$this->loggerOnly();
225
    }
226
227
    /**
228
     * Get the frame args var_dump.
229
     * @param  \Whoops\Exception\Frame $frame [description]
230
     * @param  integer                 $line  [description]
231
     * @return string
232
     */
233 1
    private function getFrameArgsOutput(Frame $frame, $line)
234
    {
235 1
        if ($this->addTraceFunctionArgsToOutput() === false
236 1
            || $this->addTraceFunctionArgsToOutput() < $line) {
237 1
            return '';
238
        }
239
240
        // Dump the arguments:
241 1
        ob_start();
242 1
        $this->dump($frame->getArgs());
243 1
        if (ob_get_length() > $this->getTraceFunctionArgsOutputLimit()) {
244
            // The argument var_dump is to big.
245
            // Discarded to limit memory usage.
246
            ob_clean();
247
            return sprintf(
248
                "\n%sArguments dump length greater than %d Bytes. Discarded.",
249
                self::VAR_DUMP_PREFIX,
250
                $this->getTraceFunctionArgsOutputLimit()
251
            );
252
        }
253
254 1
        return sprintf(
255 1
            "\n%s",
256 1
            preg_replace('/^/m', self::VAR_DUMP_PREFIX, ob_get_clean())
257 1
        );
258
    }
259
260
    /**
261
     * Dump variable.
262
     *
263
     * @param mixed $var
264
     * @return void
265
     */
266
    protected function dump($var)
267
    {
268
        if ($this->dumper) {
269
            call_user_func($this->dumper, $var);
270
        } else {
271
            var_dump($var);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($var); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
272
        }
273
    }
274
275
    /**
276
     * Get the exception trace as plain text.
277
     * @return string
278
     */
279 4
    private function getTraceOutput()
280
    {
281 4
        if (! $this->addTraceToOutput()) {
282 2
            return '';
283
        }
284 2
        $inspector = $this->getInspector();
285 2
        $frames = $inspector->getFrames();
286
287 2
        $response = "\nStack trace:";
288
289 2
        $line = 1;
290 2
        foreach ($frames as $frame) {
291
            /** @var Frame $frame */
292 2
            $class = $frame->getClass();
293
294 2
            $template = "\n%3d. %s->%s() %s:%d%s";
295 2
            if (! $class) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
296
                // Remove method arrow (->) from output.
297
                $template = "\n%3d. %s%s() %s:%d%s";
298
            }
299
300 2
            $response .= sprintf(
301 2
                $template,
302 2
                $line,
303 2
                $class,
304 2
                $frame->getFunction(),
305 2
                $frame->getFile(),
306 2
                $frame->getLine(),
307 2
                $this->getFrameArgsOutput($frame, $line)
308 2
            );
309
310 2
            $line++;
311 2
        }
312
313 2
        return $response;
314
    }
315
316
    /**
317
     * Get the exception as plain text.
318
     * @param \Throwable $exception
319
     * @return string
320
     */
321 2
    private function getExceptionOutput($exception)
322
    {
323 2
        return sprintf(
324 2
            "%s: %s in file %s on line %d",
325 2
            get_class($exception),
326 2
            $exception->getMessage(),
327 2
            $exception->getFile(),
328 2
            $exception->getLine()
329 2
        );
330
    }
331
332
    /**
333
     * @return int
334
     */
335 5
    public function handle()
336
    {
337 5
        $response = $this->generateResponse();
338
339 5
        if ($this->getLogger()) {
340
            $this->getLogger()->error($response);
341
        }
342
343 5
        if (! $this->canOutput()) {
344
            return Handler::DONE;
345
        }
346
347 5
        echo $response;
348
349 5
        return Handler::QUIT;
350
    }
351
352
    /**
353
     * @return string
354
     */
355 2
    public function contentType()
356
    {
357 2
        return 'text/plain';
358
    }
359
}
360