The caption checker needs details from a pull request
A museum accepts caption corrections through pull requests and wants CI to flag missing language files and inaccurate metadata before merging. The checker needs to know which event started the job, which repository it concerns, and possibly which captions changed. GitHub Actions supplies GITHUB_EVENT_PATH, a path to a JSON file containing the triggering webhook payload. That sounds convenient, but pull request titles, branch names, descriptions, and other event fields may be controlled by contributors. A workflow that drops those strings directly into a generated shell script can execute text that was supposed to be mere data. The task is to parse the event safely and keep the QA job unprivileged. This is a design example, not a report of an observed exploit.
Know what GITHUB_EVENT_PATH contains
GitHub’s variables reference describes GITHUB_EVENT_PATH as the filesystem path to the complete event webhook payload for the job. The variable is a file location, not a JSON string and not itself a trusted description of a pull request. Read the file with an ordinary JSON parser in the programming language used by the checker. Check GITHUB_EVENT_NAME or other trusted workflow configuration to decide which event shape to expect. A pull_request event and a workflow_dispatch event will not have identical fields, and an absent optional property should be handled explicitly. Do not assume the file names or branches in the payload are safe paths on the runner.
Keep dynamic fields out of inline shell expressions
GitHub warns that contexts such as pull request titles and bodies can lead to script injection when substituted directly into a run block. Expressions are expanded before the generated shell script executes. A string that contains quotes, delimiters, or shell syntax may therefore escape an intended string assignment. Prefer a parser that reads GITHUB_EVENT_PATH as data and applies schema checks instead of stitching attacker-controlled content into a command line. When passing a simple value to a process, use a safe environment variable or argument array and avoid eval, dynamic shell construction, and unquoted interpolation. The first diagram separates path discovery, JSON parsing, and validation instead of blending them into one shell command.

Validate event identity and expected structure
A robust caption checker verifies that the event type matches the workflow’s intended trigger and that expected fields have the correct types. It should compare the repository and pull request identity with the job’s approved scope, not accept arbitrary JSON paths as instructions. If a field is absent or too large, fail with a helpful diagnostic rather than guessing. Treat branch names, labels, filenames, and title text as untrusted strings, even when their values look conventional. A schema that accepts only the fields needed by the QA task reduces the blast radius of later mistakes. Keep any internal parsing error messages from dumping the full event payload into the job log.
Read changed files from an authoritative source
The event JSON can tell the checker which pull request initiated the workflow, but it is not a guaranteed complete file-diff API. Use the appropriate GitHub API or a carefully configured checkout and diff procedure to determine which caption files changed, with permissions limited to reading the repository and pull request as needed. Validate that each selected relative path stays inside the expected captions directory and has an allowed extension. Reject absolute paths and traversal sequences after normalization, and never run a user-named executable because it appeared in an event field. The comparison drawing contrasts risky shell interpolation with structured parsing plus an allowlist. It shows an approach, not actual code execution output.
Choose a safe trigger and token scope
The security boundary depends on more than parsing. Workflows triggered from untrusted pull requests should avoid broad write credentials, unnecessary secrets, and privileged checkout patterns. GitHub’s security documentation explains that event payload fields are an untrusted input channel. Pay special attention to pull_request_target, which runs with different repository context and can become dangerous when combined with checking out untrusted head code. If the QA task only reads caption text and reports a result, set the GITHUB_TOKEN permissions to the least privilege needed. Keep publishing or deployment tasks in a separate reviewed job after explicit approval. Parsing JSON safely does not make arbitrary scripts from a pull request safe to execute.

Do not mistake a passing parser for passing caption QA
A structured parser can reject malformed input but cannot judge caption timing, language completeness, or accessibility requirements by itself. After extracting safe references, run the approved caption checker on reviewed files and propagate nonzero failures to the required status check. Distinguish missing expected output, a tool crash, and content that fails the editorial rule. Avoid placing entire visitor transcripts into summary logs or public artifacts. A useful report names the file, check category, and controlled evidence location, while withholding restricted conversation text. Event parsing is an early security step in a larger release process, not an approval signal.
Exercise hostile fixtures without exposing secrets
Create synthetic webhook JSON with a quote-heavy title, an unusual branch name, oversized strings, absent optional fields, and a malicious-looking path. Test that the parser treats each string as inert data and rejects out-of-scope filenames. Also test the proper event type, an unexpected event type, and a pull request from a fork under the workflow’s chosen permissions. Inspect logs for accidental payload dumps and confirm that no token or secret reaches an untrusted process. These are suggested test cases, not tests executed for this guide. Keep the fixtures in a dedicated test environment and do not treat a locally passing parser as proof the entire GitHub workflow is safe.

Make the review boundary easy to audit
Record which payload fields the checker reads, why they are necessary, the parser version, allowed caption paths, permitted triggers, and token permissions. The reviewer should be able to trace the flow from webhook file to validated file selection without encountering shell code assembled from user text. When workflows change, review the trust boundary again, especially if new privileged actions, third-party actions, or deployment steps are added. GitHub’s own guidance remains the authority for supported event variables and security expectations. The outcome to aim for is a caption review job that interprets event metadata as data and grants no more authority than the review needs.
How We Research
Our primary named official sources were: GitHub Actions variables reference; GitHub script injection guidance; GitHub secure use reference. We reviewed GitHub’s documented GITHUB_EVENT_PATH variable and script-injection guidance, plus the Actions secure-use reference. We did not execute a workflow, run a malicious pull request, or test repository permissions. The diagrams are conceptual and illustrate data-flow boundaries rather than a real GitHub runner screenshot. Readers should verify current deployment-specific documentation and their own permissions before adopting a workflow. Any figures are original instructional diagrams, not actual vendor screenshots or observed results.
Frequently Asked Questions
No. It is the path to a runner file containing the event webhook payload.
No. GitHub explicitly treats these context values as potentially untrusted input.
Do not assume so. Query or compute changes through an appropriate authoritative and bounded mechanism.
No. Trigger choice, checkout behavior, token permissions, secrets, and executed code still need separate review.
No. The caption checker must run actual content tests and propagate failures to required job status.
