{"id":50039626,"url":"https://github.com/cpeoples/ansible-security-scanner","last_synced_at":"2026-05-27T03:11:30.242Z","repository":{"id":358998291,"uuid":"1224669495","full_name":"cpeoples/ansible-security-scanner","owner":"cpeoples","description":"🛡️ Static security scanner for Ansible playbooks. 1,090+ rules across 30+ categories covering malicious code, supply-chain risk, IaC misconfiguration, secrets, RCE, and lateral movement. Outputs SARIF, GitLab SAST, and SBOM. CI-native with autofix support.","archived":false,"fork":false,"pushed_at":"2026-05-21T01:55:37.000Z","size":1263,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T06:51:52.600Z","etag":null,"topics":["ansible","ansible-playbook","ci-cd","code-scanning","devsecops","github-actions","gitlab-sast","iac-security","infrastructure-as-code","python","sarif","sast","secrets-detection","security","security-scanner","security-tools","static-analysis","supply-chain-security","vulnerability-scanner","yaml"],"latest_commit_sha":null,"homepage":"https://cpeoples.github.io/ansible-security-scanner/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cpeoples.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T14:04:48.000Z","updated_at":"2026-05-21T01:55:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cpeoples/ansible-security-scanner","commit_stats":null,"previous_names":["cpeoples/ansible-security-scanner"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/cpeoples/ansible-security-scanner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpeoples%2Fansible-security-scanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpeoples%2Fansible-security-scanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpeoples%2Fansible-security-scanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpeoples%2Fansible-security-scanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cpeoples","download_url":"https://codeload.github.com/cpeoples/ansible-security-scanner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpeoples%2Fansible-security-scanner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33548592,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","ansible-playbook","ci-cd","code-scanning","devsecops","github-actions","gitlab-sast","iac-security","infrastructure-as-code","python","sarif","sast","secrets-detection","security","security-scanner","security-tools","static-analysis","supply-chain-security","vulnerability-scanner","yaml"],"created_at":"2026-05-21T02:16:26.621Z","updated_at":"2026-05-27T03:11:30.235Z","avatar_url":"https://github.com/cpeoples.png","language":"Python","funding_links":[],"categories":["Tools","Infrastructure as code security"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/assets/brand-mark.svg\"\u003e\n    \u003cimg src=\"docs/assets/brand-mark-light.svg\" alt=\"Ansible Security Scanner\" width=\"560\"\u003e\n  \u003c/picture\u003e\n\u003c/div\u003e\n\u003c!-- BADGES_START - stripped from the Hugo docs build; see .hugo/scripts/build_docs.py --\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/cpeoples/ansible-security-scanner/actions/workflows/scanner-ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/cpeoples/ansible-security-scanner/scanner-ci.yml?branch=main\u0026label=CI\u0026style=flat-square\" alt=\"CI\" /\u003e\u003c/a\u003e\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"https://www.bestpractices.dev/en/projects/12942/baseline-3\"\u003e\u003cimg src=\"https://img.shields.io/badge/OpenSSF%20Baseline-Level%203-blueviolet?style=flat-square\" alt=\"OpenSSF Baseline Level 3\" /\u003e\u003c/a\u003e\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"https://scorecard.dev/viewer/?uri=github.com/cpeoples/ansible-security-scanner\"\u003e\u003cimg src=\"https://img.shields.io/ossf-scorecard/github.com/cpeoples/ansible-security-scanner?style=flat-square\u0026label=OpenSSF%20Scorecard\" alt=\"OpenSSF Scorecard\" /\u003e\u003c/a\u003e\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"https://owasp.org/www-community/Source_Code_Analysis_Tools\"\u003e\u003cimg src=\"https://img.shields.io/badge/OWASP-Listed-000000?style=flat-square\u0026logo=owasp\u0026logoColor=white\" alt=\"OWASP Listed\" /\u003e\u003c/a\u003e\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"src/ansible_security_scanner/patterns\"\u003e\u003cimg src=\"https://img.shields.io/badge/Rules-1091-blue?style=flat-square\u0026logo=ansible\u0026logoColor=white\" alt=\"Rules\" /\u003e\u003c/a\u003e\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"https://pypi.org/project/ansible-security-scanner/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/ansible-security-scanner?style=flat-square\u0026logo=pypi\u0026logoColor=white\u0026label=PyPI\" alt=\"PyPI\" /\u003e\u003c/a\u003e\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"https://github.com/cpeoples/ansible-security-scanner/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/badge/Sigstore-verified-success?style=flat-square\u0026logo=sigstore\u0026logoColor=white\" alt=\"Sigstore verified\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003c!-- BADGES_END --\u003e\n\nStatic SAST scanner for Ansible playbooks, roles, collections, task files, vars, and inventories. Detects malicious code, RCE, command and template injection, hardcoded credentials, supply-chain risk, unauthorized cloud access, lateral movement, and reverse shells. Outputs SARIF, CycloneDX SBOM, GitLab SAST, JUnit, JSON, HTML, and Markdown reports with remediation guidance. Findings map to CWE, OWASP Top 10, OWASP ASVS, MITRE ATT\u0026CK, NIST, and CIS. CI-native, autofix-capable, DevSecOps-ready.\n\n**\u003c!--RULES--\u003e1091\u003c!--/RULES--\u003e rules** across **\u003c!--CATS--\u003e31\u003c!--/CATS--\u003e categories** -- all auto-discovered from YAML pattern plugins.\n\n**\u003c!--CRIT--\u003e412\u003c!--/CRIT--\u003e critical**, \u003c!--HIGH--\u003e528\u003c!--/HIGH--\u003e high, \u003c!--MED--\u003e131\u003c!--/MED--\u003e medium, \u003c!--LOW--\u003e19\u003c!--/LOW--\u003e low. [Per-category breakdown on the dashboard.](https://cpeoples.github.io/ansible-security-scanner/dashboard/)\n\n\u003e [!NOTE]\n\u003e **Scope.** This is a *static, pattern-based* scanner - one layer in a defense-in-depth strategy. Pair it with the runtime controls you already trust (AAP/AWX approval gates, execution-environment lockdown, network egress policy, code review) for full coverage. See [Limitations](docs/limitations.md) for the specific classes of issue this layer cannot catch on its own.\n\n## Contents\n\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [What it detects](#what-it-detects)\n- [Project Structure](#project-structure)\n- [Documentation](#documentation)\n- [Requirements](#requirements)\n- [Contributing](#contributing)\n- [Security](#security)\n- [License \u0026 Attribution](#license--attribution)\n\n### Built with\n\n\u003cdiv style=\"display:flex !important;flex-wrap:wrap;align-items:center;gap:1.25rem;margin:0.5rem 0 1rem;\"\u003e\n  \u003ca href=\"https://www.python.org/\" title=\"Python\" style=\"display:inline-flex !important;align-items:center;\"\u003e\u003cimg src=\"docs/assets/python.svg\" alt=\"Python\" height=\"28\" style=\"display:inline-block;\" /\u003e\u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://yaml.org/\" title=\"YAML\" style=\"display:inline-flex !important;align-items:center;\"\u003e\u003cimg src=\"docs/assets/yaml.svg\" alt=\"YAML\" height=\"28\" style=\"display:inline-block;\" /\u003e\u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://docs.pytest.org/\" title=\"Pytest\" style=\"display:inline-flex !important;align-items:center;\"\u003e\u003cimg src=\"docs/assets/pytest.svg\" alt=\"Pytest\" height=\"28\" style=\"display:inline-block;\" /\u003e\u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://gohugo.io/\" title=\"Hugo\" style=\"display:inline-flex !important;align-items:center;\"\u003e\u003cimg src=\"docs/assets/hugo.svg\" alt=\"Hugo\" height=\"28\" style=\"display:inline-block;\" /\u003e\u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://docs.gitlab.com/ee/ci/\" title=\"GitLab CI\" style=\"display:inline-flex !important;align-items:center;\"\u003e\u003cimg src=\"docs/assets/gitlab.svg\" alt=\"GitLab CI\" height=\"28\" style=\"display:inline-block;\" /\u003e\u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://docs.github.com/actions\" title=\"GitHub Actions\" style=\"display:inline-flex !important;align-items:center;\"\u003e\u003cimg src=\"docs/assets/githubactions.svg\" alt=\"GitHub Actions\" height=\"28\" style=\"display:inline-block;\" /\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n## Installation\n\n```bash\npip install ansible-security-scanner\n```\n\nRequires Python 3.11+. Installs an `ansible-security-scanner` command on your PATH.\n\n## Quick Start\n\nAfter `pip install ansible-security-scanner`, try one of these:\n\n```bash\n# 1. Scan the current directory, print a Markdown report to the terminal\nansible-security-scanner\n\n# 2. Scan a project and write a SARIF report for GitHub Code Scanning\nansible-security-scanner --directory ansible/ --output results.sarif\n\n# 3. CI/CD: emit a GitLab SAST report (auto-populates the Security Dashboard)\nansible-security-scanner --directory ansible/ --output gl-sast-report.json\n\n# 4. One Markdown report per scanned playbook (lands under ./security-reports/)\nansible-security-scanner --directory ansible/ --output-per-file --format markdown\n\n# 5. Only fail the build on secrets-related findings\nansible-security-scanner --directory ansible/ --compliance CIS-Secrets\n\n# 6. Dry-run autofix - emit a unified diff of the changes the scanner would make\nansible-security-scanner --files site.yml --fix --fix-output fixes.patch\n\n# 7. CI/CD: post a concise findings comment on the current PR / MR\n#    (auto-detects GitHub Actions vs. GitLab CI; works on self-hosted).\nansible-security-scanner --gh-comment    # inside a pull_request workflow\nansible-security-scanner --gl-comment    # inside a merge_request_event pipeline\n\n# Full list of flags \u0026 examples:\nansible-security-scanner --help\n```\n\n**Smart defaults**\n\n- **No `--format` given?** If you pass `--output report.sarif`, the format\n  is inferred from the extension (`.sarif` -\u003e SARIF, `.json` -\u003e JSON,\n  `.md`/`.markdown` -\u003e Markdown, `.html`/`.htm` -\u003e HTML, `.xml` -\u003e XML,\n  `.yml`/`.yaml` -\u003e YAML, `.csv` -\u003e CSV). An explicit `--format` always\n  wins; the scanner logs a warning if the two disagree so pipeline\n  misconfigurations fail loudly.\n- **No `--output` given with `--output-per-file`?** Reports land under\n  `./security-reports/` (a self-documenting directory; add it to\n  `.gitignore`).\n- **`--output` would overwrite an input file?** The scanner refuses and\n  exits with code 2 - common footgun when running\n  `--files site.yml --output site.yml` with `.yml`-as-format inference.\n\n**Working from a source checkout?** Use `python main.py ...` instead of the\ninstalled CLI - it's a thin shim around the same entry point.\n\n## What it detects\n\nThe scanner ships \u003c!--RULES--\u003e1091\u003c!--/RULES--\u003e rules across \u003c!--CATS--\u003e31\u003c!--/CATS--\u003e auto-discovered categories. Highlights:\n\n**Malicious code and post-exploitation**\n\n- Reverse shells, webshell deployment, system compromise, lateral movement\n- Anti-forensics, obfuscation and evasion, tunneling, offensive tooling\n\n**Code execution and injection**\n\n- Command injection, template injection, variable injection\n- Jinja lookup RCE, dangerous Ansible modules, binary planting\n\n**Secrets and supply chain**\n\n- Hardcoded credentials and API keys\n- Supply-chain risk (Galaxy collections, ad-hoc downloads, untrusted URLs)\n- Data exfiltration, webhook exposure, external URL contact\n\n**Cloud, IaC, and platform hardening**\n\n- Unauthorized cloud access, Kubernetes insecure specs\n- Privilege escalation, unsafe permissions, environment hijacking\n- Insecure communication (TLS, SSH, plaintext protocols)\n\n**AI/ML and operational hygiene**\n\n- AI/ML supply-chain and prompt-injection risks\n- Ansible hygiene, Ansible-specific anti-patterns, operational security\n\nEvery rule includes severity, framework mappings (CWE, OWASP Top 10, OWASP ASVS, MITRE ATT\u0026CK, NIST, CIS Controls), vulnerable and remediated examples, and remediation guidance. Findings are deduplicated across files via cross-file taint tracking. See the [rule dashboard](https://cpeoples.github.io/ansible-security-scanner/dashboard/) for a per-category, per-severity breakdown.\n\n## Project Structure\n\n```\nansible-security-scanner/                      # repo root (hyphenated - matches PyPI)\n├── pyproject.toml                             # packaging + pytest + hatch-vcs\n├── README.md\n├── CONTRIBUTING.md\n├── RELEASING.md                               # maintainer release runbook\n├── LICENSE / NOTICE                           # Apache-2.0 + attribution terms\n├── main.py                                    # local dev entry point (py main.py ...)\n├── .github/workflows/                         # CI, release, docs workflows\n├── .hugo/                                     # Hugo documentation site\n│   ├── scripts/build_docs.py                  # Generates Hugo content from docs/ + patterns\n│   └── content/                               # Generated .md pages (do not edit by hand)\n├── docs/                                      # Long-form prose docs (source of truth)\n│   ├── assets/                                # Images \u0026 SVGs the README references\n│   ├── cli.md                                 # CLI Reference (and exit codes, suppressions, dedup)\n│   ├── environment.md                         # Environment Variables\n│   ├── api.md                                 # Programmatic API\n│   ├── output-formats.md\n│   ├── allowlist.md\n│   ├── ci-cd.md\n│   ├── mr-pr-comments.md\n│   ├── custom-patterns.md\n│   ├── scoring.md\n│   ├── testing.md\n│   ├── limitations.md\n│   └── releasing.md\n├── src/\n│   └── ansible_security_scanner/              # the Python package\n│       ├── cli.py                             # CLI (--directory, --fix, --compliance, ...)\n│       ├── scanner.py                         # Multi-pass orchestrator\n│       ├── file_scanner.py                    # Per-file rules (line patterns, AST walkers)\n│       ├── taint_tracker.py                   # Cross-file taint analysis\n│       ├── fix_proposer.py                    # Dry-run unified-diff patch generator\n│       ├── dependency_collector.py            # SBOM inventory\n│       ├── suppressions.py                    # Inline `# nosec` parser\n│       ├── models.py                          # SecurityFinding, ScanReport, SecurityScore\n│       ├── score_calculator.py                # Severity-weighted scoring\n│       ├── patterns_manager.py                # Loads pattern YAML plugins\n│       ├── patterns/                          # 29+ YAML pattern plugins (auto-discovered)\n│       ├── remediations/                      # One module per category\n│       └── formatters/                        # markdown, json, xml, yaml, csv, html, junit, sarif, gitlab_sast, cyclonedx\n└── tests/\n    ├── test_integration.py                    # End-to-end scanner tests\n    ├── test_formatters.py                     # Formatter unit tests\n    ├── test_remediations.py                   # Remediation generator unit tests\n    └── playbooks/\n        ├── bad_example.yml                    # Triggers every rule (100% coverage)\n        ├── clean_example.yml                  # Zero findings (false-positive guard)\n        ├── multi_example_bad/                 # 6-file role fixture (cross-file taint)\n        └── multi_example_clean/               # 6-file hardened role fixture (zero findings)\n```\n\n## Documentation\n\nThe long-form documentation is split by topic. Each page is a standalone\nMarkdown file in [`docs/`](docs/) - GitHub renders them inline, and the\nHugo site at [GitHub Pages](#documentation-site) serves the same content\nwith a navigation sidebar and search.\n\n| Topic | Source |\n|---|---|\n| **CLI flags, exit codes, suppressions, cross-file dedup** | [`docs/cli.md`](docs/cli.md) |\n| **Environment variables (auth, defaults, `--changed-files`)** | [`docs/environment.md`](docs/environment.md) |\n| **Programmatic Python API** | [`docs/api.md`](docs/api.md) |\n| **Output formats (Markdown, JSON, SARIF, GL-SAST, SBOM, ...)** | [`docs/output-formats.md`](docs/output-formats.md) |\n| **Allowlist / suppressing findings** | [`docs/allowlist.md`](docs/allowlist.md) |\n| **CI/CD integration (GitLab CI, GitHub Actions)** | [`docs/ci-cd.md`](docs/ci-cd.md) |\n| **MR / PR comments (auto-detected, self-hosted-aware)** | [`docs/mr-pr-comments.md`](docs/mr-pr-comments.md) |\n| **Adding custom patterns** | [`docs/custom-patterns.md`](docs/custom-patterns.md) |\n| **Security score model** | [`docs/scoring.md`](docs/scoring.md) |\n| **Testing** | [`docs/testing.md`](docs/testing.md) |\n| **Limitations of static analysis** | [`docs/limitations.md`](docs/limitations.md) |\n| **Releasing** | [`docs/releasing.md`](docs/releasing.md) |\n\n### Documentation site\n\nFull documentation is auto-generated from the [`docs/`](docs/) Markdown\nfiles plus the pattern YAML plugins, and published via Hugo + GitHub\nPages on every push to `main`.\n\nThe build pipeline (`.github/workflows/scanner-docs.yml`) runs:\n\n1. `build_docs.py` - copies each `docs/\u003cslug\u003e.md` into Hugo's `content/`\n   with appropriate front-matter, and generates one rule-table page per\n   pattern category.\n2. Hugo builds a static site with the\n   [Relearn](https://mcshelby.github.io/hugo-theme-relearn/) theme.\n3. The site is deployed to GitHub Pages.\n\nTo preview locally:\n\n```bash\n# Generate content\npython .hugo/scripts/build_docs.py\n\n# Download theme (first time only)\ncd .hugo\ncurl -sL https://github.com/McShelby/hugo-theme-relearn/archive/refs/heads/main.tar.gz | tar -xz -C themes/\nmv themes/hugo-theme-relearn-main themes/hugo-theme-relearn\n\n# Serve locally\nhugo server\n```\n\n## Requirements\n\n- Python 3.11+\n- PyYAML \u003e= 6.0\n- Jinja2 \u003e= 3.0\n- httpx \u003e= 0.27 (used by `--github-comment` / `--gitlab-comment` only)\n\nFor development work from source:\n\n```bash\npip install -e \".[dev]\"\n```\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full dev-environment\nwalkthrough, pattern-authoring guide, and PR checklist.\n\n**TL;DR for a first-time clone:**\n\n```bash\ngit clone --recurse-submodules https://github.com/cpeoples/ansible-security-scanner.git\ncd ansible-security-scanner\npython -m venv .venv \u0026\u0026 source .venv/bin/activate\npython task.py install        # editable install + test/lint/build deps\npython task.py test           # run the full pytest suite\npython task.py scan ./tests/playbooks/bad_example.yml   # try the scanner locally\n```\n\n**Common contribution paths:**\n\n1. **Add a security pattern** - drop a YAML plugin in\n   `src/ansible_security_scanner/patterns/` (auto-discovered at startup).\n   See [§3 of `CONTRIBUTING.md`](CONTRIBUTING.md#3-adding-a-new-security-pattern)\n   for the schema and validation steps.\n2. **Add a remediation generator** - create a module in\n   `src/ansible_security_scanner/remediations/`, then wire it into\n   `remediation_generator.py`.\n3. **Add an output formatter** - subclass `base.BaseFormatter` under\n   `src/ansible_security_scanner/formatters/` and register it in\n   `utils.get_formatter_class`.\n4. **Run the gates before opening a PR** - `python task.py test` (full\n   suite), `python task.py lint`, `python task.py build`.\n\n## Security\n\nThis repository runs three GitHub-native security checks on every push\nand pull request:\n\n- **Dependabot** ([`.github/dependabot.yml`](.github/dependabot.yml)) -\n  weekly update PRs for `pip` and `github-actions` ecosystems, plus\n  out-of-band security advisories.\n- **CodeQL** (default setup, configured in repo settings) - SAST against\n  the Python in `src/ansible_security_scanner/`.\n- **Secret scanning + push protection** - alerts on credential-shaped\n  strings in tracked files.\n\n### Why some paths are excluded from secret scanning\n\nBecause this *is* a security scanner, the repo ships two structurally\nrequired corpora that look exactly like real secrets:\n\n1. **Hand-curated negative fixtures** (`tests/playbooks/bad_example.yml`\n   and `tests/playbooks/multi_example_bad/**`) - the integration tests\n   feed these to the scanner to assert each rule class fires correctly.\n   They contain deliberate hardcoded credentials, fake AWS keys, and\n   embedded SQS URLs; nothing here is a real credential.\n2. **Pattern-pack `vulnerable_examples:` blocks**\n   (`src/ansible_security_scanner/patterns/**`) - rule definitions\n   document, by design, the literal strings each rule is meant to\n   match. These blocks are rendered into the generated rule docs that\n   ship at \u003chttps://cpeoples.github.io/ansible-security-scanner/\u003e.\n\nBoth surfaces are excluded via [`.github/secret_scanning.yml`](.github/secret_scanning.yml),\nwhere each entry is annotated with the structural reason it's there.\n\n### Reporting a vulnerability\n\nOpen a private security advisory via the\n[Security tab](https://github.com/cpeoples/ansible-security-scanner/security/advisories/new)\nrather than a public issue. Vulnerabilities in the scanner itself\n(e.g. a code path that lets an attacker leak unredacted secrets through\nan MR comment) are in scope; vulnerabilities in *Ansible playbooks\ndetected by the scanner* are not - those belong to the playbook's\nmaintainer.\n\n## License \u0026 Attribution\n\nThis project is licensed under the [Apache License, Version 2.0](LICENSE).\n\n**If you use, fork, embed, or build on this project, please retain attribution\nto the original repository and contributors.** The [`NOTICE`](NOTICE) file at\nthe repo root spells out exactly what is required.\n\nIn plain English:\n\n- You can use this scanner commercially, modify it, embed it in larger tools,\n  or build a paid product on top of it - no fee, no permission needed.\n- You must keep the `LICENSE` and `NOTICE` files in any redistribution.\n- If you fork this project or ship a derivative work (for example, a\n  rebranded scanner, a hosted service, or a SaaS wrapper), you must state\n  that it is derived from **Ansible Security Scanner** by Chris Peoples and\n  link back to the original repository:\n  \u003chttps://github.com/cpeoples/ansible-security-scanner\u003e.\n- The project name **\"Ansible Security Scanner\"** / `ansible-security-scanner`\n  is a reserved mark of the original author (Apache-2.0 §6). Your fork is\n  welcome - under a different name.\n- Apache-2.0 includes an explicit **patent grant** and a **retaliation clause**:\n  if you sue the project or its contributors over a patent related to the\n  software, your rights under the license terminate automatically.\n\nSee [`NOTICE`](NOTICE) for the full attribution terms and\n[`LICENSE`](LICENSE) for the Apache-2.0 text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpeoples%2Fansible-security-scanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcpeoples%2Fansible-security-scanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpeoples%2Fansible-security-scanner/lists"}