Skip to main content

🩺 yaml-doctor

YAML Linter & Security Scanner for DevOps Engineers

Validate and lint Kubernetes manifests, Docker Compose files, GitHub Actions workflows, GitLab CI pipelines, and generic YAML with 60+ built-in rules covering security, reliability, and best practices.

PyPI version Python License: MIT Tests


✨ Features

  • 🔍 60+ Lint Rules — Security, reliability, and best practice checks
  • 🎯 Auto-Detection — Automatically identifies Kubernetes, Docker Compose, GitHub Actions, GitLab CI, and Helm files
  • 📊 Grading System — A+ to F grades with detailed scoring
  • 🌐 HTML Dashboard — Beautiful dark-theme HTML reports with severity charts
  • 📋 JSON Export — Machine-readable reports for CI/CD integration
  • 🔧 Fix Suggestions — Actionable remediation for every finding
  • 🎮 Demo Mode — Try it instantly with built-in sample files
  • 🚀 Zero Config — Works out of the box, no configuration needed

📦 Installation

pip install yaml-doctor

🚀 Quick Start

# Lint a single file
yaml-doctor lint deployment.yaml

# Scan a directory recursively
yaml-doctor scan ./k8s/

# Run demo with sample files
yaml-doctor demo

# Show all 60 rules
yaml-doctor rules

# Get fix suggestions
yaml-doctor fix deployment.yaml

# Export HTML dashboard
yaml-doctor scan . --html report.html

# Export JSON report
yaml-doctor lint config.yaml -j report.json

🎯 Supported File Types

Type Detection Rules
Kubernetes apiVersion + kind 20 rules (K8S001-K8S020)
Docker Compose services + image/build 12 rules (DC001-DC012)
GitHub Actions .github/workflows/ + on/jobs 10 rules (GHA001-GHA010)
GitLab CI .gitlab-ci.yml + stages/script 10 rules (GL001-GL010)
Helm Chart.yaml / values.yaml K8s rules applied
Generic YAML Any .yml/.yaml file 8 rules (YML001-YML008)

🔒 Security Rules

Kubernetes (20 rules)

Rule Severity Description
K8S001 🔴 CRITICAL Container running as root
K8S004 🔴 CRITICAL Privileged container
K8S002 🟠 HIGH Missing resource limits
K8S003 🟠 HIGH Missing resource requests
K8S005 🟠 HIGH Using :latest image tag
K8S006 🟠 HIGH Missing liveness probe
K8S011 🟠 HIGH Host network enabled
K8S012 🟠 HIGH Host PID enabled
K8S016 🟠 HIGH Secrets in environment variables
K8S007 🟡 MEDIUM Missing readiness probe
K8S008 🟡 MEDIUM Read-only filesystem not set
K8S013 🟡 MEDIUM Single replica deployment
K8S014 🟡 MEDIUM Privilege escalation allowed
K8S017 🟡 MEDIUM Missing update strategy
K8S018 🟡 MEDIUM Capabilities not dropped
K8S020 🟡 MEDIUM Missing restart policy
K8S009 🔵 LOW Missing recommended labels
K8S015 🔵 LOW Missing PodDisruptionBudget
K8S019 🔵 LOW No anti-affinity rules
K8S010 ⚪ INFO Missing namespace

Docker Compose (12 rules)

Rule Severity Description
DC002 🔴 CRITICAL Privileged container
DC001 🟠 HIGH Using :latest tag
DC005 🟠 HIGH Secrets in environment
DC009 🟠 HIGH Host volume with write access
DC012 🟡 MEDIUM Host network mode
DC003 🟡 MEDIUM No restart policy
DC004 🟡 MEDIUM No healthcheck defined
DC007 🟡 MEDIUM Exposed to all interfaces
DC011 🟡 MEDIUM No depends_on
DC006 🔵 LOW No resource limits
DC010 🔵 LOW No logging configuration
DC008 ⚪ INFO Deprecated version key

GitHub Actions (10 rules)

Rule Severity Description
GHA001 🔴 CRITICAL Mutable action reference (using @main)
GHA002 🟠 HIGH Persist credentials enabled
GHA003 🟠 HIGH Secrets in run commands
GHA009 🟠 HIGH Script injection risk
GHA004 🟡 MEDIUM Overly broad permissions
GHA005 🟡 MEDIUM No job timeout
GHA006 🟡 MEDIUM pull_request_target trigger
GHA007 🔵 LOW No concurrency control
GHA008 🔵 LOW Unversioned runner image
GHA010 ⚪ INFO Missing workflow name

GitLab CI (10 rules)

Rule Severity Description
GL001 🟠 HIGH Secrets in script blocks
GL007 🟠 HIGH allow_failure on security jobs
GL002 🟡 MEDIUM No retry configuration
GL004 🟡 MEDIUM Using :latest image
GL005 🟡 MEDIUM No timeout set
GL009 🟡 MEDIUM No rules/conditions
GL003 🔵 LOW No cache defined
GL008 🔵 LOW No artifacts defined
GL010 🔵 LOW Missing job description
GL006 ⚪ INFO No stages defined

Generic YAML (8 rules)

Rule Severity Description
YML005 🟠 HIGH Hardcoded credentials
YML001 🟡 MEDIUM Inconsistent indentation
YML006 🟡 MEDIUM Duplicate keys
YML002 🔵 LOW Trailing whitespace
YML003 🔵 LOW Line too long (>200 chars)
YML007 🔵 LOW Empty values
YML004 ⚪ INFO Missing document start marker
YML008 ⚪ INFO File too long (>1000 lines)

📊 Grading System

Grade Score Description
A+ 95-100 Excellent — production ready
A 85-94 Great — minor improvements possible
B 75-84 Good — some issues to address
C 65-74 Fair — significant improvements needed
D 50-64 Poor — many issues found
F 0-49 Failing — critical issues present

Score deductions per finding:

  • 🔴 Critical: -15 points
  • 🟠 High: -8 points
  • 🟡 Medium: -3 points
  • 🔵 Low: -1 point
  • ⚪ Info: 0 points

🖥️ CLI Commands

yaml-doctor lint <file>

Lint a single YAML file with auto-detection.

yaml-doctor lint deployment.yaml
yaml-doctor lint docker-compose.yml --html report.html
yaml-doctor lint .github/workflows/ci.yml -j report.json

yaml-doctor scan <directory>

Scan all YAML files in a directory.

yaml-doctor scan ./k8s/
yaml-doctor scan . --html dashboard.html
yaml-doctor scan ./configs --no-recursive

yaml-doctor demo

Run a demo with built-in sample files.

yaml-doctor demo
yaml-doctor demo --type kubernetes
yaml-doctor demo --type compose
yaml-doctor demo --html demo-report.html

yaml-doctor rules

Display all 60 available lint rules.

yaml-doctor rules

yaml-doctor fix <file>

Show fix suggestions for all findings.

yaml-doctor fix deployment.yaml

🔌 CI/CD Integration

GitHub Actions

- name: YAML Lint
  run: |
    pip install yaml-doctor
    yaml-doctor scan . --html report.html -j report.json
    
- name: Upload Report
  uses: actions/upload-artifact@v4
  with:
    name: yaml-doctor-report
    path: report.html

GitLab CI

yaml-lint:
  stage: test
  script:
    - pip install yaml-doctor
    - yaml-doctor scan . --html report.html -j report.json
  artifacts:
    paths:
      - report.html
      - report.json

Pre-commit Hook

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: yaml-doctor
        name: yaml-doctor
        entry: yaml-doctor lint
        language: python
        types: [yaml]
        additional_dependencies: [yaml-doctor]

📁 Project Structure

yaml-doctor/
├── yaml_doctor/
│   ├── __init__.py          # Package version
│   ├── __main__.py          # python -m support
│   ├── cli.py               # Click CLI commands
│   ├── scanner.py           # Core scanning engine
│   ├── models.py            # Data models & enums
│   ├── rules.py             # Rule registry (60 rules)
│   ├── utils.py             # Helper utilities
│   ├── demo.py              # Demo sample data
│   ├── analyzers/
│   │   ├── __init__.py      # File type detection
│   │   ├── kubernetes.py    # 20 K8s rules
│   │   ├── compose.py       # 12 Docker Compose rules
│   │   ├── github_actions.py # 10 GitHub Actions rules
│   │   ├── gitlab_ci.py     # 10 GitLab CI rules
│   │   └── yaml_lint.py     # 8 generic YAML rules
│   └── output/
│       ├── console.py       # Rich terminal output
│       └── html_report.py   # HTML dashboard reports
├── tests/                   # 188 tests
├── pyproject.toml
├── LICENSE
└── README.md

🧪 Development

git clone https://github.com/SanjaySundarMurthy/yaml-doctor.git
cd yaml-doctor
pip install -e ".[dev]"
pytest
ruff check .

📄 License

MIT License — see LICENSE for details.

👨‍💻 Author

Sanjay SGitHub · Email

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yaml_doctor_cli-1.0.0.tar.gz (34.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yaml_doctor_cli-1.0.0-py3-none-any.whl (33.2 kB view details)

Uploaded Python 3

File details

Details for the file yaml_doctor_cli-1.0.0.tar.gz.

File metadata

  • Download URL: yaml_doctor_cli-1.0.0.tar.gz
  • Upload date:
  • Size: 34.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for yaml_doctor_cli-1.0.0.tar.gz
Algorithm Hash digest
SHA256 6810d9692893c89d5ce19c136907539510ac59e0ca13842ebb21036e4b18c3bf
MD5 8b966682200cc6c9d71bc21d6de019c9
BLAKE2b-256 2bbfb9b981f41cb4e32c99e07d6db15e0b100dbaf346086497da8b385000b506

See more details on using hashes here.

File details

Details for the file yaml_doctor_cli-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for yaml_doctor_cli-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0d22c4d915e409a1b2bef7593f7bc8bf01858542b717d9546e6d4c0c7408b976
MD5 23ddacdf0e76228585708b38a975031d
BLAKE2b-256 cf46039cad81487025c49b8d6427df689dafebb70fcfba41c3cf0e108f386948

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page