If you are looking for a Python security scanner for GitHub Actions, the highest-leverage place to add it is the pull-request workflow.

If you're running a Python project on GitHub and you don't have automated security scanning, each PR relies entirely on manual review. Hardcoded secrets, SQL injection patterns, dead code, and AI-generated bugs can slip through.

This guide shows you how to set up automated Python security and quality scanning in GitHub Actions using Skylos, from an initial local scan to a PR-blocking quality gate.


Why scan Python code in CI

Manual code review catches logic problems. It's bad at catching:

  • Hardcoded secrets — API keys and passwords that look like config values
  • SQL injection patterns — string formatting in database queries
  • Dead code — functions nobody calls that expand your attack surface
  • Weak cryptography — MD5/SHA1 used for hashing passwords
  • AI-generated problems — registry-backed nonexistent dependencies, undeclared imports, missing members on resolvable local modules, and disabled SSL verification

These are patterns static analysis is designed to catch automatically. To make a failed scan block merge, configure the Skylos job as a required status check in GitHub branch protection or a ruleset.


Local first, then GitHub Actions

Even if the target workflow is GitHub Actions, the fastest sanity check is still local:

pip install skylos
skylos . -a

If the findings are useful on a real repository, then move the same workflow into GitHub Actions with skylos cicd init.

If you also need to secure the workflow itself, not just scan the code running inside it, read How to Secure GitHub Actions for Python Repos.


Option 1: One-command setup with Skylos

The fastest way to add Python security scanning to GitHub Actions:

pip install skylos
skylos cicd init

This writes .github/workflows/skylos.yml. The generated workflow is the source of truth for the installed Skylos version. It currently:

  • checks out full Git history so the pull-request base can be resolved
  • scans the enabled categories and writes a JSON result
  • uses --diff-base and --diff on pull requests while retaining repository context
  • runs skylos cicd gate for the status check and job summary
  • runs skylos cicd annotate for GitHub Actions annotations
  • runs skylos cicd review for pull-request review comments

The local scan needs no Skylos API key. The review step uses GitHub's built-in token, and optional Cloud workflows use GitHub OIDC.


Option 2: Manual workflow with quality gate

If you already manage the checkout and Python setup yourself, the core scan, gate, and annotation steps are:

- name: Install Skylos
  run: python -m pip install skylos

- name: Run Skylos
  run: skylos . -a --format json -o skylos-results.json

- name: Apply the quality gate
  if: always()
  run: skylos cicd gate --input skylos-results.json --summary

- name: Add GitHub Actions annotations
  if: always()
  run: skylos cicd annotate --input skylos-results.json

skylos cicd gate evaluates the saved result against the configured thresholds. Add skylos cicd review as shown by the generated workflow if you also want review comments; --github on a direct scan emits GitHub Actions annotations, not review comments.

Configuring the quality gate

Set gate thresholds in pyproject.toml:

[tool.skylos.gate]
fail_on_critical = true
max_security = 0
max_secrets = 0
max_ai_defects = 0
max_quality = 10

The --severity option filters displayed findings; it does not replace gate policy. Run skylos . -a --gate to evaluate the configured thresholds directly, or use skylos cicd gate with a saved result as shown above.


Option 3: Changed-code scanning

Use both diff modes when you want pull-request findings while retaining cross-file context:

- name: Scan changed code
  run: skylos . -a --diff-base origin/main --diff origin/main --github

For file-scoped rules, --diff-base focuses applicable analysis on changed files while Skylos still parses unchanged files for cross-file context, and --diff filters ordinary line-attached findings to changed lines. Repository-wide dependency and circular-dependency checks can still report findings outside changed lines and affect a gate. The generated workflow resolves the actual pull-request base rather than assuming it is always origin/main.


What Skylos catches in CI

Leaked secret values (SKY-S101)

# Skylos flags this
API_KEY = "sk-proj-1234567890abcdef"

Example review message:

High-entropy value detected at config.py:7. Move this to an environment variable or secrets manager.

Hardcoded credentials (SKY-L014)

# Skylos flags this when quality checks are enabled
DATABASE_URL = "postgresql://admin:password@prod:5432/db"

Example review message:

Hardcoded credential detected at config.py:7. Move this to an environment variable or secrets manager.

SQL injection (SKY-D211)

# Skylos flags this — user input in SQL query
query = f"SELECT * FROM users WHERE id = {request.args['id']}"
cursor.execute(query)

Example review message:

SQL injection risk at routes.py:23. User input flows directly into SQL query. Use parameterized queries instead.

Command injection (SKY-D212)

# Skylos flags this
cmd = request.form.get("command")
subprocess.call(cmd, shell=True)

Dead code

# Skylos flags this — never called from any reachable code
def calculate_tax_v2(amount, rate):
    return amount * rate * 1.1

Weak cryptography (SKY-D207)

# Skylos flags this
def hash_password(pw):
    return hashlib.md5(pw.encode()).hexdigest()

AI-generated patterns

# Skylos flags disabled SSL
requests.get(url, verify=False)

# Skylos flags disabled JWT verification
jwt.decode(token, algorithms=["none"])

Adding a pre-commit hook

Catch issues before they reach the PR:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/duriantaco/skylos
    rev: v4.37.0
    hooks:
      - id: skylos-scan

Install and run:

pip install pre-commit
pre-commit install

Now every git commit runs Skylos on staged files. Issues are caught at the developer's desk, not in CI.


Combining with other tools

Skylos doesn't conflict with other security tools. Common combinations:

Skylos + Semgrep

steps:
  - name: Semgrep (custom rules)
    run: semgrep scan --config custom-rules/ src/

  - name: Skylos (dead code + security + quality)
    run: skylos . --danger --quality --ai-defects --github

Use Semgrep for domain-specific custom rules. Use Skylos here for dead code, AI-defect checks, and built-in security rules.

Skylos + Dependabot

Dependabot provides dependency alerts and update pull requests. Skylos can add an OSV-backed --sca check for supported exact Python, npm, and Go dependency inventories alongside its source scan.


Check LLM application guardrails

If the repository builds an LLM application, MCP server, or coding agent, add a guardrail scan:

- name: AI code security check
  run: |
    skylos discover . --json
    skylos defend . --fail-on high

skylos discover finds LLM integration points. With --fail-on high, skylos defend fails when a high- or critical-severity guardrail gap is present; lower-severity gaps remain visible without failing the step.

For checks aimed at generated source code, including hallucinated dependencies, see How to catch hallucinated imports in AI-generated Python code.


SARIF output for GitHub Code Scanning

If you use GitHub's native code scanning tab, output SARIF:

- name: Skylos SARIF scan
  run: skylos . --danger --sarif results.sarif

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif

This integrates Skylos findings directly into GitHub's Security tab alongside CodeQL results.


Performance tips

Runtime depends on repository size, languages, graph shape, and enabled categories. Measure the exact command on your CI runner. For pull requests, use the generated workflow's --diff-base plus --diff combination, and enable only the categories you intend to review or gate.


Quick start

# Install
pip install skylos

# Generate GitHub Actions workflow
skylos cicd init

# Or run manually
# (`--github` emits GitHub Actions annotations)
skylos . -a --github

That's it. Commit the workflow file, push, and every PR gets scanned.


Skylos is open source. View on GitHub | Docs | Install