A museum website repository uses a GitHub Actions workflow to check whether a pull request title follows an editorial naming convention. The title is supplied by the contributor, not trusted CI code. If a workflow inserts that string directly into an inline shell script, the expression may change what the runner executes. This guide explains how to separate data from commands, restrict permissions and review the resulting checks using a harmless fictional title. It is about defensive workflow design, not a recipe for attacking a repository.
Trace each untrusted value before writing a run step
Review workflows for values derived from pull requests, branch names, issue text, commit messages, external API payloads and artifact contents. GitHub documents that properties such as title, body, head_ref and message may be controlled by outside contributors. Record where those values enter the workflow and whether they flow into run scripts, action arguments, file paths or API requests. Identify the trust boundary before deciding how to validate the value.
For a hypothetical museum PR, the accepted title format might start with a category label and issue code. Test with ordinary punctuation, spaces and unexpected unicode as well as empty titles. Do not paste hostile strings into a real repository to prove the issue. A review can reason about the pipeline and use harmless fixtures. Preserve the team’s original policy separately from the expression that reads PR metadata.
Understand expression substitution in inline scripts
GitHub’s script-injection documentation explains that expressions embedded directly in a run block are evaluated and inserted before the shell executes the generated script. Shell quoting around an expression is not, by itself, a reliable boundary between data and code. The risk is easy to overlook because a workflow file can look like a normal conditional check. The editor should inspect the generated execution context, not just the YAML’s visual indentation.

Treat any contributor-controlled value as data even when a format validator will reject it later. Validation happens after the runner has already interpreted the script if unsafe interpolation is used. Avoid using a model or text classifier to label a title as safe while it is being embedded in executable code. Use execution primitives that keep the input out of the shell program text in the first place.
Move data into environment variables or action inputs
GitHub recommends passing untrusted strings through an intermediate environment variable in the relevant step, or supplying them as an input to a well-designed action. The shell then reads a variable as data rather than receiving new shell source constructed from the field. Quote variable expansions appropriately and use a deliberately narrow validation rule. Review how outputs are logged and avoid blindly echoing the raw title into a public job summary.
A minimal safe design sets a step environment variable from the PR title and compares it against an anchored expected pattern. It should fail with a generic explanation if the title does not conform. For reusable workflows, specify exactly which values are accepted. Keep secrets out of the validation step entirely; a naming check almost never needs package publication access or a cloud deployment credential.
Keep untrusted pull requests away from privileged triggers
Separately audit the workflow trigger and token permissions. GitHub warns that pull_request_target and workflow_run contexts can carry special risk if their privileged jobs checkout or execute untrusted contribution code. A pull request validation workflow should normally run with read-only permissions and no deployment secrets. Do not combine an untrusted title check with a publish step merely for convenience.
If a release job needs higher privileges, place it behind trusted branch, environment and approval controls. When an upstream workflow produces artifacts, treat those artifacts as untrusted inputs until validated. The correct design depends on repository policy, but no single successful title check should grant a contributor’s branch authority to alter production. Document which context is trusted at each workflow edge.
Compare vulnerable interpolation with bounded data flow
The first conceptual diagram shows contributor text entering the constructed shell source. The intermediate diagram highlights that adding quotes around the interpolated expression does not reliably turn it into a safe data channel. The reviewed diagram passes the same text as an environment value and runs a fixed validation command with minimal permissions. All three drawings use innocuous placeholder text, not exploit payloads.

The objective is to preserve a clean boundary, not to claim that an environment variable sanitizes every possible downstream use. If a script later evaluates the variable as a new command, the risk returns. Review every downstream consumer and avoid dynamic command construction. Keep the defensive change small enough to code-review, and run a reproducible unit check on harmless edge cases before merging.
Audit third-party actions and workflow dependencies
An external action can also consume untrusted metadata or expose secrets. Review what each action receives, what it logs and which permissions it has. GitHub’s secure-use reference covers dependency pinning, least privilege and trusted action sourcing. Where supported, use the organization’s workflow dependency controls and locked versions; a familiar action name is not evidence that its execution is safe.
Use dependency review and code scanning to flag risky workflow changes, but don’t rely on them as complete security proofs. If a changed PR workflow introduces broad permissions, unexpected network access or secrets in a validation job, hold the merge for manual review. A branch protection check should distinguish ‘workflow ran’ from ‘workflow’s intended validation passed with required isolation.’
Regression-test the trust boundary without live attacks
Prepare fixtures for an ordinary title, missing issue code, long Unicode title, quotes and multiline input. Define expected validation outcomes and confirm that the workflow interprets each value as an input string. A separate code review should check that the workflow never constructs executable text from a repository event field. Use a disposable test repository with no production tokens if runtime verification is necessary.

Review failed-run logs for accidental disclosure of raw input or environment settings. Confirm that a failed title validation does not trigger any artifact publication or release job. This article does not claim a penetration test or verified exploit. Its examples describe defensive checks derived from GitHub’s published trust-boundary guidance, not observed results from a target repository.
Make the release gate prove the correct behavior
Before adopting the revised workflow, confirm reviewers approved the YAML, token permissions are restricted, third-party actions are trusted and the required check covers the relevant branch. Keep a sample of the input format policy in the repository documentation. When the check fails, provide instructions for correcting a title rather than exposing internal execution details or granting an override automatically.
Recheck GitHub documentation as event behavior, security guidance and workflow dependency features evolve. The success criterion is a reliable validation job that treats contributor-controlled information as data and never lets it decide privileged execution. The public documentation and this article are not a security warranty; project maintainers must assess their own CI context and threats.
How We Research
We researched this November 2026 article from named official documentation: GitHub: Script injections; GitHub: Secure use reference; GitHub: Workflow events. We compared documented request parameters and operational limitations with a hypothetical community organization use case, then designed independent human review and regression checks. Images are original fictional educational diagrams, not product screenshots, actual measured benchmark charts or verified customer cases. We did not submit live API requests, upload personal files, process museum assets or measure vendor accuracy. Implementers must verify current endpoint versions, access controls, region support, pricing and retention before deployment. Factual and rights-sensitive results require review of primary sources.
Frequently Asked Questions
No. Treat contributor-controlled metadata as untrusted.
Not reliably. Expressions can be inserted into the script before shell execution.
Pass the value through a step environment variable and validate it as data.
No. Keep title validation read-only and separate from privileged release jobs.
No. Required checks must be designed securely and reviewed themselves.
