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 (5)

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

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 Spatie\SslCertificate;
4
5
use Carbon\Carbon;
6
use Spatie\Macroable\Macroable;
7
8
class SslCertificate
9
{
10
    use Macroable;
11
12
    /** @var array */
13
    protected $rawCertificateFields = [];
14
15
    /** @var string */
16
    protected $fingerprint = '';
17
18
    /** @var string */
19
    private $fingerprintSha256 = '';
20
21
    /** @var string */
22
    private $remoteAddress = '';
23
24
    public static function download(): Downloader
25
    {
26
        return new Downloader();
27
    }
28
29
    public static function createForHostName(string $url, int $timeout = 30): self
30
    {
31
        return Downloader::downloadCertificateFromUrl($url, $timeout);
32
    }
33
34
    public static function createFromFile(string $pathToCertificate): self
35
    {
36
        return self::createFromString(file_get_contents($pathToCertificate));
37
    }
38
39 View Code Duplication
    public static function createFromString(string $certificatePem): self
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...
40
    {
41
        $certificateFields = openssl_x509_parse($certificatePem);
42
43
        $fingerprint = openssl_x509_fingerprint($certificatePem);
44
        $fingerprintSha256 = openssl_x509_fingerprint($certificatePem, 'sha256');
45
46
        return new self(
47
            $certificateFields,
48
            $fingerprint,
49
            $fingerprintSha256
50
        );
51
    }
52
53
    public function __construct(
54
        array $rawCertificateFields,
55
        string $fingerprint = '',
56
        string $fingerprintSha256 = '',
57
        string $remoteAddress = ''
58
    ) {
59
        $this->rawCertificateFields = $rawCertificateFields;
60
61
        $this->fingerprint = $fingerprint;
62
63
        $this->fingerprintSha256 = $fingerprintSha256;
64
65
        $this->remoteAddress = $remoteAddress;
66
    }
67
68
    public function getRawCertificateFields(): array
69
    {
70
        return $this->rawCertificateFields;
71
    }
72
73
    public function getIssuer(): string
74
    {
75
        return $this->rawCertificateFields['issuer']['CN'] ?? '';
76
    }
77
78
    public function getDomain(): string
79
    {
80
        if (! array_key_exists('CN', $this->rawCertificateFields['subject'])) {
81
            return '';
82
        }
83
84
        if (is_string($this->rawCertificateFields['subject']['CN'])) {
85
            return $this->rawCertificateFields['subject']['CN'];
86
        }
87
88
        if (is_array($this->rawCertificateFields['subject']['CN'])) {
89
            return $this->rawCertificateFields['subject']['CN'][0];
90
        }
91
92
        return '';
93
    }
94
95
    public function getSignatureAlgorithm(): string
96
    {
97
        return $this->rawCertificateFields['signatureTypeSN'] ?? '';
98
    }
99
100
    public function getOrganization(): string
101
    {
102
        return $this->rawCertificateFields['subject']['O'] ?? '';
103
    }
104
105
    public function getFingerprint(): string
106
    {
107
        return $this->fingerprint;
108
    }
109
110
    /**
111
     * @return string
112
     */
113
    public function getFingerprintSha256(): string
114
    {
115
        return $this->fingerprintSha256;
116
    }
117
118
    public function getAdditionalDomains(): array
119
    {
120
        $additionalDomains = explode(', ', $this->rawCertificateFields['extensions']['subjectAltName'] ?? '');
121
122
        return array_map(function (string $domain) {
123
            return str_replace('DNS:', '', $domain);
124
        }, $additionalDomains);
125
    }
126
127
    public function validFromDate(): Carbon
128
    {
129
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validFrom_time_t']);
130
    }
131
132
    public function expirationDate(): Carbon
133
    {
134
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validTo_time_t']);
135
    }
136
137
    public function lifespanInDays(): int
138
    {
139
        return $this->validFromDate()->diffInDays($this->expirationDate());
140
    }
141
142
    public function isExpired(): bool
143
    {
144
        return $this->expirationDate()->isPast();
145
    }
146
147
    public function isValid(string $url = null)
148
    {
149
        if (! Carbon::now()->between($this->validFromDate(), $this->expirationDate())) {
150
            return false;
151
        }
152
153
        if (! empty($url)) {
154
            return $this->appliesToUrl($url ?? $this->getDomain());
155
        }
156
157
        return true;
158
    }
159
160
    public function isSelfSigned(): bool
161
    {
162
        return $this->getIssuer() === $this->getDomain();
163
    }
164
165
    public function usesSha1Hash(): bool
166
    {
167
        $certificateFields = $this->getRawCertificateFields();
168
169
        if ($certificateFields['signatureTypeSN'] === 'RSA-SHA1') {
170
            return true;
171
        }
172
173
        if ($certificateFields['signatureTypeLN'] === 'sha1WithRSAEncryption') {
174
            return true;
175
        }
176
177
        return false;
178
    }
179
180
    public function isValidUntil(Carbon $carbon, string $url = null): bool
181
    {
182
        if ($this->expirationDate()->lte($carbon)) {
183
            return false;
184
        }
185
186
        return $this->isValid($url);
187
    }
188
189
    public function daysUntilExpirationDate(): int
190
    {
191
        $endDate = $this->expirationDate();
192
193
        $interval = Carbon::now()->diff($endDate);
194
195
        return (int) $interval->format('%r%a');
196
    }
197
198
    public function getDomains(): array
199
    {
200
        $allDomains = $this->getAdditionalDomains();
201
        $allDomains[] = $this->getDomain();
202
        $uniqueDomains = array_unique($allDomains);
203
204
        return array_values(array_filter($uniqueDomains));
205
    }
206
207
    public function appliesToUrl(string $url): bool
208
    {
209
        if (filter_var($url, FILTER_VALIDATE_IP)) {
210
            $host = $url;
211
        } else {
212
            $host = (new Url($url))->getHostName();
213
        }
214
215
        $certificateHosts = $this->getDomains();
216
217
        foreach ($certificateHosts as $certificateHost) {
218
            $certificateHost = str_replace('ip address:', '', strtolower($certificateHost));
219
            if ($host === $certificateHost) {
220
                return true;
221
            }
222
223
            if ($this->wildcardHostCoversHost($certificateHost, $host)) {
224
                return true;
225
            }
226
        }
227
228
        return false;
229
    }
230
231
    protected function wildcardHostCoversHost(string $wildcardHost, string $host): bool
232
    {
233
        if ($host === $wildcardHost) {
234
            return true;
235
        }
236
237
        if (! starts_with($wildcardHost, '*')) {
238
            return false;
239
        }
240
241
        if (substr_count($wildcardHost, '.') < substr_count($host, '.')) {
242
            return false;
243
        }
244
245
        $wildcardHostWithoutWildcard = substr($wildcardHost, 1);
246
247
        $hostWithDottedPrefix = ".{$host}";
248
249
        return ends_with($hostWithDottedPrefix, $wildcardHostWithoutWildcard);
250
    }
251
252
    public function getRawCertificateFieldsJson(): string
253
    {
254
        return json_encode($this->getRawCertificateFields());
255
    }
256
257
    public function getHash(): string
258
    {
259
        return md5($this->getRawCertificateFieldsJson());
260
    }
261
262
    public function getRemoteAddress(): string
263
    {
264
        return $this->remoteAddress;
265
    }
266
267
    public function __toString(): string
268
    {
269
        return $this->getRawCertificateFieldsJson();
270
    }
271
272
    public function containsDomain(string $domain): bool
273
    {
274
        $certificateHosts = $this->getDomains();
275
276
        foreach ($certificateHosts as $certificateHost) {
277
            if ($certificateHost == $domain) {
278
                return true;
279
            }
280
281
            if (ends_with($domain, '.'.$certificateHost)) {
282
                return true;
283
            }
284
        }
285
286
        return false;
287
    }
288
289
    public function isPreCertificate(): bool
290
    {
291
        if (! array_key_exists('extensions', $this->rawCertificateFields)) {
292
            return false;
293
        }
294
295
        if (! array_key_exists('ct_precert_poison', $this->rawCertificateFields['extensions'])) {
296
            return false;
297
        }
298
299
        return true;
300
    }
301
}
302