Skip to main content
Script injection occurs when untrusted input is interpolated directly into shell commands, allowing attackers to execute arbitrary code. In GitHub Actions workflows, inline shell scripts are especially susceptible if values like issue titles or user inputs are expanded before execution. This guide shows how to move untrusted data into environment variables, ensuring it’s parsed at runtime rather than baked into your script.

Insecure Example

Interpolating untrusted input inside the run block lets attackers inject arbitrary commands.
Never build shell scripts by concatenating or expanding variables directly in the script body.

Secure Approach

By passing untrusted input via the env block, the value is provided to the shell at execution time rather than expanded when the workflow is generated.
Defining issue_title as an environment variable prevents any injected payload from being interpreted as part of the script.
The shell will see it only as data.

Insecure vs. Secure Comparison

Demonstration of Attack Mitigation

Simulate an issue title containing a malicious payload:

Workflow Logs

Output:
No external curl request is executed—only the intended logic runs.

HTTP Dump Confirmation

Inspecting the HTTP dump shows only the initial probe requests, confirming no secrets were exfiltrated:

Further Reading

References

Watch Video