Back to skill

Security audit

GitHub Actions Cache Hardening Audit

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local GitHub Actions cache-audit helper with no evidence of credential theft, persistence, network access, or destructive behavior.

Reasonable to install as a lightweight local checker, but keep `WORKFLOW_GLOB` scoped to workflow files and do not treat its results as a complete security gate until multiline YAML parsing limitations are fixed or independently reviewed.

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
scripts/cache-hardening-audit.sh:95
Finding
Multiline YAML Values Bypass Cache Security Checks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cache-hardening-audit.sh`, lines 95–98, 139–160, and 190–211 **Vulnerability Type**: Incomplete parsing of YAML block scalar values **Risk Level**: Medium ### Vulnerable Code ```python restore_key_re = re.compile(r"^\s*-\s*(.+?)\s*$") path_re = re.compile(r"^\s*path\s*:\s*(.+?)\s*(?:#.*)?$") with_re = re.compile(r"^\s*with\s*:\s*$") ``` ```python key_value = None restore_keys = [] path_values = [] base_indent = len(line) - len(line.lstrip(' ')) saw_with_block = False for follow_idx in range(idx + 1, len(lines) + 1): follow = lines[follow_idx - 1] stripped = follow.strip() if not stripped: continue indent = len(follow) - len(follow.lstrip(' ')) if indent <= base_indent and (stripped.startswith('- ') or stripped.startswith('uses:') or stripped.startswith('name:') or re.match(r'^\w', stripped)): break if with_re.match(follow): saw_with_block = True continue key_match = key_re.match(follow) if key_match: key_value = key_match.group(1).strip().strip('"\'') continue path_match = path_re.match(follow) if path_match: path_values.append(path_match.group(1).strip().strip('"\'')) continue if saw_with_block and stripped.startswith('- '): rk = restore_key_re.match(follow) if rk: restore_keys.append(rk.group(1).strip().strip('"\'')) ``` ```python broad_restore = [rk for rk in restore_keys if rk.endswith('-') and rk.count('-') <= 2] if broad_restore: step_weight += 1 step_issues.append({ 'code': 'broad_restore_keys', 'message': 'restore-keys appears broad and may over-share cache entries across contexts.', 'lines': [idx], 'weight': 1, 'details': broad_restore[:5], }) sensitive_hits = [] for value in path_values: lowered = value.lower() for token in sensitive_path_tokens: if token in lowered: ...[truncated 3442 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the line-oriented regular-expression parser with a safe YAML parser and inspect the resulting workflow structure. 2. Parse each job's `steps` collection and identify cache actions by the normalized `uses` value. 3. Read `with.path`, `with.key`, and `with.restore-keys` as structured YAML values, supporting both scalar and sequence representations. 4. Split multiline `path` and `restore-keys` scalar values into individual normalized entries before applying security checks. 5. Support literal and folded block scalar forms, including `|`, `|-`, `|+`, `>`, `>-`, and `>+`. 6. If a YAML parser cannot be introduced, implement indentation-aware block scalar handling that tracks the parent field and consumes all subordinate lines. This is less reliable than structured YAML parsing and should be treated as a temporary mitigation. 7. Add regression tests for: - Literal and folded multiline paths. - Sensitive paths including `.ssh`, `.aws`, `.npmrc`, `.pypirc`, and `.git`. - Multiline broad `restore-keys` prefixes. - Quoted and unquoted scalar values. - Multiple cache steps in one job. - Comments, blank lines, chomping indicators, expressions, and YAML sequences. 8. Fail safely or emit a prominent parse warning when workflow syntax cannot be interpreted reliably, rather than silently treating the workflow as safe. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Credential Access

High
Category
Privilege Escalation
Content
- `actions/cache` usage on untrusted triggers (`pull_request_target`)
- Cache keys that do not use `hashFiles(...)`
- Overly broad `restore-keys` prefixes
- Sensitive paths accidentally included in cache paths (`.aws`, `.ssh`, `.npmrc`, `.git`)
- Floating cache action refs (`@main`, `@master`)

## Inputs
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- `actions/cache` usage on untrusted triggers (`pull_request_target`)
- Cache keys that do not use `hashFiles(...)`
- Overly broad `restore-keys` prefixes
- Sensitive paths accidentally included in cache paths (`.aws`, `.ssh`, `.npmrc`, `.git`)
- Floating cache action refs (`@main`, `@master`)

## Inputs
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill instructs users to run bash and statically audit workflow files, which implies file-reading capability, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates unnecessary ambiguity about what the skill is permitted to access and weakens least-privilege controls, making misuse or overbroad execution more likely in an agent environment.

Static analysis

No suspicious patterns detected.