Skip to content

Commit 0c75705

Browse files
kagg-designhCaptcha GHA
andauthored
Tighten permissions. (#439)
* Tighten permissions. * Update ci.yml. * Update create-zip.yml. * Ensure wp-cli integrity via checksum. * Do not run CI on internal PRs. * Fix tests for running with WP 6.9. * Fix weird cron bug in tests with WP 6.9. * Update changelog from readme.txt * Revert test changes in readme.txt and changelog.txt. * Check if the user is authorized in the deploy action. --------- Co-authored-by: hCaptcha GHA <[email protected]>
1 parent bae5369 commit 0c75705

File tree

14 files changed

+73
-20
lines changed

14 files changed

+73
-20
lines changed

.github/workflows/ci.yml

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
name: hCaptcha CI
22
on: [ push, pull_request ]
3+
4+
# 1. SECURITY: Default to read-only permissions for the workflow
5+
permissions:
6+
actions: read
7+
contents: read
8+
39
concurrency:
4-
group: ${{ github.ref }}
10+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
511
cancel-in-progress: true
612

713
jobs:
@@ -25,6 +31,10 @@ jobs:
2531
WP_ADMIN_PASSWORD: admin
2632
WP_ADMIN_EMAIL: [email protected]
2733

34+
if: |
35+
github.event_name == 'push' ||
36+
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true)
37+
2838
runs-on: ${{ matrix.os }}
2939

3040
name: PHP ${{ matrix.php-version }} on ${{ matrix.os }}
@@ -35,10 +45,8 @@ jobs:
3545
with:
3646
path: ${{ env.wp-plugin-directory }}
3747

38-
- name: Update changelog
39-
if: ${{ matrix.php-version == '8.4' }}
40-
working-directory: ${{ env.wp-plugin-directory }}
41-
run: .github/scripts/update-changelog.sh
48+
# MOVED: The "Update changelog" step has been moved to the specific job below
49+
# to prevent giving 'contents: write' permissions to this testing job.
4250

4351
- name: Setup PHP
4452
uses: hCaptcha/setup-php@42a9487ddd45db247decea2acf7de871a8178226
@@ -67,8 +75,12 @@ jobs:
6775
yarn lint
6876
6977
- name: Install WP CLI
78+
# Security: 1. Ensure wp-cli integrity via checksum.
7079
run: |
71-
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
80+
WPCLI_VERSION=2.12.0
81+
curl -fsSL -o wp-cli.phar "https://github.com/wp-cli/wp-cli/releases/download/v${WPCLI_VERSION}/wp-cli-${WPCLI_VERSION}.phar"
82+
curl -fsSL -o wp-cli.phar.sha256 "https://github.com/wp-cli/wp-cli/releases/download/v${WPCLI_VERSION}/wp-cli-${WPCLI_VERSION}.phar.sha256"
83+
echo "$(cat wp-cli.phar.sha256) wp-cli.phar" | sha256sum -c -
7284
chmod +x wp-cli.phar
7385
mkdir -p wp-cli
7486
sudo mv wp-cli.phar wp-cli/wp
@@ -115,3 +127,30 @@ jobs:
115127
if: ${{ matrix.php-version == '8.4' }}
116128
working-directory: ${{ env.wp-plugin-directory }}
117129
run: yarn jest
130+
131+
update_changelog:
132+
name: Update Changelog
133+
runs-on: ubuntu-latest
134+
135+
# 2. SECURITY: Only run on PUSH, never on Pull Requests
136+
if: github.event_name == 'push'
137+
needs: cs_and_tests
138+
139+
# 3. SECURITY: Grant write permission ONLY to this job
140+
permissions:
141+
contents: write
142+
143+
env:
144+
wp-plugin-directory: wordpress/wp-content/plugins/hcaptcha-wordpress-plugin
145+
146+
steps:
147+
- name: Checkout code
148+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
149+
with:
150+
path: ${{ env.wp-plugin-directory }}
151+
# Check out the branch ref to ensure we can push back to it
152+
ref: ${{ github.ref }}
153+
154+
- name: Update changelog
155+
working-directory: ${{ env.wp-plugin-directory }}
156+
run: .github/scripts/update-changelog.sh

.github/workflows/create-zip.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
name: Create zip file
1+
name: Create zip
22

33
on:
44
push:
55
workflow_dispatch:
66

77
permissions:
8+
actions: read
89
contents: write
910

1011
jobs:
1112
build-zip:
1213
name: New zip file
1314
runs-on: ubuntu-latest
1415

15-
if: >
16-
(github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[zip]'))
16+
# Security: 1. Check for [zip] tag. 2. Check if user is authorized.
17+
if: |
18+
(github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[zip]')) &&
19+
contains(fromJson('["kagg-design", "e271828-"]'), github.actor)
1720
1821
env:
1922
SLUG: "hcaptcha-for-forms-and-more"

.github/workflows/deploy-readme-assets-to-wp-org.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ on:
33
push:
44
branches:
55
- trunk
6+
permissions:
7+
actions: read
8+
contents: read
69
jobs:
710
trunk:
811
name: Push to trunk

.github/workflows/deploy-to-wp-org.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ name: Deploy to WordPress.org
22
on:
33
release:
44
types: [published]
5+
permissions:
6+
actions: read
7+
contents: write
58
jobs:
69
tag:
710
name: New release
811

912
runs-on: ubuntu-latest
1013

14+
# Security: 1. Check if user is authorized.
15+
if: contains(fromJson('["kagg-design", "e271828-"]'), github.actor)
16+
1117
env:
1218
SLUG: "hcaptcha-for-forms-and-more"
1319

tests/php/integration/Admin/NotificationsTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ public function test_admin_enqueue_scripts(): void {
670670
$expected_extra = [
671671
'group' => 1,
672672
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
673-
'data' => 'var HCaptchaNotificationsObject = ' . json_encode( $params ) . ';',
673+
'data' => 'var HCaptchaNotificationsObject = ' . json_encode( $params, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
674674
];
675675

676676
$subject = new Notifications();

tests/php/integration/Admin/WhatsNewTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public function test_enqueue_assets(): void {
9999
$expected_extra = [
100100
'group' => 1,
101101
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
102-
'data' => 'var HCaptchaWhatsNewObject = ' . json_encode( $params ) . ';',
102+
'data' => 'var HCaptchaWhatsNewObject = ' . json_encode( $params, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
103103
];
104104

105105
$subject = new WhatsNew();

tests/php/integration/FluentForm/FormTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ public function test_print_footer_scripts(): void {
531531
<script type="text/javascript" id="$fluent_forms_conversational_script-js-extra">
532532
/* <![CDATA[ */
533533
var $fluent_forms_conversational_object = $fluent_forms_conversational_json;
534+
//# sourceURL=fluent_forms_conversational_form-js-extra
534535
/* ]]> */
535536
</script>
536537
HTML;
@@ -550,7 +551,7 @@ public function test_print_footer_scripts(): void {
550551
$expected_extra = [
551552
'group' => 1,
552553
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
553-
'data' => 'var HCaptchaFluentFormObject = ' . json_encode( $params ) . ';',
554+
'data' => 'var HCaptchaFluentFormObject = ' . json_encode( $params, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
554555
];
555556
$args = [
556557
'action' => 'hcaptcha_fluentform',
@@ -593,7 +594,7 @@ public function test_admin_enqueue_scripts(): void {
593594
$expected_extra = [
594595
'group' => 1,
595596
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
596-
'data' => 'var HCaptchaFluentFormObject = ' . json_encode( $params ) . ';',
597+
'data' => 'var HCaptchaFluentFormObject = ' . json_encode( $params, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
597598
];
598599

599600
$subject = Mockery::mock( Form::class )->makePartial();

tests/php/integration/Formidable/FormTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ public function test_admin_enqueue_scripts(): void {
273273
$expected_extra = [
274274
'group' => 1,
275275
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
276-
'data' => 'var HCaptchaFormidableFormsObject = ' . json_encode( $params ) . ';',
276+
'data' => 'var HCaptchaFormidableFormsObject = ' . json_encode( $params, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
277277
];
278278

279279
$subject = Mockery::mock( Form::class )->makePartial();

tests/php/integration/Forminator/FormTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ public function test_admin_enqueue_scripts(): void {
261261
$expected_extra = [
262262
'group' => 1,
263263
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
264-
'data' => 'var HCaptchaForminatorObject = ' . json_encode( $params ) . ';',
264+
'data' => 'var HCaptchaForminatorObject = ' . json_encode( $params, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
265265
];
266266

267267
$subject = Mockery::mock( Form::class )->makePartial();

tests/php/integration/GravityForms/FieldTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ public function test_enqueue_admin_script(): void {
317317
$expected_extra = [
318318
'group' => 1,
319319
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
320-
'data' => 'var HCaptchaGravityFormsObject = ' . json_encode( $params ) . ';',
320+
'data' => 'var HCaptchaGravityFormsObject = ' . json_encode( $params, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
321321
];
322322

323323
self::assertFalse( wp_script_is( Field::ADMIN_HANDLE ) );

0 commit comments

Comments
 (0)