Issues (2)

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/Toolbox.php (1 issue)

Severity

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 smtech\StMarksReflexiveCanvasLTI;
4
5
use LTI_Tool_Consumer;
6
use LTI_Data_Connector;
7
8
use Battis\HierarchicalSimpleCache;
9
use Battis\DataUtilities;
10
use Battis\BootstrapSmarty\NotificationMessage;
11
12
use smtech\StMarksSmarty\StMarksSmarty;
13
use smtech\ReflexiveCanvasLTI\Exception\ConfigurationException;
14
15
/**
16
 * Add HTML templating and basic caching to the ReflexiveCanvasLTI Toolbox
17
 *
18
 * @author Seth Battis <[email protected]>
19
 * @version v0.1
20
 */
21
class Toolbox extends \smtech\ReflexiveCanvasLTI\Toolbox
22
{
23
24
    /**
25
     * Cache manager
26
     * @var HierarchicalSimpleCache
27
     */
28
    protected $cache;
29
30
    /**
31
     * St. Mark's-styled HTML templating
32
     * @var StMarksSmarty
33
     */
34
    protected $smarty;
35
36
    /**
37
     * Update a Toolbox instance from a configuration file
38
     *
39
     * Extends the inherited `Toolbox::loadConfiguration()` to add two
40
     * additional pieces of configuration metadata:
41
     *
42
     *   - `APP_PATH` is the path to the Tool Provider app
43
     *   - `APP_URL` is the URL of the Tool Provider app
44
     *
45
     * Also stores the API access token acquired by `interactiveGetAccessToken()`.
46
     *
47
     * @see interactiveGetAccessToken() `interactiveGetAccessToken()`
48
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/smtech/reflexive-canvas-lti/master/doc/classes/smtech.ReflexiveCanvasLTI.Toolbox.html#method_loadConfiguration `smtech\ReflexiveCanvasLTI\Toolbox::loadConfiguration()`
49
     *
50
     * @param string $configFilePath
51
     * @param boolean $forceRecache (Optional, default `false`)
52
     * @return void
53
     */
54
    protected function loadConfiguration($configFilePath, $forceRecache = false)
55
    {
56
        parent::loadConfiguration($configFilePath, $forceRecache);
57
58
        /* patch in passed back API access token, if present */
59
        if (!empty($_SESSION['TOOL_CANVAS_API'])) {
60
            $this->metadata['TOOL_CANVAS_API'] = $_SESSION['TOOL_CANVAS_API'];
61
            unset($_SESSION['TOOL_CANVAS_API']);
62
        }
63
64
        if ($forceRecache || empty($this->config('APP_PATH'))) {
65
            $this->config('APP_PATH', dirname($this->config('TOOL_CONFIG_FILE')));
66
        }
67
68
        if ($forceRecache || empty($this->config('APP_URL'))) {
69
            $this->config('APP_URL', DataUtilities::URLfromPath($this->config('APP_PATH')));
70
        }
71
    }
72
73
    /**
74
     * Interactively acquire an API access token
75
     *
76
     * `/config/canvas/key` and `/config/canvas/secret` must be defined in
77
     * `config.xml` for this to work!
78
     *
79
     * @param string $reason Explanation of why an API access token is necessary
80
     * @param string $redirectURL (Optional, defaults to
81
     *     `$_SERVER['REQUEST_URI']`) URL of page to redirect to after
82
     *     acquiring access token
83
     * @param string $errorURL (Optional) URL of page to redirect to on error
84
     * @return void
85
     */
86
    public function interactiveGetAccessToken($reason = null, $redirectURL = null, $errorURL = null)
87
    {
88
        $redirectURL = (
89
            empty($redirectURL) ?
90
                $_SERVER['REQUEST_URI'] :
91
                $redirectURL
92
        );
93
        $errorURL = (
94
            empty($errorURL) ?
95
                DataUtilities::URLfromPath(__DIR__ . '/../error.php') :
96
                $errorURL
97
        );
98
        $canvas = $this->metadata['TOOL_CANVAS_API'];
99
        if (!empty($canvas['key']) && !empty($canvas['secret'])) {
100
            /* if so, request an API access token interactively */
101
            if (session_status() !== PHP_SESSION_ACTIVE) {
102
                session_start();
103
            }
104
            $_SESSION['oauth'] = [
105
                'purpose' => $this->metadata['TOOL_NAME'],
106
                'key' => $canvas['key'],
107
                'secret' => $canvas['secret']
108
            ];
109
            header(
110
                'Location: ' . DataUtilities::URLfromPath(__DIR__ . '/../oauth.php') .
111
                '?' . http_build_query([
112
                    'oauth-return' => $redirectURL,
113
                    'oauth-error' => $errorURL,
114
                    'reason' => $reason
115
                ])
116
            );
117
            return;
118
        } else { /* no (understandable) API credentials available -- doh! */
119
            throw new ConfigurationException(
120
                'Missing OAuth key/secret pair in configuration, which is ' .
121
                'required to interactively acquire an API access token',
122
                ConfigurationException::CANVAS_API_MISSING
123
            );
124
        }
125
    }
126
127
    /**
128
     * Create a (potentially new) LTI_Tool_Consumer
129
     *
130
     * @param string $key (Optional)
131
     * @return LTI_Tool_Consumer
132
     */
133
    private function interactiveConsumersControlPanel_loadConsumer($key = null)
134
    {
135
        /*
136
         * load an existing consumer (if we have a consumer_key) or create a blank
137
         * that we will fill in
138
         */
139
        $consumer = new LTI_Tool_Consumer(
140
            (empty($key) ? LTI_Data_Connector::getRandomString(32) : $key),
141
            $this->getToolProvider()->data_connector,
142
            true // wicked confusing _not_ to autoenable
143
        );
144
145
        /* pre-fill secret if not editing an existing consumer */
146
        if (empty($key)) {
147
            $consumer->secret = LTI_Data_Connector::getRandomString(32);
148
        }
149
150
        return $consumer;
151
    }
152
153
    /**
154
     * Handle tool consumer management interactively
155
     *
156
     * Display and manage a control panel for managing Tool Consumers
157
     * interactively.
158
     *
159
     * @uses interactiveConsumersControlPanel_loadConsumer() `interactiveConsumersControlPanel_loadConsumer()`
160
     * @return void
161
     */
162
    public function interactiveConsumersControlPanel()
163
    {
164
        /* clean request values */
165
        $name = (empty($_POST['name']) ? null : trim($_POST['name']));
166
        $key = (empty($_POST['key']) ? null : trim($_POST['key']));
167
        $secret = (empty($_POST['secret']) ? null : trim($_POST['secret']));
168
        $enabled = (empty($_POST['enabled']) ? false : (boolean) $_POST['enabled']);
169
        $action = (empty($_POST['action']) ? false : strtolower(trim($_POST['action'])));
170
171
        /* load requested consumer (or create new if none requested) */
172
        $consumer = $this->interactiveConsumersControlPanel_loadConsumer($key);
173
174
        /* what are we asked to do with this consumer? */
175
        switch ($action) {
176
            case 'update':
177
            case 'insert':
178
                $consumer->name = $name;
179
                $consumer->secret = $secret;
180
                $consumer->enabled = $enabled;
181
                if (!$consumer->save()) {
182
                    $this->smarty_addMessage(
183
                        'Error saving consumer',
184
                        'There was an error attempting to save your new or ' .
185
                        'updated consumer information to the database.',
186
                        NotificationMessage::DANGER
187
                    );
188
                }
189
                break;
190
            case 'delete':
191
                $consumer->delete();
192
                break;
193
            case 'select':
194
                $this->smarty_assign('key', $key);
195
                break;
196
        }
197
198
        /*
199
         * if action was anything other than 'select', create a new empty
200
         * consumer to fill the form with
201
         */
202
        if ($action && $action !== 'select') {
203
            $consumer = $this->interactiveConsumersControlPanel_loadConsumer();
204
        }
205
206
        /* display a list of consumers */
207
        $consumers = $this->lti_getConsumers();
208
        $this->smarty_assign([
0 ignored issues
show
array('name' => 'Consume...s->metadata['APP_URL']) is of type array<string,?,{"name":"...ion":"?","appUrl":"?"}>, but the function expects a string.

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...
209
            'name' => 'Consumers',
210
            'category' => 'Control Panel',
211
            'consumers' => $consumers,
212
            'consumer' => $consumer,
213
            'formAction' => $_SERVER['PHP_SELF'],
214
            'appUrl' => $this->metadata['APP_URL']
215
        ]);
216
        $this->smarty_display('consumers-control-panel.tpl');
217
    }
218
219
    /**
220
     * Update the cache manager
221
     *
222
     * @param HierarchicalSimpleCache $cache
223
     */
224
    public function setCache(HierarchicalSimpleCache $cache)
225
    {
226
        $this->cache = $cache;
227
    }
228
229
    /**
230
     * Get the cache manager
231
     *
232
     * @return HierarchicalSimpleCache
233
     */
234
    public function getCache()
235
    {
236
        if (empty($this->cache)) {
237
            $this->cache = new HierarchicalSimpleCache($this->getMySQL(), basename(__FILE__, '.php'));
238
        }
239
        return $this->cache;
240
    }
241
242
    /**
243
     * Push a hierarchical layer to the cache
244
     *
245
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/simplecache/master/doc/classes/Battis.HierarchicalSimpleCache.html#method_pushKey Pass-through to `HierarchicalSimpleCache::pushKey()`
246
     *
247
     * @param  string $layer
248
     * @return string
249
     */
250
    public function cache_pushKey($layer)
251
    {
252
        return $this->getCache()->pushKey($layer);
253
    }
254
255
    /**
256
     * Pop a hierarchical layer off of the cache
257
     *
258
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/simplecache/master/doc/classes/Battis.HierarchicalSimpleCache.html#method_popKey Pass-through to `HierarchicalSimpleCache::popKey()`
259
     *
260
     * @return string|null
261
     */
262
    public function cache_popKey()
263
    {
264
        return $this->getCache()->popKey();
265
    }
266
267
    /**
268
     * Retrieve a cached value
269
     *
270
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/simplecache/master/doc/classes/Battis.HierarchicalSimpleCache.html#method_getCache Pass-through to `HierarchicalSimpleCache::getCache()`
271
     *
272
     * @param string $key
273
     * @return mixed
274
     */
275
    public function cache_get($key)
276
    {
277
        return $this->getCache()->getCache($key);
278
    }
279
280
    /**
281
     * Set a cached value
282
     *
283
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/simplecache/master/doc/classes/Battis.HierarchicalSimpleCache.html#method_setCache Pass-through to `HierarchicalSimpleCache::setCache()`
284
     *
285
     * @param string $key
286
     * @param mixed $data
287
     * @return boolean
288
     */
289
    public function cache_set($key, $data)
290
    {
291
        return $this->getCache()->setCache($key, $data);
292
    }
293
294
    /**
295
     * Update the HTML templating engine
296
     *
297
     * @param StMarksSmarty $smarty
298
     */
299
    public function setSmarty(StMarksSmarty $smarty)
300
    {
301
        $this->smarty = $smarty;
302
    }
303
304
    /**
305
     * Get the HTML templating engine
306
     *
307
     * @return StMarksSmarty
308
     */
309
    public function getSmarty()
310
    {
311
        if (empty($this->smarty)) {
312
            $this->smarty = StMarksSmarty::getSmarty();
313
            $this->smarty->prependTemplateDir(realpath(__DIR__ . '/../templates'), __CLASS__);
314
            $this->smarty->setFramed(true);
315
        }
316
        return $this->smarty;
317
    }
318
319
    /**
320
     * Assign a value to a template variables
321
     *
322
     * @link http://www.smarty.net/docs/en/api.assign.tpl Pass-through to `Smarty::assign()`
323
     *
324
     * @param string $varname
325
     * @param mixed $var
326
     * @param boolean $noCache (Optional, default `false`)
327
     * @return void
328
     */
329
    public function smarty_assign($varname, $var = null, $noCache = false)
330
    {
331
        return $this->getSmarty()->assign($varname, $var, $noCache);
332
    }
333
334
    /**
335
     * Register another template directory
336
     *
337
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/BootstrapSmarty/master/doc/classes/Battis.BootstrapSmarty.BootstrapSmarty.html#method_addTemplateDir Pass-through to `BootstrapSmarty::addTemplateDir()`
338
     *
339
     * @param string $template
340
     * @param string $key (Optional, default `null`)
341
     * @param boolean $isConfig (Optional, default `false`)
342
     */
343
    public function smarty_addTemplateDir($template, $key = null, $isConfig = false)
344
    {
345
        return $this->getSmarty()->addTemplateDir($template, $key, $isConfig);
346
    }
347
348
    /**
349
     * Prepend an over-riding template directory to Smarty
350
     *
351
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/BootstrapSmarty/master/doc/classes/Battis.BootstrapSmarty.BootstrapSmarty.html#method_prependTemplateDir Pass-through to `BootstrapSmarty::prependTemplateDir()`
352
     *
353
     * @param string $template
354
     * @param string $key (Optional)
355
     */
356
    public function smarty_prependTemplateDir($template, $key = null) {
357
        return $this->getSmarty()->prependTemplateDir($template, $key);
358
    }
359
360
    /**
361
     * Add a message to be displayed to the user
362
     *
363
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/BootstrapSmarty/master/doc/classes/Battis.BootstrapSmarty.BootstrapSmarty.html#method_addMessage Pass-through to `BootstrapSmarty::addMessage()`
364
     *
365
     * @param string $title
366
     * @param string $content
367
     * @param string $class (Optional, default `NotificationMessage::INFO`)
368
     */
369
    public function smarty_addMessage($title, $content, $class = NotificationMessage::INFO)
370
    {
371
        return $this->getSmarty()->addMessage($title, $content, $class);
372
    }
373
374
    /**
375
     * Display an HTML template
376
     *
377
     * @link https://htmlpreview.github.io/?https://raw.githubusercontent.com/battis/BootstrapSmarty/master/doc/classes/Battis.BootstrapSmarty.BootstrapSmarty.html#method_display Pass-through to `BootstrapSmarty::display()`
378
     *
379
     * @param string $template (Optional, default `page.tpl`)
380
     * @param string $cache_id (Optional, default `null`)
381
     * @param string $compile_id (Optional, default, `null`)
382
     * @param string $parent (Optional, default `null`)
383
     * @return void
384
     */
385
    public function smarty_display($template = 'page.tpl', $cache_id = null, $compile_id = null, $parent = null)
386
    {
387
        return $this->getSmarty()->display($template, $cache_id, $compile_id, $parent);
388
    }
389
}
390