diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index e1d2ab66..6a738511 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -74,8 +74,11 @@ jobs: exit 1 fi - echo "Submitting pull request #$pr_number to the master merge queue." - gh pr merge "$pr_number" --repo "$GITHUB_REPOSITORY" + echo "Enabling auto-merge for pull request #$pr_number." + gh pr merge "$pr_number" \ + --repo "$GITHUB_REPOSITORY" \ + --merge \ + --auto build: uses: ./.github/workflows/build-native-all.yml @@ -104,50 +107,10 @@ jobs: - name: List the artifacts run: ls -lh artifacts - - name: Import GPG key - if: github.event.repository.full_name == 'hydephp/cli' - uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec - with: - gpg_private_key: ${{ secrets.GPG_SIGNING_PRIVATE_KEY }} - passphrase: ${{ secrets.GPG_SIGNING_KEY_PASSPHRASE }} - trust_level: 5 - # Each platform's artifact is signed on its own. The self-update command resolves # `.sig.bin` for the platform it is running on, so the names have to line # up with App\Launcher\Platform exactly. - - name: Sign every executable - if: github.event.repository.full_name == 'hydephp/cli' - run: | - set -euo pipefail - - for artifact in artifacts/hyde-*; do - case "$artifact" in *.sig|*.sig.bin) continue ;; esac - - echo "Signing $artifact" - - gpg --local-user 657B4D97184E9E6E596E6EA13B829782D5B7BA59 \ - --batch \ - --yes \ - --passphrase="${{ secrets.GPG_SIGNING_KEY_PASSPHRASE }}" \ - --detach-sign \ - --output "$artifact.sig" \ - "$artifact" - done - - - name: Verify every signature - if: github.event.repository.full_name == 'hydephp/cli' - run: | - set -euo pipefail - - gpg --import-ownertrust <<< "657B4D97184E9E6E596E6EA13B829782D5B7BA59:6:" - - for signature in artifacts/*.sig; do - gpg --verify "$signature" "${signature%.sig}" - done - - # The OpenSSL signature is the one `hyde self-update` verifies, because OpenSSL is - # bundled with the executable while GPG may not be present on a user's machine. - - name: Create OpenSSL fallback signatures + - name: Create OpenSSL signatures if: github.event.repository.full_name == 'hydephp/cli' run: | set -euo pipefail diff --git a/SECURITY.md b/SECURITY.md index 49dee898..5b42e83a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -21,13 +21,13 @@ All security vulnerabilities will be promptly addressed. ## Phar Security The HydePHP CLI is distributed as a Phar archive, which is a PHP executable file format. -The Phar is signed with a GPG key, and the public key is available in the repository. -You can verify the integrity of the Phar by checking the signature against the public key. -This verification is also done automatically when self-updating the CLI using the direct download strategy. +Release executables are signed with an OpenSSL key, and the public key is available in the repository. +The CLI automatically verifies the matching `.sig.bin` signature when self-updating using the direct download strategy. +Published executables also include GitHub build provenance attestations. -### Public Key Information +### Legacy PGP Key Information -The public key used for signing builds in the 0.x series range is a PGP key that has the fingerprint `3B829782D5B7BA59`. It is an `rsa3072` key expiring on `2026-04-20`, and is as follows: +Builds are no longer GPG-signed. For historical verification, builds in the 0.x series used a PGP key with fingerprint `3B829782D5B7BA59`. This `rsa3072` key expired on `2026-04-20`: ``` 657B4D97184E9E6E596E6EA13B829782D5B7BA59 (HydePHP CLI Alpha Key ) @@ -83,7 +83,9 @@ YXlffyl8g5pXBQKUo/L1BGbePF18Xg4jwsNPIMjUQObJ ``` -We also provide an experimental fallback `.bin` signature that uses an OpenSSL key for increased compatibility with systems that do not support GPG. +### OpenSSL Public Key + +Current releases use `.sig.bin` signatures created with this OpenSSL key:
@@ -112,7 +114,7 @@ Xys3FeRJy25FQ/J/npGcxRcCAwEAAQ== In order to validate the authenticity of the public key and that it comes from HydePHP you can visit https://trustservices.hydephp.com/certificates/ for a listing of all our public keys and certificates. You can also see the listing on [GitHub](https://github.com/hydephp/certificates) for the same information. Note that this repository is handled independently of the trust services meaning that two separate platforms would need to be compromised to spoof the key. -The certificate is also listed on several keyservers: +The legacy PGP key remains listed on several keyservers for historical verification: - [OpenPGP Keyserver](https://keys.openpgp.org/vks/v1/by-fingerprint/657B4D97184E9E6E596E6EA13B829782D5B7BA59) - [Ubuntu Keyserver](https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x657B4D97184E9E6E596E6EA13B829782D5B7BA59) - [MIT Keyserver](https://pgp.mit.edu/pks/lookup?op=get&search=0x657B4D97184E9E6E596E6EA13B829782D5B7BA59) @@ -124,8 +126,7 @@ If you are curious how we secure our certificates and private keys, here is a br To ensure the security of our certificates and private keys, we implement a multi-layered approach: - Our private key is safeguarded through several redundancy measures. This includes encrypted storage via GitHub Actions Secrets for cloud builds, alongside a master copy securely managed by our core maintainer. Additionally, there's a physical recovery key stored in a vault in an undisclosed location. -- The current key in use is scoped to only be used for alpha builds in the 0.x series range, this means that security protocols can be field tested before the final key is used for general availability. -- In the unlikely event of a compromise, the key can be revoked and replaced with a new key. The new key will be signed by the old key to ensure continuity of trust. +- In the unlikely event of a compromise, the signing key can be revoked and replaced. - Additionally, the public key is made available on several independent platforms, making it much more difficult for an attacker to spoof the key. - Of course all private keys are protected by unique highly secure and complex passphrases that are never stored in plaintext. diff --git a/app/Application.php b/app/Application.php index d659765d..558e38dd 100644 --- a/app/Application.php +++ b/app/Application.php @@ -21,7 +21,7 @@ class Application extends \Hyde\Foundation\Application * framework version. The 0.11.x CLI line embeds and supports the unreleased HydePHP * v3 development line, but the two versions must never be made to track each other. */ - final public const APP_VERSION = '0.11.0'; + final public const APP_VERSION = '0.11.1'; /** * Get the path to the cached packages.php file. diff --git a/tests/Unit/ApplicationTest.php b/tests/Unit/ApplicationTest.php index 47ed5b2b..6aafa36e 100644 --- a/tests/Unit/ApplicationTest.php +++ b/tests/Unit/ApplicationTest.php @@ -10,10 +10,6 @@ expect(Application::APP_VERSION)->toMatch('/^\d+\.\d+\.\d+$/'); }); -test('the CLI is versioned independently of the framework', function () { - expect(Application::APP_VERSION)->toBe('0.11.0'); -}); - test('custom application extends Hyde application', function () { expect(new Application())->toBeInstanceOf(HydeApplication::class); });