Issues (24)

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.

test/RoaveTest/ComposerGpgVerify/VerifyTest.php (6 issues)

Labels
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
declare(strict_types=1);
4
5
namespace RoaveTest\ComposerGpgVerify;
6
7
use Composer\Composer;
8
use Composer\Config;
9
use Composer\Installer\InstallationManager;
10
use Composer\IO\IOInterface;
11
use Composer\Package\PackageInterface;
12
use Composer\Repository\RepositoryInterface;
13
use Composer\Repository\RepositoryManager;
14
use Composer\Script\Event;
15
use Composer\Script\ScriptEvents;
16
use PHPUnit\Framework\TestCase;
17
use Roave\ComposerGpgVerify\Exception\PackagesTrustCheckFailed;
18
use Roave\ComposerGpgVerify\Exception\PreferredInstallIsNotSource;
19
use Roave\ComposerGpgVerify\Verify;
20
use Symfony\Component\Process\Process;
21
22
/**
23
 * @covers \Roave\ComposerGpgVerify\Verify
24
 */
25
final class VerifyTest extends TestCase
26
{
27
    /**
28
     * @var Event|\PHPUnit_Framework_MockObject_MockObject
29
     */
30
    private $event;
31
32
    /**
33
     * @var Composer|\PHPUnit_Framework_MockObject_MockObject
34
     */
35
    private $composer;
36
37
    /**
38
     * @var IOInterface|\PHPUnit_Framework_MockObject_MockObject
39
     */
40
    private $io;
41
42
    /**
43
     * @var Config|\PHPUnit_Framework_MockObject_MockObject
44
     */
45
    private $config;
46
47
    /**
48
     * @var RepositoryManager|\PHPUnit_Framework_MockObject_MockObject
49
     */
50
    private $repositoryManager;
51
52
    /**
53
     * @var InstallationManager|\PHPUnit_Framework_MockObject_MockObject
54
     */
55
    private $installationManager;
56
57
    /**
58
     * @var RepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
59
     */
60
    private $localRepository;
61
62
    /**
63
     * @var string
64
     */
65
    private $originalGpgHome;
66
67
    /**
68
     * @var string
69
     */
70
    private $originalLanguage;
71
72
    /**
73
     * @var PackageInterface[] indexed by installation path
74
     */
75
    private $installedPackages = [];
76
77
    protected function setUp() : void
78
    {
79
        parent::setUp();
80
81
        $this->installedPackages = [];
82
        $this->originalGpgHome   = (string) getenv('GNUPGHOME');
83
        $this->originalLanguage  = (string) getenv('LANGUAGE');
84
85
        $this->event               = $this->createMock(Event::class);
86
        $this->composer            = $this->createMock(Composer::class);
87
        $this->io                  = $this->createMock(IOInterface::class);
88
        $this->config              = $this->createMock(Config::class);
89
        $this->repositoryManager   = $this->createMock(RepositoryManager::class);
90
        $this->installationManager = $this->createMock(InstallationManager::class);
91
        $this->localRepository     = $this->createMock(RepositoryInterface::class);
92
93
        $this->event->expects(self::any())->method('getComposer')->willReturn($this->composer);
94
        $this->event->expects(self::any())->method('getIO')->willReturn($this->io);
95
        $this->composer->expects(self::any())->method('getConfig')->willReturn($this->config);
96
        $this
97
            ->composer
98
            ->expects(self::any())
99
            ->method('getRepositoryManager')
100
            ->willReturn($this->repositoryManager);
101
        $this
102
            ->composer
103
            ->expects(self::any())
104
            ->method('getInstallationManager')
105
            ->willReturn($this->installationManager);
106
        $this
107
            ->repositoryManager
108
            ->expects(self::any())
109
            ->method('getLocalRepository')
110
            ->willReturn($this->localRepository);
111
        $this
112
            ->installationManager
113
            ->expects(self::any())
114
            ->method('getInstallPath')
115
            ->willReturnCallback(function (PackageInterface $package) : string {
116
                return array_search($package, $this->installedPackages, true);
117
            });
118
        $this
119
            ->localRepository
120
            ->expects(self::any())
121
            ->method('getPackages')
122
            ->willReturnCallback(function () {
123
                return array_values($this->installedPackages);
124
            });
125
    }
126
127
    protected function tearDown() : void
128
    {
129
        putenv(sprintf('GNUPGHOME=%s', $this->originalGpgHome));
130
        putenv(sprintf('LANGUAGE=%s', $this->originalLanguage));
131
132
        parent::tearDown();
133
    }
134
135
    public function testWillDisallowInstallationOnNonSourceInstall() : void
136
    {
137
        $this
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Composer\Config.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
138
            ->config
139
            ->expects(self::any())
140
            ->method('get')
141
            ->with('preferred-install')
142
            ->willReturn('foo');
143
144
        $this->expectException(PreferredInstallIsNotSource::class);
145
146
        Verify::verify($this->event);
147
    }
148
149
    public function testWillRetrieveSubscribedEvents() : void
150
    {
151
        $events = Verify::getSubscribedEvents();
152
153
        self::assertNotEmpty($events);
154
155
        $availableEvents = (new \ReflectionClass(ScriptEvents::class))->getConstants();
156
157
        foreach ($events as $eventName => $callback) {
158
            self::assertContains($eventName, $availableEvents);
159
            self::assertInternalType('string', $callback);
160
            self::assertInternalType('callable', [Verify::class, $callback]);
161
        }
162
    }
163
164
    public function testWillRejectNonGitPackages() : void
165
    {
166
        $packageName = 'vendor1/package1';
167
        $vendor1     = sys_get_temp_dir() . '/' . uniqid('vendor', true) . '/' . $packageName;
168
169
        /* @var $package PackageInterface|\PHPUnit_Framework_MockObject_MockObject */
170
        $package = $this->createMock(PackageInterface::class);
171
172
        $package->expects(self::any())->method('getName')->willReturn($packageName);
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Composer\Package\PackageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
173
174
        $this->installedPackages[$vendor1] = $package;
175
176
        self::assertTrue(mkdir($vendor1, 0700, true));
177
        $this->configureCorrectComposerSetup();
178
179
        $this->assertWillFailPackageVerification();
180
    }
181
182
    public function testWillAcceptSignedAndTrustedPackages() : void
183
    {
184
        $gpgHomeDirectory = $this->makeGpgHomeDirectory();
185
186
        $vendorName  = 'Mr. Magoo';
187
        $vendorEmail = '[email protected]';
188
        $vendorKey   = $this->makeKey($gpgHomeDirectory, $vendorEmail, $vendorName);
189
        $vendorDir   = $this->makeVendorDirectory();
190
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
191
192
        $this->signDependency($vendor1, $gpgHomeDirectory, $vendorKey);
193
194
        $this->configureCorrectComposerSetup();
195
196
        putenv('GNUPGHOME=' . $gpgHomeDirectory);
197
198
        $this->assertWillSucceedPackageVerification();
199
    }
200
201
    public function testWillRejectPackageSignedWithImportedButUnTrustedKey() : void
202
    {
203
        $personalGpgDirectory = $this->makeGpgHomeDirectory();
204
        $foreignGpgDirectory  = $this->makeGpgHomeDirectory();
205
206
        $this->makeKey($personalGpgDirectory, '[email protected]', 'Just Me');
207
208
        $vendorName  = 'Mr. Magoo';
209
        $vendorEmail = '[email protected]';
210
        $vendorKey   = $this->makeKey($foreignGpgDirectory, $vendorEmail, $vendorName);
211
        $vendorDir   = $this->makeVendorDirectory();
212
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
213
214
        $this->signDependency($vendor1, $foreignGpgDirectory, $vendorKey);
215
216
        $this->importForeignKeys($personalGpgDirectory, $foreignGpgDirectory, $vendorKey, false);
217
218
        $this->configureCorrectComposerSetup();
219
220
        putenv('GNUPGHOME=' . $personalGpgDirectory);
221
222
        $this->assertWillFailPackageVerification();
223
    }
224
225
    public function testWillRejectPackageSignedWithImportedButUnTrustedKeyWithDifferentLocaleSettings() : void
226
    {
227
        $personalGpgDirectory = $this->makeGpgHomeDirectory();
228
        $foreignGpgDirectory  = $this->makeGpgHomeDirectory();
229
230
        $this->makeKey($personalGpgDirectory, '[email protected]', 'Just Me');
231
232
        $vendorName  = 'Mr. Magoo';
233
        $vendorEmail = '[email protected]';
234
235
        $vendorKey   = $this->makeKey($foreignGpgDirectory, $vendorEmail, $vendorName);
236
        $vendorDir   = $this->makeVendorDirectory();
237
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
238
239
        $this->signDependency($vendor1, $foreignGpgDirectory, $vendorKey);
240
241
        $this->importForeignKeys($personalGpgDirectory, $foreignGpgDirectory, $vendorKey, false);
242
243
        $this->configureCorrectComposerSetup();
244
245
        putenv('GNUPGHOME=' . $personalGpgDirectory);
246
        putenv('LANGUAGE=de_DE');
247
248
        try {
249
            Verify::verify($this->event);
250
        } catch (PackagesTrustCheckFailed $failure) {
251
            self::assertSame('de_DE', getenv('LANGUAGE'));
252
253
            return;
254
        }
255
256
        self::fail('Exception was not thrown');
257
    }
258
259
    public function testWillAcceptPackageSignedWithImportedAndTrustedKey() : void
260
    {
261
        $personalGpgDirectory = $this->makeGpgHomeDirectory();
262
        $foreignGpgDirectory  = $this->makeGpgHomeDirectory();
263
264
        $this->makeKey($personalGpgDirectory, '[email protected]', 'Just Me');
265
266
        $vendorName  = 'Mr. Magoo';
267
        $vendorEmail = '[email protected]';
268
        $vendorKey   = $this->makeKey($foreignGpgDirectory, $vendorEmail, $vendorName);
269
        $vendorDir   = $this->makeVendorDirectory();
270
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
271
272
        $this->signDependency($vendor1, $foreignGpgDirectory, $vendorKey);
273
274
        $this->importForeignKeys($personalGpgDirectory, $foreignGpgDirectory, $vendorKey, true);
275
276
        $this->configureCorrectComposerSetup();
277
278
        putenv('GNUPGHOME=' . $personalGpgDirectory);
279
280
        $this->assertWillSucceedPackageVerification();
281
    }
282
283
    public function testWillRejectPackageTaggedAndSignedWithImportedButUnTrustedKey() : void
284
    {
285
        $personalGpgDirectory = $this->makeGpgHomeDirectory();
286
        $foreignGpgDirectory  = $this->makeGpgHomeDirectory();
287
288
        $this->makeKey($personalGpgDirectory, '[email protected]', 'Just Me');
289
290
        $vendorName  = 'Mr. Magoo';
291
        $vendorEmail = '[email protected]';
292
        $vendorKey   = $this->makeKey($foreignGpgDirectory, $vendorEmail, $vendorName);
293
        $vendorDir   = $this->makeVendorDirectory();
294
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
295
296
        $this->createDependencySignedTag($vendor1, $foreignGpgDirectory, $vendorKey);
297
298
        $this->importForeignKeys($personalGpgDirectory, $foreignGpgDirectory, $vendorKey, false);
299
300
        $this->configureCorrectComposerSetup();
301
302
        putenv('GNUPGHOME=' . $personalGpgDirectory);
303
304
        $this->assertWillFailPackageVerification();
305
    }
306
307
    public function testWillAcceptPackageTaggedAndSignedWithImportedAndTrustedKey() : void
308
    {
309
        $personalGpgDirectory = $this->makeGpgHomeDirectory();
310
        $foreignGpgDirectory  = $this->makeGpgHomeDirectory();
311
312
        $this->makeKey($personalGpgDirectory, '[email protected]', 'Just Me');
313
314
        $vendorName  = 'Mr. Magoo';
315
        $vendorEmail = '[email protected]';
316
        $vendorKey   = $this->makeKey($foreignGpgDirectory, $vendorEmail, $vendorName);
317
        $vendorDir   = $this->makeVendorDirectory();
318
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
319
320
        $this->createDependencySignedTag($vendor1, $foreignGpgDirectory, $vendorKey);
321
322
        $this->importForeignKeys($personalGpgDirectory, $foreignGpgDirectory, $vendorKey, true);
323
324
        $this->configureCorrectComposerSetup();
325
326
        putenv('GNUPGHOME=' . $personalGpgDirectory);
327
328
        $this->assertWillSucceedPackageVerification();
329
    }
330
331
    public function testWillAcceptSignedAndTrustedTaggedPackages() : void
332
    {
333
        $gpgHomeDirectory = $this->makeGpgHomeDirectory();
334
335
        $vendorName  = 'Mr. Magoo';
336
        $vendorEmail = '[email protected]';
337
        $vendorKey   = $this->makeKey($gpgHomeDirectory, $vendorEmail, $vendorName);
338
        $vendorDir   = $this->makeVendorDirectory();
339
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
340
341
        $this->createDependencySignedTag($vendor1, $gpgHomeDirectory, $vendorKey);
342
343
        $this->configureCorrectComposerSetup();
344
345
        putenv('GNUPGHOME=' . $gpgHomeDirectory);
346
347
        $this->assertWillSucceedPackageVerification();
348
    }
349
350
    public function testWillRejectUnSignedCommits() : void
351
    {
352
        $vendorName  = 'Mr. Magoo';
353
        $vendorEmail = '[email protected]';
354
        $vendorDir   = $this->makeVendorDirectory();
355
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
356
357
        (new Process('git commit --allow-empty -m "unsigned commit"', $vendor1))
358
            ->setTimeout(30)
359
            ->mustRun();
360
361
        $this->configureCorrectComposerSetup();
362
363
        putenv('GNUPGHOME=' . $this->makeGpgHomeDirectory());
364
365
        $this->assertWillFailPackageVerification();
366
    }
367
368
    public function testWillRejectUnSignedTags() : void
369
    {
370
        $vendorName  = 'Mr. Magoo';
371
        $vendorEmail = '[email protected]';
372
        $vendorDir   = $this->makeVendorDirectory();
373
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
374
375
        (new Process('git commit --allow-empty -m "unsigned commit"', $vendor1))
376
            ->setTimeout(30)
377
            ->mustRun();
378
379
        (new Process('git tag unsigned-tag -m "unsigned tag"', $vendor1))
380
            ->setTimeout(30)
381
            ->mustRun();
382
383
        $this->configureCorrectComposerSetup();
384
385
        putenv('GNUPGHOME=' . $this->makeGpgHomeDirectory());
386
387
        $this->assertWillFailPackageVerification();
388
    }
389
390
    public function testWillRejectSignedTagsFromUnknownKey() : void
391
    {
392
        $personalGpgDirectory = $this->makeGpgHomeDirectory();
393
        $foreignGpgDirectory  = $this->makeGpgHomeDirectory();
394
        $vendorName  = 'Mr. Magoo';
395
        $vendorEmail = '[email protected]';
396
        $vendorKey   = $this->makeKey($foreignGpgDirectory, $vendorEmail, $vendorName);
397
        $vendorDir   = $this->makeVendorDirectory();
398
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
399
400
        $this->createDependencySignedTag($vendor1, $foreignGpgDirectory, $vendorKey);
401
402
        $this->configureCorrectComposerSetup();
403
404
        putenv('GNUPGHOME=' . $personalGpgDirectory);
405
406
        $this->assertWillFailPackageVerification();
407
    }
408
409
    public function testWillRejectSignedTagsFromNonHeadCommit() : void
410
    {
411
        $gpgHome     = $this->makeGpgHomeDirectory();
412
        $vendorName  = 'Mr. Magoo';
413
        $vendorEmail = '[email protected]';
414
        $vendorKey   = $this->makeKey($gpgHome, $vendorEmail, $vendorName);
415
        $vendorDir   = $this->makeVendorDirectory();
416
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
417
418
        $this->createDependencySignedTag($vendor1, $gpgHome, $vendorKey);
419
420
        (new Process('git commit --allow-empty -m "unsigned commit"', $vendor1))
421
            ->setTimeout(30)
422
            ->mustRun();
423
424
        $this->configureCorrectComposerSetup();
425
426
        putenv('GNUPGHOME=' . $gpgHome);
427
428
        $this->assertWillFailPackageVerification();
429
    }
430
431
    public function testWillOnlyConsiderTheHeadCommitForValidation() : void
432
    {
433
        $gpgHome     = $this->makeGpgHomeDirectory();
434
        $vendorName  = 'Mr. Magoo';
435
        $vendorEmail = '[email protected]';
436
        $vendorKey   = $this->makeKey($gpgHome, $vendorEmail, $vendorName);
437
        $vendorDir   = $this->makeVendorDirectory();
438
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
439
440
        $this->signDependency($vendor1, $gpgHome, $vendorKey);
441
442
        (new Process('git commit --allow-empty -m "unsigned commit"', $vendor1))
443
            ->setTimeout(30)
444
            ->mustRun();
445
446
        $this->configureCorrectComposerSetup();
447
448
        putenv('GNUPGHOME=' . $gpgHome);
449
450
        $this->assertWillFailPackageVerification();
451
    }
452
453
    public function testWillRejectSignedCommitsFromUnknownKeys() : void
454
    {
455
        $personalGpgDirectory = $this->makeGpgHomeDirectory();
456
        $foreignGpgDirectory  = $this->makeGpgHomeDirectory();
457
458
        $vendorName  = 'Mr. Magoo';
459
        $vendorEmail = '[email protected]';
460
        $vendorKey   = $this->makeKey($foreignGpgDirectory, $vendorEmail, $vendorName);
461
        $vendorDir   = $this->makeVendorDirectory();
462
        $vendor1     = $this->makeDependencyGitRepository($vendorDir, 'vendor1/package1', $vendorEmail, $vendorName);
463
464
        $this->signDependency($vendor1, $foreignGpgDirectory, $vendorKey);
465
466
        $this->configureCorrectComposerSetup();
467
468
        putenv('GNUPGHOME=' . $personalGpgDirectory);
469
470
        $this->assertWillFailPackageVerification();
471
    }
472
473
    private function makeVendorDirectory() : string
474
    {
475
        $vendorDirectory = sys_get_temp_dir() . '/' . uniqid('vendor', true);
476
477
        self::assertTrue(mkdir($vendorDirectory));
478
479
        return $vendorDirectory;
480
    }
481
482
    private function signDependency(
483
        string $dependencyDirectory,
484
        string $gpgHomeDirectory,
485
        string $signingKey
486
    ) : void {
487
        (new Process(sprintf('git config --local --add user.signingkey %s', escapeshellarg($signingKey)), $dependencyDirectory))
488
            ->setTimeout(30)
489
            ->mustRun();
490
491
        (new Process(
492
            'git commit --allow-empty -m "signed commit" -S',
493
            $dependencyDirectory,
494
            ['GNUPGHOME' => $gpgHomeDirectory, 'GIT_TRACE' => '2']
495
        ))
496
            ->setTimeout(30)
497
            ->mustRun();
498
    }
499
500
    private function createDependencySignedTag(
501
        string $dependencyDirectory,
502
        string $gpgHomeDirectory,
503
        string $signingKey
504
    ) : void {
505
        (new Process(sprintf('git config --local --add user.signingkey %s', escapeshellarg($signingKey)), $dependencyDirectory))
506
            ->setTimeout(30)
507
            ->mustRun();
508
509
        (new Process('git commit --allow-empty -m "unsigned commit"', $dependencyDirectory))
510
            ->setTimeout(30)
511
            ->mustRun();
512
513
        (new Process(
514
            'git tag -s "tag-name" -m "signed tag"',
515
            $dependencyDirectory,
516
            ['GNUPGHOME' => $gpgHomeDirectory, 'GIT_TRACE' => '2']
517
        ))
518
            ->setTimeout(30)
519
            ->mustRun();
520
    }
521
522
    private function makeDependencyGitRepository(
523
        string $vendorDirectory,
524
        string $packageName,
525
        string $email,
526
        string $name
527
    ) : string {
528
        $dependencyRepository = $vendorDirectory . '/' . $packageName;
529
530
        self::assertTrue(mkdir($dependencyRepository, 0777, true));
531
532
        (new Process('git init', $dependencyRepository))
533
            ->setTimeout(30)
534
            ->mustRun();
535
536
        (new Process(sprintf('git config --local --add user.email %s', escapeshellarg($email)), $dependencyRepository))
537
            ->setTimeout(30)
538
            ->mustRun();
539
540
        (new Process(sprintf('git config --local --add user.name %s', escapeshellarg($name)), $dependencyRepository))
541
            ->setTimeout(30)
542
            ->mustRun();
543
544
        /* @var $package PackageInterface|\PHPUnit_Framework_MockObject_MockObject */
545
        $package = $this->createMock(PackageInterface::class);
546
547
        $package->expects(self::any())->method('getName')->willReturn($packageName);
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Composer\Package\PackageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
548
549
        $this->installedPackages[$dependencyRepository] = $package;
550
551
        return $dependencyRepository;
552
    }
553
554
    private function makeGpgHomeDirectory() : string
555
    {
556
        $homeDirectory = sys_get_temp_dir() . '/' . uniqid('gpg-verification-test', true);
557
558
        self::assertTrue(mkdir($homeDirectory, 0700));
559
560
        return $homeDirectory;
561
    }
562
563
    private function makeKey(string $gpgHomeDirectory, string $emailAddress, string $name) : string
564
    {
565
        $input = <<<'KEY'
566
%echo Generating a standard key
567
Key-Type: RSA
568
Key-Length: 128
569
Name-Real: <<<NAME>>>
570
Name-Email: <<<EMAIL>>>
571
Expire-Date: 0
572
%no-protection
573
%no-ask-passphrase
574
%commit
575
%echo done
576
577
KEY;
578
        self::assertGreaterThan(
579
            0,
580
            file_put_contents(
581
                $gpgHomeDirectory . '/key-info.txt',
582
                str_replace(['<<<NAME>>>', '<<<EMAIL>>>'], [$name, $emailAddress], $input)
583
            )
584
        );
585
586
        $keyOutput = (new Process(
587
            'gpg --batch --gen-key -a key-info.txt',
588
            $gpgHomeDirectory,
589
            ['GNUPGHOME' => $gpgHomeDirectory]
590
        ))
591
            ->setTimeout(30)
592
            ->mustRun()
593
            ->getErrorOutput();
594
595
        self::assertRegExp('/key [0-9A-F]+ marked as ultimately trusted/i', $keyOutput);
596
597
        preg_match('/key ([0-9A-F]+) marked as ultimately trusted/i', $keyOutput, $matches);
598
599
        return $matches[1];
600
    }
601
602
    private function configureCorrectComposerSetup() : void
603
    {
604
        $this
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Composer\Config.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
605
            ->config
606
            ->expects(self::any())
607
            ->method('get')
608
            ->with('preferred-install')
609
            ->willReturn('source');
610
    }
611
612
    private function assertWillSucceedPackageVerification() : void
613
    {
614
        $this
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Composer\IO\IOInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
615
            ->io
616
            ->expects(self::exactly(2))
617
            ->method('write')
618
            ->with(self::logicalOr(
619
                '<info>roave/composer-gpg-verify:</info>  Analysing downloaded packages...',
620
                '<info>roave/composer-gpg-verify:</info>  All installed packages passed GPG validation!'
621
            ));
622
623
        Verify::verify($this->event);
624
    }
625
626
    private function assertWillFailPackageVerification() : void
627
    {
628
        $this
0 ignored issues
show
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Composer\IO\IOInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
629
            ->io
630
            ->expects(self::once())
631
            ->method('write')
632
            ->with(self::logicalOr('<info>roave/composer-gpg-verify:</info>  Analysing downloaded packages...'));
633
634
        $this->expectException(PackagesTrustCheckFailed::class);
635
636
        Verify::verify($this->event);
637
    }
638
639
    private function importForeignKeys(
640
        string $localGpgHome,
641
        string $foreignGpgHome,
642
        string $foreignKey,
643
        bool $sign
644
    ) : void {
645
        $exportPath = sys_get_temp_dir() . '/' . uniqid('exportedKey', true);
646
647
        (new Process(
648
            sprintf('gpg --export --armor > %s', escapeshellarg($exportPath)),
649
            null,
650
            ['GNUPGHOME' => $foreignGpgHome]
651
        ))
652
            ->setTimeout(30)
653
            ->mustRun();
654
655
        self::assertFileExists($exportPath);
656
657
        (new Process(
658
            sprintf('gpg --import < %s', escapeshellarg($exportPath)),
659
            null,
660
            ['GNUPGHOME' => $localGpgHome]
661
        ))
662
            ->setTimeout(30)
663
            ->mustRun();
664
665
        if (! $sign) {
666
            return;
667
        }
668
669
        (new Process(
670
            sprintf('gpg --batch --yes --sign-key %s', escapeshellarg($foreignKey)),
671
            null,
672
            ['GNUPGHOME' => $localGpgHome]
673
        ))
674
            ->setTimeout(30)
675
            ->mustRun();
676
    }
677
}
678