Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 6 additions & 43 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
# `<asset>.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
Expand Down
19 changes: 10 additions & 9 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <hello@hydephp.com>)
Expand Down Expand Up @@ -83,7 +83,9 @@ YXlffyl8g5pXBQKUo/L1BGbePF18Xg4jwsNPIMjUQObJ
```
</details>

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:


<details>
Expand Down Expand Up @@ -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)
Expand All @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion app/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 0 additions & 4 deletions tests/Unit/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down
Loading