Problem: Inline Script Injection
A workflow that reads an issue title into a shell variable without sanitization allows an attacker to inject arbitrary commands:curl command and expose your secret.
Exploit Demonstration
- Open a new issue with the payload above.
- Check workflow logs:
curl runs before your conditional, leaking secrets.
Solution: Use Environment Variables for Expressions
Store GitHub expressions in environment variables. Because Actions resolves${{ }} outside the shell, any injected payload remains inert.
Quoting the expression (
'${{ ... }}') ensures the shell sees it as a literal. Any embedded quotes or commands will not be evaluated.Demonstration of Safe Execution
issue_title, the curl never executes. Your secret remains safe.
Further Security Hardening
Go beyond input sanitization to fully secure your workflows:- Least Privilege: Grant minimal permissions to tokens and service accounts.
- Action Pinning: Pin actions to specific versions or commit SHAs.
- Third-Party Review: Audit community actions before use.
- Avoid Inline Scripts: Use dedicated action steps or scripts in your repo.
Never expose secrets in logs or pass untrusted input to shell commands without sanitization.