Skip to main content
Protect your CI/CD pipelines by ensuring untrusted input cannot execute malicious commands or leak secrets. Inline scripts that interpolate user-controlled data directly in shell code are especially vulnerable.

Problem: Inline Script Injection

A workflow that reads an issue title into a shell variable without sanitization allows an attacker to inject arbitrary commands:
A malicious issue title such as:
would run the curl command and expose your secret.

Exploit Demonstration

  1. Open a new issue with the payload above.
  2. Check workflow logs:
The injected 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

Even though the payload appears in 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.

References

Watch Video