Skip to content

Add eslint-plugin-playwright enforcement with secure CI workflow - #26515

Merged
karanh37 merged 3 commits into
playwright-eslint-enforcement-v2from
copilot/sub-pr-26494
Mar 16, 2026
Merged

Add eslint-plugin-playwright enforcement with secure CI workflow#26515
karanh37 merged 3 commits into
playwright-eslint-enforcement-v2from
copilot/sub-pr-26494

Conversation

Copilot AI commented Mar 16, 2026

Copy link
Copy Markdown
Contributor

Adds eslint-plugin-playwright to catch common Playwright anti-patterns and wires it into a secured CI workflow that runs on PRs touching playwright/ files.

ESLint Rule Configuration

Blocking (error) — fails CI immediately:

Rule Catches
no-networkidle waitForLoadState('networkidle') — unreliable with websockets/polling
no-page-pause page.pause() — debug statements left in code
no-focused-test test.only() / describe.only() — accidentally committed focus

Aspirational (warn) — tracks tech debt: missing-playwright-await, no-wait-for-timeout, no-force-option, no-element-handle, no-eval, no-skipped-test, prefer-web-first-assertions, no-useless-await, no-wait-for-selector, valid-expect

Current baseline: 0 errors, 1657 warnings.

CI Workflow Security (ui-checkstyle.yml)

Converted from pull_requestpull_request_target with the standard repo security pattern:

  • Label gate only on labeled event: trigger types restricted to [labeled] only — prevents TOCTOU attacks where an attacker pushes malicious code after "safe to test" is applied (label persists across pushes); maintainer must re-apply the label after each new commit
  • Explicit fork checkout: checks out github.event.pull_request.head.sha only after label verification passes
  • Removed yarn cache steps: eliminates the actions/cache poisoning vector — fork PRs can no longer inject malicious content into shared caches affecting base-branch runs
  • Removed redundant conditions: dropped if: ${{ github.event_name == 'pull_request_target' }} guards from label-gate steps since pull_request_target is the only trigger

Cleanup

  • Fixed last networkidle usage in ClassificationConditionalRendering.spec.ts
  • Removed 3 stale eslint-disable comments referencing undefined rules (jest/no-export, react-hooks/rules-of-hooks)
  • Updated Playwright Developer Handbook and Playwright skills with ESLint enforcement docs

Type of change:

  • Improvement

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

…h label gating

Co-authored-by: karanh37 <33024356+karanh37@users.noreply.github.com>
Copilot AI changed the title [WIP] Add eslint-plugin-playwright enforcement with CI check Add eslint-plugin-playwright enforcement with secure CI workflow Mar 16, 2026
Copilot AI requested a review from karanh37 March 16, 2026 10:22
Comment thread .github/workflows/ui-checkstyle.yml Outdated
Comment thread .github/workflows/ui-checkstyle.yml Outdated
@karanh37

Copy link
Copy Markdown
Contributor

@copilot address review comments

Co-authored-by: karanh37 <33024356+karanh37@users.noreply.github.com>

Copilot AI commented Mar 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review comments

Addressed both review comments in commit 2450786:

  1. TOCTOU fix: Changed trigger types to [labeled] only — the workflow now only runs when a maintainer applies a label, not on synchronize/opened/etc. This prevents an attacker from pushing malicious code after the "safe to test" label was applied (since labels persist across pushes).

  2. Removed redundant conditions: Dropped if: ${{ github.event_name == 'pull_request_target' }} from both the "Wait for the labeler" and "Verify PR labels" steps — since pull_request_target is the only workflow trigger, these conditions were always true.

@gitar-bot

gitar-bot Bot commented Mar 16, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 2 resolved / 2 findings

Adds eslint-plugin-playwright enforcement with secure CI workflow, addressing TOCTOU vulnerability by using pull_request_target with label gating and removing redundant event_name condition. No open issues remain.

✅ 2 resolved
Security: TOCTOU: synchronize trigger bypasses label gate after push

📄 .github/workflows/ui-checkstyle.yml:15-16 📄 .github/workflows/ui-checkstyle.yml:54-57 📄 .github/workflows/ui-checkstyle.yml:65
The workflow triggers on synchronize events (new pushes) but the "safe to test" label is never automatically removed when new commits are pushed. This creates a time-of-check-to-time-of-use vulnerability:

  1. Attacker opens PR with benign code
  2. Maintainer reviews and adds "safe to test" label
  3. Attacker pushes a malicious commit → synchronize event fires
  4. Label check passes (label persists across pushes)
  5. Malicious code is checked out (github.event.pull_request.head.sha) and executed with sudo make install_antlr_cli, yarn install (lifecycle hooks), and yarn lint:playwright

Since pull_request_target runs with write-scoped GITHUB_TOKEN and the Makefile/package.json come from untrusted PR code, this allows arbitrary code execution in the privileged context.

The safest fix is to remove synchronize from the trigger types so the workflow only runs on labeled (requiring a maintainer to re-apply the label after each push). Alternatively, add a companion workflow that removes the "safe to test" label on every synchronize event.

Quality: Redundant event_name condition is always true

📄 .github/workflows/ui-checkstyle.yml:38 📄 .github/workflows/ui-checkstyle.yml:47
The if: ${{ github.event_name == 'pull_request_target' }} conditions on the "Wait for the labeler" and "Verify PR labels" steps (lines 38 and 47) are always true since pull_request_target is the only trigger for this workflow. These conditions add noise without providing any value.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@karanh37
karanh37 marked this pull request as ready for review March 16, 2026 10:29
@karanh37
karanh37 merged commit 280f217 into playwright-eslint-enforcement-v2 Mar 16, 2026
1 check passed
@karanh37
karanh37 deleted the copilot/sub-pr-26494 branch March 16, 2026 10:29
karanh37 added a commit that referenced this pull request Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants