GitHub Security Alert Fixer

Systematically analyzes and fixes GitHub CodeQL security alerts with proper documentation and testing

$ 설치

git clone https://github.com/bigandslow/cproj /tmp/cproj && cp -r /tmp/cproj/.claude/github-security-fixer ~/.claude/skills/cproj

// tip: Run this command in your terminal to install the skill


name: GitHub Security Alert Fixer description: Systematically analyzes and fixes GitHub CodeQL security alerts with proper documentation and testing

GitHub Security Alert Fixer

Purpose

Automates the process of fixing GitHub CodeQL security alerts by:

  • Fetching and analyzing security alerts from GitHub API
  • Grouping issues by type and severity
  • Applying standardized fixes
  • Ensuring all changes pass CI/CD checks

When to Use

  • When GitHub security alerts need to be addressed
  • After security scans identify code quality issues
  • Before merging PRs with security warnings
  • During periodic security maintenance

Core Workflow

1. Fetch and Analyze Alerts

gh api /repos/{owner}/{repo}/code-scanning/alerts?state=open --paginate | \
python3 -c "
import sys, json
alerts = json.load(sys.stdin)
print(f'Total open alerts: {len(alerts)}')

by_rule = {}
for alert in alerts:
    rule_id = alert['rule']['id']
    if rule_id not in by_rule:
        by_rule[rule_id] = {'count': 0, 'alerts': []}
    by_rule[rule_id]['count'] += 1
    by_rule[rule_id]['alerts'].append({
        'file': alert['most_recent_instance']['location']['path'],
        'line': alert['most_recent_instance']['location']['start_line'],
        'message': alert['most_recent_instance']['message']['text']
    })

for rule_id, data in sorted(by_rule.items(), key=lambda x: -x[1]['count']):
    print(f'\n{rule_id}: {data[\"count\"]} instances')
    for alert in data['alerts'][:3]:
        print(f\"  {alert['file']}:{alert['line']}\")
"

2. Common Fixes by Alert Type

py/stack-trace-exposure (MEDIUM/HIGH Severity)

Problem: Stack traces exposed to external users through error responses

Fix:

# Before
except Exception as e:
    raise HTTPException(status_code=400, detail=str(e)) from e

# After
import structlog
logger = structlog.get_logger(__name__)

except Exception as e:
    logger.error("Operation failed", exc_info=e, context=value)
    raise HTTPException(status_code=400, detail="Operation failed")

Key Points:

  • Use structured logging with exc_info=e for server-side logs
  • Return generic error messages to clients
  • Include context fields for debugging (not sensitive data)

py/empty-except

Problem: Empty except blocks without explanatory comments

Fix:

# Before
except Exception:
    pass

# After
except Exception:
    # Ignore cleanup errors - already processed the transaction
    pass

Comment Templates:

  • Cleanup: # Ignore cleanup errors - already processed the transaction
  • Parsing: # Invalid date format - try next parsing method
  • Optional operations: # Skip {operation} that can't be read during {context}
  • Test code: # Test continues - checking for {condition} regardless of success

py/unused-local-variable

Problem: Variables assigned but never used

Fix:

# Before
result = expensive_operation()

# After - Prefix with underscore if intentionally unused
_result = expensive_operation()

# Or remove if truly unnecessary
expensive_operation()

Auto-fix command:

ruff check --select F401,F841 --fix --unsafe-fixes .

js/unused-local-variable

Problem: Unused TypeScript/JavaScript variables or imports

Fix:

// Before
import { unusedImport } from './module';
const unusedVar = getValue();

// After - Remove entirely
// (no import needed)

Batch fix with sed:

sed -i.bak 's/const unusedVar/const _unusedVar/' file.ts

py/ineffectual-statement

Problem: Statement with no effect (typically incomplete validation)

Fix:

# Before
expected_value  # Statement has no effect

# After
# Note: expected_value validation could be added here if needed

3. Project-Specific Configuration

Update Linting Rules

Add ignores to pyproject.toml only for technical debt:

[tool.ruff.lint]
ignore = [
    "S110",  # try-except-pass (TODO: Fix and re-enable - 11 instances)
    "S112",  # try-except-continue (TODO: Fix and re-enable - 9 instances)
]

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "S105", "S106"]  # Allow test credentials

Coverage Configuration

Ensure pytest coverage is properly configured:

# apps/api/pytest.ini
[pytest]
addopts =
    --cov=app
    --cov-fail-under=15

4. Testing & Validation

Run full build without cache:

pnpm build --force

Run Python linting:

ruff check .
poetry run mypy .
poetry run pytest

Commit pattern:

git add -A
git commit -m "fix: address {issue-type} security alerts

- {Specific fixes applied}
- {Files affected}

Addresses CodeQL alerts:
- {rule-id} ({count} instances)
"

5. CI/CD Considerations

Always:

  • ✅ Run full build locally before pushing
  • ✅ Wait for all CI checks to pass
  • ✅ Verify CodeQL analysis completes
  • ✅ Check no new alerts introduced

Common CI Issues:

  • pnpm version mismatch: Remove hardcoded version from workflows, use packageManager field
  • Coverage failures: Check pytest.ini configuration
  • Type check failures: May be cached locally - use --force flag

Priority Order

  1. CRITICAL/HIGH Severity - Fix immediately

    • Stack trace exposure (CWE-209, CWE-497)
    • SQL injection vulnerabilities
    • Authentication bypasses
  2. MEDIUM Severity - Fix in current sprint

    • Information disclosure
    • Missing input validation
    • Weak cryptography
  3. LOW/NOTE Severity - Address in maintenance cycles

    • Empty except blocks
    • Unused variables
    • Code style issues

Success Criteria

  • ✅ All high/medium severity alerts resolved
  • ✅ CI/CD pipeline passes
  • ✅ No new alerts introduced
  • ✅ Technical debt documented in code comments or TODOs
  • ✅ Linting rules updated to prevent recurrence

Common Pitfalls

Don't:

  • Suppress alerts without fixing root cause
  • Use broad try/except without logging
  • Return stack traces to clients
  • Commit with failing tests
  • Skip security checks in CI

Do:

  • Add explanatory comments to all exception handlers
  • Use structured logging for errors
  • Test locally before pushing
  • Document technical debt with TODO comments
  • Update linting rules to catch similar issues

Example Session

# 1. Analyze alerts
gh api /repos/{owner}/{repo}/code-scanning/alerts?state=open --paginate

# 2. Create todo list for tracking
# Use TodoWrite tool with specific tasks

# 3. Fix by category
ruff check --select F401,F841 --fix .  # Auto-fix unused imports/vars
# Manually fix security issues with proper logging

# 4. Test
pnpm build --force
poetry run pytest

# 5. Commit and push
git add -A
git commit -m "fix: address security alerts"
git push

# 6. Verify CI passes
gh run list --limit 3

Integration

This skill works best with:

  • GitHub API access (gh CLI installed)
  • Ruff and mypy configured
  • Structured logging (structlog)
  • CI/CD with CodeQL enabled