T09 · Insecure Skill Coding Practices
- Location
scripts/permission-scope-audit.sh:104- Finding
Valid YAML Syntax Can Bypass Permission-Risk Detection
- Content
View full analysis
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: MediumVulnerable 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
View remediation
Remediation Suggestions
- Replace line-oriented regular-expression parsing with a maintained YAML parser.
- Parse and normalize the workflow-level and job-level
permissionsnodes, supporting:- Block mappings
- Flow mappings
- Scalar
read-allandwrite-allvalues - Empty mappings and
permissions: {} - Quoted keys and values
- Normalize the
onnode across all valid representations:- Scalar events
- Event lists
- Block mappings
- Flow mappings
- 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. - Treat malformed YAML, unsupported node types, and parser failures as policy-gate failures when enforcement mode is enabled.
- Add regression fixtures covering at least:
yaml on: pull_request_target permissions: write-allyaml on: [pull_request_target] permissions: {contents: write}yaml "on": pull_request_target: "permissions": contents: write- Test workflow-level and job-level permissions separately, including cases where job permissions override or restrict workflow defaults.
- Add an automated assertion that each dangerous fixture produces the expected critical classification and a nonzero exit status when
FAIL_ON_CRITICAL=1.
