Back to skill

Security audit

Github Actions Gen

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed GitHub Actions helper, but its file-scanning command is implemented unsafely and can unexpectedly expose local secret-like lines.

Review this before installing. The workflow generation parts are simple, but the secrets command should be fixed to use the first shifted argument, quote file paths, add -- before the filename, validate regular files, and clearly warn that matching lines may be printed. Avoid using the secrets command on sensitive workspaces until that is corrected.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
" grep -in 'secret\|token\|password' $2 2>/dev/null && echo 'WARN: Hardcoded secrets found' || echo 'Clean' } ``` ```bash main() { local cmd="${1:-help}" case "$cmd" in create) shift; cmd_create "$@" ;; template) shift; cmd_template "$@" ;; lint) shift; cmd_lint "$@" ;; list) shift; cmd_list "$@" ;; optimize) shift; cmd_optimize "$@" ;; secrets) shift; cmd_secrets "$@" ;; help) cmd_help ;; version) cmd_version ;; *) die "Un ...[truncated 2872 chars]:142
Finding
Grep Option Injection and Unintended Local File Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/script.sh:142-144, 166-172` **Vulnerability Type**: Unquoted argument expansion and incorrect positional argument handling **Risk Level**: Medium ### Vulnerable Code ```bash cmd_secrets() { local file="${2:-}" [ -z "$file" ] && die "Usage: $SCRIPT_NAME secrets <file>" grep -in 'secret\|token\|password' $2 2>/dev/null && echo 'WARN: Hardcoded secrets found' || echo 'Clean' } ``` ```bash main() { local cmd="${1:-help}" case "$cmd" in create) shift; cmd_create "$@" ;; template) shift; cmd_template "$@" ;; lint) shift; cmd_lint "$@" ;; list) shift; cmd_list "$@" ;; optimize) shift; cmd_optimize "$@" ;; secrets) shift; cmd_secrets "$@" ;; help) cmd_help ;; version) cmd_version ;; *) die "Unknown: $cmd" ;; esac } ``` ### Technical Analysis The command dispatcher removes the command name with `shift`, making the documented file argument available as `$1`. However, `cmd_secrets` incorrectly reads and executes against `$2`. Consequently, a normal invocation such as `script.sh secrets workflow.yml` fails because `$2` is unset, while an invocation containing an extra argument causes the second supplied value to control `grep`. The value is also expanded without quotation and is not preceded by the `--` end-of-options delimiter: ```bash grep -in 'secret\|token\|password' $2 ``` Shell word splitting and pathname expansion can therefore turn one attacker-controlled value into multiple arguments. Values beginning with a hyphen may also be interpreted as `grep` options rather than as file names. For example, GNU `grep` can interpret `-r` as a recursive-search option, causing the command to search the current directory instead of one explicitly selected file. The same incorrect `$2` convention appears in the other parameterized handlers, including `create`, `template`, `lint`, and `optimize`. Those occurrences pri ...[truncated 1609 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Read `$1` after the dispatcher performs `shift`. 2. Use the validated local variable consistently rather than reading positional parameters again. 3. Quote every file path to prevent word splitting and pathname expansion. 4. Place `--` before user-controlled file names passed to `grep`. 5. Validate that the input identifies a regular file before scanning it. 6. Return a nonzero status for missing or invalid files instead of reporting them as clean. 7. Apply the same positional-argument and quoting corrections to `create`, `template`, `lint`, and `optimize`. A hardened implementation is: ```bash cmd_secrets() { local file="${1:-}" [ -n "$file" ] || die "Usage: $SCRIPT_NAME secrets <file>" [ -f "$file" ] || die "File not found: $file" if grep -in -- 'secret\|token\|password' "$file"; then echo 'WARN: Potential hardcoded secrets found' else echo 'Clean' fi } ``` The other handlers should likewise use `${1:-}` after dispatch: ```bash cmd_lint() { local file="${1:-}" [ -n "$file" ] || die "Usage: $SCRIPT_NAME lint <file>" [ -f "$file" ] || die "File not found: $file" grep -c -- 'runs-on' "$file" | awk '{if ($1 == 0) print "WARN: No runs-on"}' } ``` ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code partially matches the declared purpose because it can generate simple GitHub Actions YAML snippets via the create and template commands. However, its behavior is broader than 'Generate GitHub Actions workflow YAML files' alone. It also analyzes existing files (lint), scans them for secret/token/password patterns (secrets), and provides optimization suggestions, which are distinct capabilities not represented in the description. These are materially undeclared features, though they remain related to GitHub Actions workflows rather than being malicious or unrelated. Therefore this is a description-behavior mismatch due to undeclared capabilities.

Session Persistence

Medium
Category
Rogue Agent
Content
### `create`

```bash
scripts/script.sh create <type>
```

### `template`
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Whitespace Padding

Medium
Category
Prompt Injection
Content
DATA_DIR="$HOME/.local/share/github-actions-gen"
mkdir -p "$DATA_DIR"

#
#
#
#
Confidence
80% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The manifest description is narrowly framed around generating workflow YAML for CI/CD setup. In addition to generation helpers, the script implements `lint` and `secrets` commands that inspect user-supplied files and search their contents, which is a materially broader behavior than simple workflow generation.

Context-Inappropriate Capability

Medium
Confidence
85% confidence
Finding
A skill described as generating GitHub Actions YAML would be expected to emit templates or scaffolds. Searching arbitrary files for `secret`, `token`, or `password` introduces a scanning capability that is not an obvious requirement of workflow generation and is not declared in the manifest description.

Missing User Warnings

Low
Confidence
83% confidence
Finding
The `secrets` command scans an arbitrary file path supplied by the user and inspects its contents for secret-like terms, but there is no comment, docstring, or user-facing warning explaining that the command will read the file contents. For a code file, file access affecting potentially sensitive data should include some disclosure when the behavior is not otherwise documented in this file.

Static analysis

No suspicious patterns detected.