Issues (35)

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.

debug/handlers/Error.php (3 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 namespace nyx\diagnostics\debug\handlers;
2
3
// Internal dependencies
4
use nyx\diagnostics\debug\exceptions;
5
use nyx\diagnostics\debug\interfaces;
6
use nyx\diagnostics\debug;
7
use nyx\diagnostics\definitions;
8
9
/**
10
 * Error Handler
11
 *
12
 * Converts errors of a severity equal to or above the given threshold into Exceptions for easier inspections
13
 * and more robust and cohesive handling. Does not modify any of the input data it gets (for instance, error
14
 * messages are left as is, so the Exception Handler can decide how to present them).
15
 *
16
 * Note: The internal error threshold {@see self::setThreshold()} can work decoupled from PHP's error_reporting()
17
 *       level. For instance, if PHP is set to report all errors but this handler's threshold is set to warnings,
18
 *       only warnings and higher levels of errors will get converted to exceptions. This handler *does not*
19
 *       automatically turn off PHP's display_errors ini directive, meaning that under the above circumstances
20
 *       all errors below warnings might get displayed by PHP's internal error handler unless you set the
21
 *       directive to 0 yourself.
22
 *
23
 * @package     Nyx\Diagnostics\Debug
24
 * @version     0.0.5
25
 * @author      Michal Chojnacki <[email protected]>
26
 * @copyright   2012-2016 Nyx Dev Team
27
 * @link        http://docs.muyo.io/nyx/diagnostics/debug.html
28
 */
29
class Error extends debug\Handler implements interfaces\handlers\Error, interfaces\handlers\FatalError
30
{
31
    /**
32
     * Used by various components (mostly logging facilities) to denote a userland deprecation notice without
33
     * actually throwing errors/exceptions (in a logging context etc.).
34
     */
35
    const DEPRECATION = -100;
36
37
    /**
38
     * @var int     The error severity required to convert an error into an Exception.
39
     */
40
    private $threshold;
41
42
    /**
43
     * @var int     The error severity this Handler has been initialized with.
44
     */
45
    private $initialThreshold;
46
47
    /**
48
     * Registers the given or a new Error Handler with PHP.
49
     *
50
     * @param   interfaces\handlers\Error   $handler    An optional, already instantiated Error handler instance.
51
     *                                                  If none is given, a new one will be instantiated.
52
     * @param   int                         $threshold  {@see self::setThreshold()} Will be ignored if you provide
53
     *                                                  your own Error Handler instance.
54
     * @return  Error                                   An instance of the error handler which got registered.
55
     *                                                  Either the same as the given one or if none was given,
56
     *                                                  a new instance.
57
     */
58
    public static function register(interfaces\handlers\Error $handler = null, $threshold = null)
59
    {
60
        // Use the given handler or instantiate a new one?
61
        $handler = $handler ?: new static($threshold);
62
63
        // Note: Utilizing the error_types parameter of set_error_handler would probably simplify this handler
64
        // a little bit (and make it perform better due to a cutdown on error_reporting() calls in cases with
65
        // lots of errors reported but ignored here due to being below threshold) but setting the threshold
66
        // on the fly would become unusable/less robust.
67
        set_error_handler([$handler, 'handle']);
68
69
        if ($handler instanceof interfaces\handlers\FatalError) {
70
            register_shutdown_function([$handler, 'onShutdown']);
71
        }
72
73
        return $handler;
74
    }
75
76
    /**
77
     * Constructs a new Error Handler instance.
78
     *
79
     * @param   int $threshold      {@see self::setThreshold()}.
80
     */
81
    public function __construct($threshold = null)
82
    {
83
        $this->setThreshold($threshold);
84
85
        // Keep track of the initial threshold so we can easily restore it later.
86
        $this->initialThreshold = $this->threshold;
87
    }
88
89
    /**
90
     * Returns the error severity required to convert an error into an Exception.
91
     *
92
     * @return  int
93
     */
94
    public function getThreshold()
95
    {
96
        return $this->threshold;
97
    }
98
99
    /**
100
     * Sets the error severity required to convert an error into an Exception.
101
     *
102
     * @param   int $threshold      The threshold. Passing null will make the handler use the current
103
     *                              error_reporting() level as reported by PHP. All non-null values will be
104
     *                              converted to integers.
105
     * @return  $this
106
     */
107
    public function setThreshold($threshold = null)
108
    {
109
        $this->threshold = null === $threshold ? error_reporting() : (int) $threshold;
110
111
        return $this;
112
    }
113
114
    /**
115
     * Sets the current threshold to the level this Handler has been initialized with.
116
     *
117
     * @return  $this
118
     */
119
    public function restoreThreshold()
120
    {
121
        return $this->setThreshold($this->initialThreshold);
122
    }
123
124
    /**
125
     * {@inheritDoc}
126
     *
127
     * Converts errors of a severity equal to or above the given threshold into Exceptions for easier inspections
128
     * and more robust and cohesive handling. Ignores errors which do not meed the thresholds and returns false
129
     * for those instead, letting PHP's internal error handling handle such a case.
130
     *
131
     * @throws  exceptions\Error    When the given error severity meets both the error_reporting() and internal
132
     *                              thresholds.
133
     */
134
    public function handle(int $type, string $message, string $file = null, int $line = null, array $context = []) : bool
135
    {
136
        // A threshold of 0 means the handler should ignore all errors.
137
        if (0 === $this->threshold) {
138
            return false;
139
        }
140
141
        // Make sure that the severity is included in the error_reporting level (the handler will get called for
142
        // nearly every error regardless of the error_reporting setting) and that it fits our threshold as well.
143
        if (error_reporting() & $type and $this->threshold & $type) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
144
145
            // We will construct an Exception but won't throw it yet. Conditions might prevent us from doing it.
146
            $exception = new exceptions\Error($message, 0, $type, $file, $line, $context);
147
148
            // Being Emitter Aware we are bound to comply to the Events Definition.
149
            // self::emitDebugEvent() will return false when no Emitter is present. Otherwise we'll get the
150
            // Exception after it's been processed by Event Listeners so we need to overwrite it here.
151
            if (null !== $response = $this->emitDebugEvent(definitions\Events::DEBUG_ERROR_BEFORE, $exception)) {
152
                $exception = $response;
153
            }
154
155
            // First of all run all Conditions. The method will return true if we are to prevent throwing
156
            // the Exception and since technically this Handler *somehow* handled the situation, we will return
157
            // true so PHP knows about it.
158
            if ($this->runConditions($exception)) {
159
                return true;
160
            }
161
162
            // Seems we weren't prevented, so let's do eet.
163
            throw $exception;
164
        }
165
166
        return false;
167
    }
168
169
    /**
170
     * {@inheritDoc}
171
     *
172
     * Attempts to catch the last error which occurred during script execution, convert it to an exception and
173
     * pass it to an Exception Handler that is known and usable by this class.
174
     *
175
     * @throws  exceptions\FatalError   When a fatal error meeting the threshold conditions has occurred.
176
     */
177
    public function onShutdown()
178
    {
179
        // Since this gets registered as a shutdown function, upon shutdown we need to check whether an error
180
        // actually occurred.
181
        if (null === $error = error_get_last()) {
182
            return;
183
        }
184
185
        // Even if the handler is set to ignore all errors, we are still going to kick in for the most fundamental
186
        // errors reported by PHP.
187
        if (0 === $this->threshold and !$this->isFatal($error['type'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
188
            return;
189
        }
190
191
        // Instead of directly coupling this with our own exception handler, we'll try to see if an exception handler
192
        // is already registered...
193
        $handler = set_exception_handler(null);
194
195
        // ... and then check if it's an instance of our own exception handler so that we can make use of it.
196
        // BTW Why isn't such a basic Exception Handler Interface a PSR yet?
197
        if (is_array($handler) && $handler[0] instanceof interfaces\handlers\Exception) {
198
199
            // We will construct an Exception as we need to pass it to our Conditions.
200
            $exception = new exceptions\FatalError($error['message'], 0, $error['type'], $error['file'], $error['line']);
201
202
            // Being Emitter Aware we are bound to comply to the Events Definition.
203
            // self::emitDebugEvent() will return false when no Emitter is present. Otherwise we'll get the
204
            // Exception after it's been processed by Event Listeners so we need to overwrite it here.
205
            if (false !== $response = $this->emitDebugEvent(definitions\Events::DEBUG_FATAL_ERROR_BEFORE, $exception)) {
206
                // Now, as per Events Definition, also emit a casual DEBUG_ERROR_BEFORE event. No need to check
207
                // for an Emitter now anymore, obviously.
208
                $exception = $this->emitDebugEvent(definitions\Events::DEBUG_ERROR_BEFORE, $response);
209
            }
210
211
            // Run the Conditions but ignore the PREVENT signal.
212
            $this->runConditions($exception);
213
214
            // Pass the Exception to the Exception Handler.
215
            /** @var interfaces\handlers\Exception[] $handler */
216
            $handler[0]->handle($exception);
0 ignored issues
show
It seems like $exception defined by $this->emitDebugEvent(\n...RROR_BEFORE, $response) on line 208 can be null; however, nyx\diagnostics\debug\in...ers\Exception::handle() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
217
        }
218
219
        exit;
220
    }
221
222
    /**
223
     * Determines if given error type is considered a fatal error.
224
     *
225
     * Note: E_RECOVERABLE_ERROR and E_PARSE should as of PHP7 be entirely converted to Throwables so they
226
     * should be caught by an Exception Handler directly instead of first going through an Error Handler
227
     * and being converted to an Error Exception, let alone a FatalError Exception. We still keep them here
228
     * for edge cases, however.
229
     *
230
     * @param   int     $type   The error type to check.
231
     * @return  bool
232
     */
233
    protected function isFatal($type)
234
    {
235
        return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_PARSE]);
236
    }
237
}
238