GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (13)

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/SemaltBlocker/Blocker.php (5 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 Nabble\SemaltBlocker;
4
5
/**
6
 * The most important class for this package. Basic usage:
7
 * ```
8
 * Blocker::protect();
9
 * ```.
10
 */
11
class Blocker
12
{
13
    const SEPERATOR = ':';
14
15
    public static $explanation = "Access to this website has been blocked because your referral is set to %s. <a href='%s'>Read why</a>";
16
17
    private static $blocklist = './../../domains/blocked';
18
    private static $reason = 'Not blocking, no reason given';
19
20
    //////////////////////////////////////////
21
    // PUBLIC API                           //
22
    //////////////////////////////////////////
23
24
    /**
25
     * Block a page if referer is found on list of blocked domains.
26
     *
27
     * @param string $action If empty, send 403 response; if URL, redirect here; if non-empty string, print message
28
     */
29
    public static function protect($action = '')
30
    {
31
        // Try to update the list
32
        if (!defined('SEMALT_UNIT_TESTING')) {
33
            Updater::update();
34
        }
35
36
        // Simply stop here if referer is not on the list
37
        if (!self::isRefererOnBlocklist()) {
38
            return;
39
        }
40
41
        self::doBlock($action);
42
43
        // Stop execution altogether, bye bye bots
44
        if (!defined('SEMALT_UNIT_TESTING')) {
45
            exit;
46
        }
47
    }
48
49
    /**
50
     * @param bool $verbose Deprecated. Please use the explain() method instead.
51
     *
52
     * @return bool|string
53
     */
54
    public static function blocked($verbose = false)
55
    {
56
        $blocked = self::isRefererOnBlocklist();
57
        if ($verbose === true) {
58
            return self::$reason;
59
        }
60
61
        return $blocked;
62
    }
63
64
    /**
65
     * @return string
66
     */
67
    public static function explain()
68
    {
69
        return self::$reason;
70
    }
71
72
    /**
73
     * Send a 403 Forbidden header.
74
     */
75
    public static function forbidden()
76
    {
77
        $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
78
        header($protocol . ' 403 Forbidden');
79
    }
80
81
    /**
82
     * @return array
83
     */
84
    public static function getBlocklist()
85
    {
86
        return self::parseBlocklist(self::getBlocklistContents());
87
    }
88
89
    /**
90
     * @return string
91
     */
92
    public static function getBlocklistFilename()
93
    {
94
        return __DIR__ . DIRECTORY_SEPARATOR . static::$blocklist;
0 ignored issues
show
Since $blocklist is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $blocklist to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
95
    }
96
97
    //////////////////////////////////////////
98
    // PRIVATE FUNCTIONS                    //
99
    //////////////////////////////////////////
100
101
    /**
102
     * Responsible for sending action output.
103
     *
104
     * @param string $action
105
     */
106
    private static function doBlock($action = '')
107
    {
108
        // Clear buffered output
109
        if (!defined('SEMALT_UNIT_TESTING')) {
110
            self::cls();
111
        }
112
113
        // Take user defined action
114
        self::blockAction($action);
115
116
        // If a human comes by, don't just serve a blank page
117
        echo sprintf(self::$explanation, self::getHttpReferer(), 'https://www.google.com/#q=' . urlencode(preg_replace('/https?:\/\//', '', self::getHttpReferer()) . ' referral spam'));
118
    }
119
120
    /**
121
     * Execute desired action.
122
     *
123
     * @param string $action
124
     */
125
    private static function blockAction($action = '')
126
    {
127
        // Redirect or 403
128
        if (filter_var($action, FILTER_VALIDATE_URL)) {
129
            self::redirect($action);
130
        } else {
131
            self::forbidden();
132
            if (!empty($action)) {
133
                echo $action . '<br/>';
134
            } // tell them something nice
135
        }
136
    }
137
138
    /**
139
     * Clear output buffer.
140
     */
141
    private static function cls()
142
    {
143
        while (ob_get_level()) {
144
            ob_end_clean();
145
        }
146
    }
147
148
    /**
149
     * Redirect to a url by sending the appropriate header.
150
     *
151
     * @param string $url
152
     */
153
    private static function redirect($url)
154
    {
155
        header('Location: ' . $url);
156
    }
157
158
    /**
159
     * The public use of this function is undocumented.
160
     *
161
     * @return bool
162
     */
163
    public static function isRefererOnBlocklist()
164
    {
165
        $referer = self::getHttpReferer();
166
        if ($referer === null) {
167
            self::$reason = 'Not blocking because referer header is not set or empty';
168
169
            return false;
170
        }
171
172
        return self::isUrlOnBlocklist($referer, 'referer');
173
    }
174
175
    /**
176
     * The public use of this function is undocumented.
177
     *
178
     * @param string $url
179
     * @param string $entity
180
     *
181
     * @return bool
182
     */
183
    public static function isUrlOnBlocklist($url, $entity = 'url')
184
    {
185
        $rootDomain = Domainparser::getRootDomain($url);
186
        if ($rootDomain === false) {
187
            self::$reason = "Not blocking because we couldn't parse root domain";
188
189
            return false;
190
        }
191
192
        $blocklist = self::getConcatenateBlocklist();
193 View Code Duplication
        if (substr_count($blocklist, self::SEPERATOR . $rootDomain . self::SEPERATOR)) {
0 ignored issues
show
This code seems to be duplicated across 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...
194
            self::$reason = 'Blocking because ' . $entity . ' root domain (' . $rootDomain . ') is found on blocklist';
195
196
            return true;
197
        }
198
199
        $hostname = Domainparser::getHostname($url);
200 View Code Duplication
        if (substr_count($blocklist, self::SEPERATOR . $hostname . self::SEPERATOR)) {
0 ignored issues
show
This code seems to be duplicated across 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...
201
            self::$reason = 'Blocking because ' . $entity . ' hostname (' . $hostname . ') is found on blocklist';
202
203
            return true;
204
        }
205
206
        $path = Domainparser::getPath($url);
207
        if (trim($path, '/')) {
208 View Code Duplication
            if (substr_count($blocklist, self::SEPERATOR . $rootDomain . $path . self::SEPERATOR)) {
0 ignored issues
show
This code seems to be duplicated across 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...
209
                self::$reason = 'Blocking because ' . $entity . ' root domain/path (' . $rootDomain . $path . ') is found on blocklist';
210
211
                return true;
212
            }
213 View Code Duplication
            if (substr_count($blocklist, self::SEPERATOR . $hostname . $path . self::SEPERATOR)) {
0 ignored issues
show
This code seems to be duplicated across 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...
214
                self::$reason = 'Blocking because ' . $entity . ' hostname/path (' . $hostname . $path . ') is found on blocklist';
215
216
                return true;
217
            }
218
        }
219
220
        self::$reason = 'Not blocking because ' . $entity . ' (' . $url . ') is not matched against blocklist';
221
222
        return false;
223
    }
224
225
    /**
226
     * Returns HTTP Referer if it is available and not empty, null otherwise.
227
     *
228
     * @return string|null
229
     */
230
    private static function getHttpReferer()
231
    {
232
        if (isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER'])) {
233
            return $_SERVER['HTTP_REFERER'];
234
        }
235
    }
236
237
    /**
238
     * @return string
239
     */
240
    private static function getBlocklistContents()
241
    {
242
        $blocklistContent = file_get_contents(self::getBlocklistFilename());
243
244
        return $blocklistContent;
245
    }
246
247
    /**
248
     * @return string
249
     */
250
    private static function getConcatenateBlocklist()
251
    {
252
        return self::concatenateBlocklist(self::getBlocklistContents());
253
    }
254
255
    /**
256
     * @param string $blocklistContent
257
     *
258
     * @return array
259
     */
260
    private static function parseBlocklist($blocklistContent)
261
    {
262
        return array_map('trim', array_filter(explode(PHP_EOL, strtolower($blocklistContent))));
263
    }
264
265
    /**
266
     * @param string $blocklistContent
267
     *
268
     * @return string
269
     */
270
    private static function concatenateBlocklist($blocklistContent)
271
    {
272
        return self::SEPERATOR . str_replace(PHP_EOL, self::SEPERATOR, strtolower($blocklistContent)) . self::SEPERATOR;
273
    }
274
}
275