T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/gha_linter.py:454
- Finding
- Multiline run blocks evade shell-injection and direct-secret checks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gha_linter.py:454-477` and `scripts/gha_linter.py:539-544` **Vulnerability Type**: Incomplete security analysis of multiline YAML scalar values **Risk Level**: Medium ### Vulnerable Code ```python # shell injection: ${{ }} in run blocks expr_pattern = re.compile(r'\$\{\{.*?\}\}') for i, line in enumerate(lines): stripped = line.strip() # only flag in run: blocks or env values if 'run:' in line or (stripped.startswith('run:') or stripped.startswith('- run:')): exprs = expr_pattern.findall(line) for expr in exprs: inner = expr[3:-2].strip() # check for untrusted contexts for ctx in UNTRUSTED_CONTEXTS: ctx_plain = ctx.replace('*', '') if ctx_plain in inner or (ctx in inner): issues.append(Issue('shell-injection', 'error', f'Expression `{expr}` in run: may be vulnerable to injection via `{ctx}`', i + 1)) break else: # general warning for any expression in run if 'secrets.' not in inner and 'env.' not in inner and 'needs.' not in inner and 'steps.' not in inner and 'matrix.' not in inner and 'inputs.' not in inner: if 'github.event' in inner: issues.append(Issue('untrusted-context', 'warning', f'Expression `{expr}` in run: uses event context — verify it is safe', i + 1)) ``` ```python # secrets directly in run: instead of env: for i, line in enumerate(lines): if 'run:' in line or line.strip().startswith('run:'): if '${{ secrets.' in line: issues.append(Issue('env-in-run', 'warning', f'Secret used directly in `run:` — prefer passing via `env:` for security', i + 1)) ``` ### Technical Analysis The implementation scans individ ...[truncated 2134 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Analyze parsed step objects rather than searching only raw declaration lines. - For every job step with a `run` value, inspect the complete scalar value, including literal and folded multiline blocks. - Preserve source-position metadata for each scalar so findings can identify the exact expression line. - Check every expression in the complete command body against the untrusted-context list. - Detect direct secret interpolation throughout the complete command body. - Recommend assigning expressions to environment variables and referencing safely quoted shell variables. - Add regression tests for `run: |`, `run: >`, multiline commands containing untrusted event fields, and multiline direct secret references. - Where practical, model the selected shell because quoting and metacharacter behavior differ between Bash, PowerShell, and other shells. ]]>
