Issues (569)

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/Common/TaskIO.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
2
3
namespace Robo\Common;
4
5
use Robo\Robo;
6
use Robo\TaskInfo;
7
use Consolidation\Log\ConsoleLogLevel;
8
use Psr\Log\LoggerAwareTrait;
9
use Psr\Log\LogLevel;
10
use Robo\Contract\ProgressIndicatorAwareInterface;
11
12
/**
13
 * Task input/output methods.  TaskIO is 'used' in BaseTask, so any
14
 * task that extends this class has access to all of the methods here.
15
 * printTaskInfo, printTaskSuccess, and printTaskError are the three
16
 * primary output methods that tasks are encouraged to use.  Tasks should
17
 * avoid using the IO trait output methods.
18
 */
19
trait TaskIO
20
{
21
    use LoggerAwareTrait;
22
    use ConfigAwareTrait;
23
    use VerbosityThresholdTrait;
24
25
    /**
26
     * @return null|\Psr\Log\LoggerInterface
27
     */
28
    public function logger()
29
    {
30
        // $this->logger should always be set in Robo core tasks.
31
        if ($this->logger) {
32
            return $this->logger;
33
        }
34
35
        // TODO: Remove call to Robo::logger() once maintaining backwards
36
        // compatibility with legacy external Robo tasks is no longer desired.
37
        if (!Robo::logger()) {
38
            return null;
39
        }
40
41
        static $gaveDeprecationWarning = false;
42
        if (!$gaveDeprecationWarning) {
43
            trigger_error('No logger set for ' . get_class($this) . '. Use $this->task(Foo::class) rather than new Foo() in loadTasks to ensure the builder can initialize task the task, or use $this->collectionBuilder()->taskFoo() if creating one task from within another.', E_USER_DEPRECATED);
44
            $gaveDeprecationWarning = true;
45
        }
46
        return Robo::logger();
47
    }
48
49
    /**
50
     * Print information about a task in progress.
51
     *
52
     * With the Symfony Console logger, NOTICE is displayed at VERBOSITY_VERBOSE
53
     * and INFO is displayed at VERBOSITY_VERY_VERBOSE.
54
     *
55
     * Robo overrides the default such that NOTICE is displayed at
56
     * VERBOSITY_NORMAL and INFO is displayed at VERBOSITY_VERBOSE.
57
     *
58
     * n.b. We should probably have printTaskNotice for our ordinary
59
     * output, and use printTaskInfo for less interesting messages.
60
     *
61
     * @param string $text
62
     * @param null|array $context
63
     */
64
    protected function printTaskInfo($text, $context = null)
65
    {
66
        // The 'note' style is used for both 'notice' and 'info' log levels;
67
        // However, 'notice' is printed at VERBOSITY_NORMAL, whereas 'info'
68
        // is only printed at VERBOSITY_VERBOSE.
69
        $this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context));
70
    }
71
72
    /**
73
     * Provide notification that some part of the task succeeded.
74
     *
75
     * With the Symfony Console logger, success messages are remapped to NOTICE,
76
     * and displayed in VERBOSITY_VERBOSE. When used with the Robo logger,
77
     * success messages are displayed at VERBOSITY_NORMAL.
78
     *
79
     * @param string $text
80
     * @param null|array $context
81
     */
82
    protected function printTaskSuccess($text, $context = null)
83
    {
84
        // Not all loggers will recognize ConsoleLogLevel::SUCCESS.
85
        // We therefore log as LogLevel::NOTICE, and apply a '_level'
86
        // override in the context so that this message will be
87
        // logged as SUCCESS if that log level is recognized.
88
        $context['_level'] = ConsoleLogLevel::SUCCESS;
89
        $this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context));
90
    }
91
92
    /**
93
     * Provide notification that there is something wrong, but
94
     * execution can continue.
95
     *
96
     * Warning messages are displayed at VERBOSITY_NORMAL.
97
     *
98
     * @param string $text
99
     * @param null|array $context
100
     */
101
    protected function printTaskWarning($text, $context = null)
102
    {
103
        $this->printTaskOutput(LogLevel::WARNING, $text, $this->getTaskContext($context));
104
    }
105
106
    /**
107
     * Provide notification that some operation in the task failed,
108
     * and the task cannot continue.
109
     *
110
     * Error messages are displayed at VERBOSITY_NORMAL.
111
     *
112
     * @param string $text
113
     * @param null|array $context
114
     */
115
    protected function printTaskError($text, $context = null)
116
    {
117
        $this->printTaskOutput(LogLevel::ERROR, $text, $this->getTaskContext($context));
118
    }
119
120
    /**
121
     * Provide debugging notification.  These messages are only
122
     * displayed if the log level is VERBOSITY_DEBUG.
123
     *
124
     * @param string$text
125
     * @param null|array $context
126
     */
127
    protected function printTaskDebug($text, $context = null)
128
    {
129
        $this->printTaskOutput(LogLevel::DEBUG, $text, $this->getTaskContext($context));
130
    }
131
132
    /**
133
     * @param string $level
134
     *   One of the \Psr\Log\LogLevel constant
135
     * @param string $text
136
     * @param null|array $context
137
     */
138
    protected function printTaskOutput($level, $text, $context)
139
    {
140
        if (!$this->verbosityMeetsThreshold()) {
141
            return;
142
        }
143
        $logger = $this->logger();
144
        if (!$logger) {
145
            return;
146
        }
147
        // Hide the progress indicator, if it is visible.
148
        $inProgress = $this->hideTaskProgress();
149
        $logger->log($level, $text, $this->getTaskContext($context));
150
        // After we have printed our log message, redraw the progress indicator.
151
        $this->showTaskProgress($inProgress);
152
    }
153
154
    /**
155
     * @return bool
156
     */
157
    protected function hideTaskProgress()
158
    {
159
        $inProgress = false;
160
        if ($this instanceof ProgressIndicatorAwareInterface) {
161
            $inProgress = $this->inProgress();
162
        }
163
164
        // If a progress indicator is running on this task, then we mush
165
        // hide it before we print anything, or its display will be overwritten.
166
        if ($inProgress) {
167
            $inProgress = $this->hideProgressIndicator();
0 ignored issues
show
It seems like hideProgressIndicator() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
168
        }
169
        return $inProgress;
170
    }
171
172
    /**
173
     * @param bool $inProgress
174
     */
175
    protected function showTaskProgress($inProgress)
176
    {
177
        if ($inProgress) {
178
            $this->restoreProgressIndicator($inProgress);
0 ignored issues
show
It seems like restoreProgressIndicator() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
179
        }
180
    }
181
182
    /**
183
     * Format a quantity of bytes.
184
     *
185
     * @param int $size
186
     * @param int $precision
187
     *
188
     * @return string
189
     */
190
    protected function formatBytes($size, $precision = 2)
191
    {
192
        if ($size === 0) {
193
            return 0;
194
        }
195
        $base = log($size, 1024);
196
        $suffixes = array('', 'k', 'M', 'G', 'T');
197
        return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
198
    }
199
200
    /**
201
     * Get the formatted task name for use in task output.
202
     * This is placed in the task context under 'name', and
203
     * used as the log label by Robo\Common\RoboLogStyle,
204
     * which is inserted at the head of log messages by
205
     * Robo\Common\CustomLogStyle::formatMessage().
206
     *
207
     * @param null|object $task
208
     *
209
     * @return string
210
     */
211
    protected function getPrintedTaskName($task = null)
212
    {
213
        if (!$task) {
214
            $task = $this;
215
        }
216
        return TaskInfo::formatTaskName($task);
0 ignored issues
show
It seems like $task can also be of type this<Robo\Common\TaskIO>; however, Robo\TaskInfo::formatTaskName() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
217
    }
218
219
    /**
220
     * @param null|array $context
221
     *
222
     * @return array
223
     *   Context information.
224
     */
225
    protected function getTaskContext($context = null)
226
    {
227
        if (!$context) {
228
            $context = [];
229
        }
230
        if (!is_array($context)) {
231
            $context = ['task' => $context];
232
        }
233
        if (!array_key_exists('task', $context)) {
234
            $context['task'] = $this;
235
        }
236
237
        return $context + TaskInfo::getTaskContext($context['task']);
238
    }
239
}
240