Join our Newsletter — 33% off our NHI Course

What are the signs that a workflow input is being used unsafely in a composite action?

A common warning sign is any composite action that copies issue text, pull request fields, or other external input into shell variables without sanitisation. Another signal is inline bash that interpolates those values directly into commands. If the workflow depends on user-controlled content to decide execution and the permissions are broad, the action may be exposing a command injection path.

What unsafe workflow input looks like inside a composite action

The warning signs are usually visible in the way data moves from the workflow boundary into executable logic. If a composite action takes issue text, pull request fields, or other user-controlled values and stores them in shell variables without sanitisation, the input is no longer just data. If those values are then interpolated into bash, path arguments, or command fragments, the action has crossed from handling input to executing it.

Composite actions are especially easy to misuse because they often feel like reusable glue code rather than security-sensitive code. That mindset leads teams to trust workflow inputs too early, especially when the input came from a familiar trigger such as a pull request comment, issue body, or dispatch payload. Once the action makes execution decisions from that content, the question is no longer just “is it valid?”, but “can it change command behaviour?”

A second sign is broad permissions combined with user-controlled branching logic. If the action decides what to run based on external content and the workflow token can write, deploy, or modify repository state, the input can become an attack path rather than a convenience feature. The risk is highest when the composite action blends parsing, decision-making, and execution in the same step.

How to recognise the command-injection pattern

Unsafe handling often follows a predictable pattern: take untrusted workflow context, assign it to a variable, and then use that variable inside an inline shell command. The danger is not limited to obvious semicolons or backticks. Even apparently harmless interpolation can become unsafe when the shell expands whitespace, quotes, glob patterns, or command substitutions in unexpected ways.

Another signal is when the action treats workflow input as trusted control data, such as using it to pick a branch, select a file, or decide which command path to execute, without constraining the allowed values. That pattern is risky when the allowed set is implicit instead of explicit. A safe composite action makes the permitted values narrow and predictable, and fails closed when the input falls outside that set.

It is also a warning sign when the action has to “clean up” the input right before execution, especially with ad hoc string replacements or partial escaping. That often means the workflow design accepted the wrong level of trust at the start. Sanitisation is much easier to reason about when the action separates data validation, command construction, and execution into distinct steps.

What good looks like in a composite action review

The safer pattern is to treat workflow inputs as untrusted until proven otherwise, then keep them out of direct shell interpolation. A composite action should prefer explicit allowlists, quoted parameters, structured inputs, and dedicated action parameters over free-form command construction. Where shell use is unavoidable, the command should be deterministic enough that the input cannot change the meaning of the command itself.

Reviewers should also check whether the action can be refactored so the workflow decides policy and the composite action only performs a bounded operation. That separation matters because a composite action that both interprets user input and executes commands has a much larger blast radius than one that only consumes prevalidated values. If the action must touch repository content, pull request metadata, or comment text, the safest posture is to minimise what that input can influence.

For implementation detail and defensive coding patterns, the OWASP Cheat Sheet Series is a useful reference for input handling, and the OWASP API Security Top 10 is helpful when the same trust problem appears in machine-readable inputs and execution paths.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP ASVS, CIS Controls v8 and NIST SP 800-53 Rev 5 set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
OWASP ASVS V2 — Validation and Business Logic Unsafe workflow input handling is an input-validation and control-flow problem.
V15 — Secure Coding and Architecture Composite actions become unsafe when architecture lets untrusted data reach execution logic.
Recommendation — Validate workflow inputs before they influence command construction or execution flow. Separate untrusted input handling from command execution in the action design.
CIS Controls v8 CIS-16 — Application Software Security Composite action command injection is a software security weakness that needs secure coding practices.
Recommendation — Review reusable workflow code for injection-prone patterns and unsafe interpolation.
NIST SP 800-53 Rev 5 SI-10 — Information Input Validation The issue is unsafe handling of workflow-supplied input before use in commands.
AC-6 — Least Privilege Broad workflow permissions magnify the impact of unsafe input-driven execution.
Recommendation — Validate and constrain workflow inputs before they are consumed by shell logic. Limit workflow permissions so injected commands cannot perform unnecessary actions.

Practitioner Guidance

What to prioritise: Review any composite action that mixes user-controlled workflow input with bash, especially where the input can influence command text, file paths, or conditional execution. Prioritise actions that run with write, deploy, or release permissions because the impact of a mistake is much higher there.

What to verify: Confirm that the action does not pass raw issue, pull request, or dispatch content into shell commands. Verify that every user-controlled field has an explicit allowed-value set, and that the workflow still behaves safely when the input is empty, malformed, or adversarially crafted.

Common mistake: Teams often assume that quoting alone makes interpolation safe. In practice, the safer test is whether the input can alter command structure, execution flow, or the set of files and targets the action touches.

Practitioner takeaway: If untrusted workflow input can affect command construction, the composite action should be treated as a potential injection surface until the input is bounded, validated, and kept out of direct execution paths.