T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/permission-scope-audit.sh:104
- Finding
- Valid YAML Syntax Can Bypass Permission-Risk Detection## Vulnerability Details **File Location**: `scripts/permission-scope-audit.sh`, lines 104–175 **Vulnerability Type**: Incomplete security analysis caused by regex-based YAML parsing **Risk Level**: Medium ### Vulnerable Code ```python def extract_event_set(lines): events = set() in_on = False on_indent = -1 for line in lines: stripped = line.strip() if not stripped or stripped.startswith('#'): continue indent = len(line) - len(line.lstrip(' ')) if re.match(r'^on\s*:\s*$', line): in_on = True on_indent = indent continue if in_on: if indent <= on_indent and stripped: in_on = False else: match = trigger_key_re.match(stripped) if match: events.add(match.group(1)) return sorted(events) ``` ```python if re.match(r'^\s*permissions\s*:\s*$', line): permissions_blocks += 1 in_permissions = True permission_indent = indent continue if in_permissions and indent <= permission_indent and stripped: in_permissions = False if in_permissions: write_match = write_scope_re.match(line) if write_match: scope = write_match.group(1) permission_entries.append( {'line': idx, 'scope': scope, 'value': 'write'} ) continue inline_match = re.match( r'^\s*permissions\s*:\s*([^#]+?)\s*(?:#.*)?$', line ) if inline_match: value = inline_match.group(1).strip().strip('"\'') lowered = value.lower() if lowered in {'write-all', 'read-all'}: permission_entries.append( {'line': idx, 'scope': lowered, 'value': lowered} ) ``` ### Technical Analysis The security scanner interprets GitHub Actions workflow YAML through line-oriented regular expressions rather than a YAML parser. Trigger extraction only recognizes a bare block-form `on:` key followed by separately indented event keys ...[truncated 2693 chars]
- Remediation
- ## Remediation Suggestions 1. Replace line-oriented regular-expression parsing with a maintained YAML parser. 2. Parse and normalize the workflow-level and job-level `permissions` nodes, supporting: - Block mappings - Flow mappings - Scalar `read-all` and `write-all` values - Empty mappings and `permissions: {}` - Quoted keys and values 3. Normalize the `on` node across all valid representations: - Scalar events - Event lists - Block mappings - Flow mappings 4. Ensure YAML 1.1 boolean coercion does not incorrectly convert the GitHub Actions key `on`; use a loader with suitable YAML semantics or explicitly account for this behavior. 5. Treat malformed YAML, unsupported node types, and parser failures as policy-gate failures when enforcement mode is enabled. 6. Add regression fixtures covering at least: ```yaml on: pull_request_target permissions: write-all ``` ```yaml on: [pull_request_target] permissions: {contents: write} ``` ```yaml "on": pull_request_target: "permissions": contents: write ``` 7. Test workflow-level and job-level permissions separately, including cases where job permissions override or restrict workflow defaults. 8. Add an automated assertion that each dangerous fixture produces the expected critical classification and a nonzero exit status when `FAIL_ON_CRITICAL=1`.
