From 280b493b701036b7907f63cb1a4d5acd80cbd7c9 Mon Sep 17 00:00:00 2001 From: Amp Date: Mon, 14 Sep 2026 19:42:53 +0000 Subject: [PATCH 1/2] Tag Craft Cloud request signatures Amp-Thread-ID: https://ampcode.com/threads/T-01a0a161-d8cf-758b-bc73-0bae3232314a Co-authored-by: Tim Kelty --- src/signing/RequestSigner.php | 1 + tests/unit/RequestSignerTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/signing/RequestSigner.php b/src/signing/RequestSigner.php index 5846a94c..8ce91c56 100644 --- a/src/signing/RequestSigner.php +++ b/src/signing/RequestSigner.php @@ -36,6 +36,7 @@ public function sign(RequestInterface $request): RequestInterface 'keyid' => $this->keyId, 'created' => $created, 'expires' => $created + $this->expiresAfter, + 'tag' => 'craft-cloud', ], ); diff --git a/tests/unit/RequestSignerTest.php b/tests/unit/RequestSignerTest.php index ded73ebd..d94c8642 100644 --- a/tests/unit/RequestSignerTest.php +++ b/tests/unit/RequestSignerTest.php @@ -57,6 +57,7 @@ private function assertSignedRequest(RequestInterface $request): void $this->assertStringContainsString('"@target-uri"', $signatureInput); $this->assertStringContainsString('alg="hmac-sha256"', $signatureInput); $this->assertStringContainsString('keyid="hmac"', $signatureInput); + $this->assertStringContainsString('tag="craft-cloud"', $signatureInput); $matches = []; $this->assertSame(1, preg_match('/created=(\d+);expires=(\d+)/', $signatureInput, $matches)); From d3bc9e84849d739ad1c2e6f0ba0cf7b93af0eed3 Mon Sep 17 00:00:00 2001 From: Amp Date: Mon, 14 Sep 2026 19:51:54 +0000 Subject: [PATCH 2/2] Test signature tag tampering Amp-Thread-ID: https://ampcode.com/threads/T-01a0a161-d8cf-758b-bc73-0bae3232314a Co-authored-by: Tim Kelty --- tests/unit/RequestSignerTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/unit/RequestSignerTest.php b/tests/unit/RequestSignerTest.php index d94c8642..ae1cbe9f 100644 --- a/tests/unit/RequestSignerTest.php +++ b/tests/unit/RequestSignerTest.php @@ -9,6 +9,7 @@ use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; use HttpMessageSignatures\Algorithm\HmacSha256; +use HttpMessageSignatures\Exception\VerificationException; use HttpMessageSignatures\Verifier; use Psr\Http\Message\RequestInterface; @@ -46,6 +47,19 @@ public function testCreatesHandlerStackForSignedRequests(): void $this->assertSignedRequest($capturedRequest); } + public function testRejectsTamperedSignatureTag(): void + { + $request = (new RequestSigner('test-signing-key')) + ->sign(new Request('GET', 'https://example.test/status')); + $request = $request->withHeader( + 'Signature-Input', + str_replace('tag="craft-cloud"', 'tag="other"', $request->getHeaderLine('Signature-Input')), + ); + + $this->expectException(VerificationException::class); + (new Verifier(new HmacSha256('test-signing-key')))->verify($request); + } + private function assertSignedRequest(RequestInterface $request): void { $this->assertNotSame('', $request->getHeaderLine('Signature'));