Issues (685)

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/Console/Installer.php (7 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
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link      http://cakephp.org CakePHP(tm) Project
12
 * @since     3.0.0
13
 * @license   http://www.opensource.org/licenses/mit-license.php MIT License
14
 */
15
namespace App\Console;
16
17
use Cake\Auth\DefaultPasswordHasher;
18
use Cake\Utility\Security;
19
use Composer\Script\Event;
20
use Exception;
21
22
/**
23
 * Provides installation hooks for when this application is installed via
24
 * composer. Customize this class to suit your needs.
25
 */
26
class Installer
27
{
28
29
    /**
30
     * Does some routine installation tasks so people don't have to.
31
     *
32
     * @param \Composer\Script\Event $event The composer event object.
33
     *
34
     * @return void
35
     */
36
    public static function postInstall(Event $event)
37
    {
38
        $io = $event->getIO();
39
40
        $rootDir = dirname(dirname(__DIR__));
41
        static::createAppConfig($rootDir, $io);
42
        static::createWritableDirectories($rootDir, $io);
43
        static::createRecaptchaConfig($rootDir, $io);
44
        static::createDatabaseConfig($rootDir, $io);
45
        static::createEmailConfig($rootDir, $io);
46
        static::setDatabaseName($rootDir, $io);
47
48
        // ask if the permissions should be changed
49
        if ($io->isInteractive()) {
50
            $validator = function ($arg) {
51
                if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
52
                    return $arg;
53
                }
54
                throw new Exception('This is not a valid answer. Please choose Y or n.');
55
            };
56
            $setFolderPermissions = $io->askAndValidate(
57
                '<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ',
58
                $validator,
59
                10,
60
                'Y'
61
            );
62
63
            if (in_array($setFolderPermissions, ['Y', 'y'])) {
64
                static::setFolderPermissions($rootDir, $io);
65
            }
66
        } else {
67
            static::setFolderPermissions($rootDir, $io);
68
        }
69
70
        $newKey = static::setSecuritySaltAndKey($rootDir, $io);
71
        static::setAccountPassword($rootDir, $io, $newKey);
72
73
        if (class_exists('\Cake\Codeception\Console\Installer')) {
74
            \Cake\Codeception\Console\Installer::customizeCodeceptionBinary($event);
75
        }
76
    }
77
78
    /**
79
     * Create the config/app.php file if it does not exist.
80
     *
81
     * @param string $dir The application's root directory.
82
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
83
     *
84
     * @return void
85
     */
86 View Code Duplication
    public static function createAppConfig($dir, $io)
0 ignored issues
show
This method seems to be duplicated in 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...
87
    {
88
        $appConfig = $dir . '/config/app.php';
89
        $defaultConfig = $dir . '/config/app.default.php';
90
        if (!file_exists($appConfig)) {
91
            copy($defaultConfig, $appConfig);
92
            $io->write('Created `config/app.php` file');
93
        }
94
    }
95
96
    /**
97
     * Create the config/database.php file if it does not exist.
98
     *
99
     * @param string $dir The application's root directory.
100
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
101
     *
102
     * @return void
103
     */
104 View Code Duplication
    public static function createDatabaseConfig($dir, $io)
0 ignored issues
show
This method seems to be duplicated in 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...
105
    {
106
        $databaseConfig = $dir . '/config/database.php';
107
        $defaultConfig = $dir . '/config/database.default.php';
108
        if (!file_exists($databaseConfig)) {
109
            copy($defaultConfig, $databaseConfig);
110
            $io->write('Created `config/database.php` file');
111
        }
112
    }
113
114
    /**
115
     * Create the config/email.php file if it does not exist.
116
     *
117
     * @param string $dir The application's root directory.
118
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
119
     *
120
     * @return void
121
     */
122 View Code Duplication
    public static function createEmailConfig($dir, $io)
0 ignored issues
show
This method seems to be duplicated in 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...
123
    {
124
        $databaseConfig = $dir . '/config/email.php';
125
        $defaultConfig = $dir . '/config/email.default.php';
126
        if (!file_exists($databaseConfig)) {
127
            copy($defaultConfig, $databaseConfig);
128
            $io->write('Created `config/email.php` file');
129
        }
130
    }
131
132
    /**
133
     * Create the `logs` and `tmp` directories.
134
     *
135
     * @param string $dir The application's root directory.
136
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
137
     * @return void
138
     */
139
    public static function createWritableDirectories($dir, $io)
140
    {
141
        $paths = [
142
            'logs',
143
            'tmp',
144
            'tmp/cache',
145
            'tmp/cache/models',
146
            'tmp/cache/persistent',
147
            'tmp/cache/views',
148
            'tmp/sessions',
149
            'tmp/tests'
150
        ];
151
152
        foreach ($paths as $path) {
153
            $path = $dir . '/' . $path;
154
            if (!file_exists($path)) {
155
                mkdir($path);
156
                $io->write('Created `' . $path . '` directory');
157
            }
158
        }
159
    }
160
161
    /**
162
     * Create the config/recaptcha.php file if it does not exist.
163
     *
164
     * @param string $dir The application's root directory.
165
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
166
     *
167
     * @return void
168
     */
169 View Code Duplication
    public static function createRecaptchaConfig($dir, $io)
0 ignored issues
show
This method seems to be duplicated in 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...
170
    {
171
        $appConfig = $dir . '/config/recaptcha.php';
172
        $defaultConfig = $dir . '/config/recaptcha.default.php';
173
        if (!file_exists($appConfig)) {
174
            copy($defaultConfig, $appConfig);
175
            $io->write('Created `config/recaptcha.php` file');
176
        }
177
    }
178
179
    /**
180
     * Set globally writable permissions on the "tmp" and "logs" directory.
181
     *
182
     * This is not the most secure default, but it gets people up and running quickly.
183
     *
184
     * @param string $dir The application's root directory.
185
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
186
     * @return void
187
     */
188
    public static function setFolderPermissions($dir, $io)
189
    {
190
        // Change the permissions on a path and output the results.
191
        $changePerms = function ($path, $perms, $io) {
192
            // Get permission bits from stat(2) result.
193
            $currentPerms = fileperms($path) & 0777;
194
            if (($currentPerms & $perms) == $perms) {
195
                return;
196
            }
197
198
            $res = chmod($path, $currentPerms | $perms);
199
            if ($res) {
200
                $io->write('Permissions set on ' . $path);
201
            } else {
202
                $io->write('Failed to set permissions on ' . $path);
203
            }
204
        };
205
206
        $walker = function ($dir, $perms, $io) use (&$walker, $changePerms) {
207
            $files = array_diff(scandir($dir), ['.', '..']);
208
            foreach ($files as $file) {
209
                $path = $dir . '/' . $file;
210
211
                if (!is_dir($path)) {
212
                    continue;
213
                }
214
215
                $changePerms($path, $perms, $io);
216
                $walker($path, $perms, $io);
217
            }
218
        };
219
220
        $worldWritable = bindec('0000000111');
221
        $walker($dir . '/tmp', $worldWritable, $io);
222
        $changePerms($dir . '/tmp', $worldWritable, $io);
223
        $changePerms($dir . '/logs', $worldWritable, $io);
224
    }
225
226
    /**
227
     * Set the datasources.default.database value in the application's config file.
228
     *
229
     * @param string $dir The application's root directory.
230
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
231
     *
232
     * @return void
233
     */
234
    public static function setDatabaseName($dir, $io)
235
    {
236
        $config = $dir . '/config/database.php';
237
        $content = file_get_contents($config);
238
239
        $databaseName = $io->ask('What is the database host ? ', 'localhost');
240
        $content = str_replace('__DATABASE_HOST__', $databaseName, $content, $count);
241
242
        $databaseName = $io->ask('What is the database name ? ', 'xeta_test');
243
        $content = str_replace('__DATABASE_NAME__', $databaseName, $content, $count);
244
245
        $databaseName = $io->ask('What is the database username ? ', 'xeta');
246
        $content = str_replace('__DATABASE_USERNAME__', $databaseName, $content, $count);
247
248
        $databaseName = $io->ask('What is the database password ? ', 'xeta');
249
        $content = str_replace('__DATABASE_PASSWORD__', $databaseName, $content, $count);
250
251
        if ($count == 0) {
0 ignored issues
show
It seems like you are loosely comparing $count of type integer|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
252
            $io->write('No Datasources.default.database placeholder to replace.');
253
254
            return;
255
        }
256
257
        $result = file_put_contents($config, $content);
258
        if ($result) {
259
            $io->write('Updated Datasources.default.database value in config/app.php');
260
261
            return;
262
        }
263
        $io->write('Unable to update Datasources.default.database value.');
264
    }
265
266
    /**
267
     * Set the security.salt value in the application's config file.
268
     *
269
     * @param string $dir The application's root directory.
270
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
271
     * @return void
272
     */
273
    public static function setSecuritySaltAndKey($dir, $io)
274
    {
275
        $config = $dir . '/config/app.php';
276
        $content = file_get_contents($config);
277
278
        $newKey = hash('sha256', Security::randomBytes(64));
279
        $securityKey = hash('sha256', Security::randomBytes(64));
280
281
        $content = str_replace('__SALT__', $newKey, $content, $count);
282
        $content = str_replace('__KEY__', $securityKey, $content, $count);
283
284
        if ($count == 0) {
0 ignored issues
show
It seems like you are loosely comparing $count of type integer|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
285
            $io->write('No Security.salt placeholder to replace.');
286
287
            return;
288
        }
289
290
        $result = file_put_contents($config, $content);
291
        if ($result) {
292
            $io->write('Updated Security.salt value in config/app.php');
293
294
            return $newKey;
295
        }
296
        $io->write('Unable to update Security.salt value.');
297
    }
298
299
    /**
300
     * Set up the admin and member password for the database.
301
     *
302
     * @param string $dir The application's root directory.
303
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
304
     * @param string $newKey The new security.salt.
305
     *
306
     * @return void
307
     */
308
    public static function setAccountPassword($dir, $io, $newKey = null)
309
    {
310
        if ($newKey == null) {
0 ignored issues
show
It seems like you are loosely comparing $newKey of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
311
            $io->write('The new Security.salt value is empty in config/Seeds/UsersSeed.php, can\'t set up the password.');
312
313
            return;
314
        }
315
316
        $database = $dir . '/config/Seeds/UsersSeed.php';
317
        $content = file_get_contents($database);
318
319
        $adminPass = 'administrator';
320
        $memberPass = 'testaccount';
321
322
        $hasher = new DefaultPasswordHasher();
323
324
        $replacement = [
325
            $hasher->hash($adminPass),
326
            $hasher->hash($memberPass),
327
        ];
328
329
        $search = [
330
            '__ADMINPASSWORD__',
331
            '__MEMBERPASSWORD__'
332
        ];
333
334
        $content = str_replace($search, $replacement, $content, $count);
335
336
        if ($count != 2) {
337
            $io->write('Error, there was no password to replace.');
338
339
            return;
340
        }
341
342
        $result = file_put_contents($database, $content);
343
344
        if ($result) {
345
            $io->write('Set up Admin & Member passwords successfully !');
346
347
            return;
348
        }
349
350
        $io->write('Unable to set up Admin & Member passwords.');
351
    }
352
}
353