Full Code of cisagov/bad-practices for AI

develop 5165a0cf63f4 cached
27 files
80.0 KB
20.6k tokens
1 requests
Download .txt
Repository: cisagov/bad-practices
Branch: develop
Commit: 5165a0cf63f4
Files: 27
Total size: 80.0 KB

Directory structure:
gitextract_x1k3vyxe/

├── .ansible-lint
├── .flake8
├── .github/
│   ├── CODEOWNERS
│   ├── dependabot.yml
│   ├── labeler.yml
│   ├── labels.yml
│   ├── lineage.yml
│   └── workflows/
│       ├── build.yml
│       ├── codeql-analysis.yml
│       ├── dependency-review.yml
│       ├── label-prs.yml
│       └── sync-labels.yml
├── .gitignore
├── .isort.cfg
├── .mdl_config.yaml
├── .pre-commit-config.yaml
├── .prettierignore
├── .yamllint
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── bump-version
├── requirements-dev.txt
├── requirements-test.txt
├── requirements.txt
├── setup-env
└── version.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .ansible-lint
================================================
---
# See https://ansible-lint.readthedocs.io/configuring/ for a list of
# the configuration elements that can exist in this file.
enable_list:
  # Useful checks that one must opt-into.  See here for more details:
  # https://ansible-lint.readthedocs.io/rules/
  - fcqn-builtins
  - no-log-password
  - no-same-owner
exclude_paths:
  # This exclusion is implicit, unless exclude_paths is defined
  - .cache
  # Seems wise to ignore this too
  - .github
kinds:
  # This will force our systemd specific molecule configurations to be treated
  # as plain yaml files by ansible-lint. This mirrors the default kind
  # configuration in ansible-lint for molecule configurations:
  # yaml: "**/molecule/*/{base,molecule}.{yaml,yml}"
  - yaml: "**/molecule/*/molecule-{no,with}-systemd.yml"
use_default_rules: true


================================================
FILE: .flake8
================================================
[flake8]
max-line-length = 80

# Select (turn on)
# * C: Complexity violations reported by mccabe -
#   https://flake8.pycqa.org/en/latest/user/error-codes.html#error-violation-codes
# * C4: Default errors and warnings reported by flake8-comprehensions -
#   https://github.com/adamchainz/flake8-comprehensions#rules
# * D: Documentation conventions compliance reported by pydocstyle -
#   https://github.com/PyCQA/pydocstyle/blob/master/docs/error_codes.rst
# * DUO: Default errors and warnings reported by dlint -
#   https://github.com/dlint-py/dlint/tree/master/docs
# * E: Default errors reported by pycodestyle -
#   https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes
# * F: Default errors reported by pyflakes -
#   https://flake8.pycqa.org/en/latest/glossary.html#term-pyflakes
# * N: Default errors and warnings reported by pep8-naming -
#   https://github.com/PyCQA/pep8-naming#error-codes
# * NQA: Default errors and warnings reported by flake8-noqa -
#   https://github.com/plinss/flake8-noqa#error-codes
# * W: Default warnings reported by pycodestyle -
#   https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes
# * B: Default warnings reported by flake8-bugbear -
#   https://github.com/PyCQA/flake8-bugbear#list-of-warnings
# * B950: Bugbear opinionated warning for line too long -
#   https://github.com/PyCQA/flake8-bugbear#opinionated-warnings
select = C,C4,D,DUO,E,F,N,NQA,W,B,B950

# Ignore
# * E203: pycodestyle's default warning about whitespace before ':' because Black enforces
#   an equal amount of whitespace around slice operators (':').
# * E501: pycodestyle's default warning about maximum line length, which has a hard stop
#   at the configured value.  Instead we use flake8-bugbear's B950, which
#   allows up to 10% overage.
# * W503: pycodestyle's warning about line breaks before binary operators.  It no longer
#   agrees with PEP8.  See, for example, here:
#   https://github.com/ambv/black/issues/21
#   Guido agrees here:
#   https://github.com/python/peps/commit/c59c4376ad233a62ca4b3a6060c81368bd21e85b
ignore = E203,E501,W503


================================================
FILE: .github/CODEOWNERS
================================================
# Each line is a file pattern followed by one or more owners.

# These owners will be the default owners for everything in the
# repo. Unless a later match takes precedence, these owners will be
# requested for review when someone opens a pull request.
* @rm-sbin-sh @cisagov/vm-dev

# These folks own any files in the .github directory at the root of
# the repository and any of its subdirectories.
/.github/ @dav3r @felddy @jsf9k @mcdonnnj

# These folks own all linting configuration files.
/.ansible-lint @dav3r @felddy @jsf9k @mcdonnnj
/.bandit.yml @dav3r @felddy @jsf9k @mcdonnnj
/.flake8 @dav3r @felddy @jsf9k @mcdonnnj
/.isort.cfg @dav3r @felddy @jsf9k @mcdonnnj
/.mdl_config.yaml @dav3r @felddy @jsf9k @mcdonnnj
/.pre-commit-config.yaml @dav3r @felddy @jsf9k @mcdonnnj
/.prettierignore @dav3r @felddy @jsf9k @mcdonnnj
/.yamllint @dav3r @felddy @jsf9k @mcdonnnj
/requirements.txt @dav3r @felddy @jsf9k @mcdonnnj
/requirements-dev.txt @dav3r @felddy @jsf9k @mcdonnnj
/requirements-test.txt @dav3r @felddy @jsf9k @mcdonnnj
/setup-env @dav3r @felddy @jsf9k @mcdonnnj


================================================
FILE: .github/dependabot.yml
================================================
---

# Any ignore directives should be uncommented in downstream projects to disable
# Dependabot updates for the given dependency. Downstream projects will get
# these updates when the pull request(s) in the appropriate skeleton are merged
# and Lineage processes these changes.

updates:
  - directory: /
    ignore:
      # Managed by cisagov/skeleton-generic
      - dependency-name: actions/cache
      - dependency-name: actions/checkout
      - dependency-name: actions/dependency-review-action
      - dependency-name: actions/labeler
      - dependency-name: actions/setup-go
      - dependency-name: actions/setup-python
      - dependency-name: cisagov/action-job-preamble
      - dependency-name: cisagov/setup-env-github-action
      - dependency-name: crazy-max/ghaction-github-labeler
      - dependency-name: github/codeql-action
      - dependency-name: hashicorp/setup-packer
      - dependency-name: hashicorp/setup-terraform
      - dependency-name: mxschmitt/action-tmate
    labels:
      # dependabot default we need to replicate
      - dependencies
      # This matches our label definition in .github/labels.yml as opposed to
      # dependabot's default of `github_actions`.
      - github-actions
    package-ecosystem: github-actions
    schedule:
      interval: weekly

  - directory: /
    package-ecosystem: pip
    schedule:
      interval: weekly

  - directory: /
    package-ecosystem: terraform
    schedule:
      interval: weekly
version: 2


================================================
FILE: .github/labeler.yml
================================================
---
# Each entry in this file is a label that will be applied to pull requests
# if there is a match based on the matching rules for the entry. Please see
# the actions/labeler documentation for more information:
# https://github.com/actions/labeler#match-object
#
# Note: Verify that the label you want to use is defined in the
# crazy-max/ghaction-github-labeler configuration file located at
# .github/labels.yml.

ansible:
  - changed-files:
      - any-glob-to-any-file:
          - "**/ansible/**"
dependencies:
  - changed-files:
      - any-glob-to-any-file:
          # Add any dependency files used.
          - .pre-commit-config.yaml
          - requirements*.txt
docker:
  - changed-files:
      - any-glob-to-any-file:
          - "**/compose*.yml"
          - "**/docker-compose*.yml"
          - "**/Dockerfile*"
documentation:
  - changed-files:
      - any-glob-to-any-file:
          - "**/*.md"
github-actions:
  - changed-files:
      - any-glob-to-any-file:
          - .github/workflows/**
javascript:
  - changed-files:
      - any-glob-to-any-file:
          - "**/*.js"
packer:
  - changed-files:
      - any-glob-to-any-file:
          - "**/*.pkr.hcl"
python:
  - changed-files:
      - any-glob-to-any-file:
          - "**/*.py"
shell script:
  - changed-files:
      - any-glob-to-any-file:
          # If this project has any shell scripts that do not end in the ".sh"
          # extension, add them below.
          - "**/*.sh"
          - bump-version
          - setup-env
terraform:
  - changed-files:
      - any-glob-to-any-file:
          - "**/*.tf"
test:
  - changed-files:
      - any-glob-to-any-file:
          # Add any test-related files or paths.
          - .ansible-lint
          - .flake8
          - .isort.cfg
          - .mdl_config.yaml
          - .yamllint
typescript:
  - changed-files:
      - any-glob-to-any-file:
          - "**/*.ts"
upstream update:
  - head-branch:
      # Any Lineage pull requests should use this branch.
      - lineage/skeleton
version bump:
  - changed-files:
      - any-glob-to-any-file:
          # Ensure this matches your version tracking file(s).
          - version.txt


================================================
FILE: .github/labels.yml
================================================
---
# Rather than breaking up descriptions into multiline strings we disable that
# specific rule in yamllint for this file.
# yamllint disable rule:line-length
- color: ff5850
  description: Pull requests that update Ansible code
  name: ansible
- color: eb6420
  description: This issue or pull request is awaiting the outcome of another issue or pull request
  name: blocked
- color: "000000"
  description: This issue or pull request involves changes to existing functionality
  name: breaking change
- color: d73a4a
  description: This issue or pull request addresses broken functionality
  name: bug
- color: 07648d
  description: This issue will be advertised on code.gov's Open Tasks page (https://code.gov/open-tasks)
  name: code.gov
- color: 0366d6
  description: Pull requests that update a dependency file
  name: dependencies
- color: 1d63ed
  description: Pull requests that update Docker code
  name: docker
- color: 5319e7
  description: This issue or pull request improves or adds to documentation
  name: documentation
- color: cfd3d7
  description: This issue or pull request already exists or is covered in another issue or pull request
  name: duplicate
- color: b005bc
  description: A high-level objective issue encompassing multiple issues instead of a specific unit of work
  name: epic
- color: "000000"
  description: Pull requests that update GitHub Actions code
  name: github-actions
- color: 0e8a16
  description: This issue or pull request is well-defined and good for newcomers
  name: good first issue
- color: ff7518
  description: Pull request that should count toward Hacktoberfest participation
  name: hacktoberfest-accepted
- color: a2eeef
  description: This issue or pull request will add or improve functionality, maintainability, or ease of use
  name: improvement
- color: fef2c0
  description: This issue or pull request is not applicable, incorrect, or obsolete
  name: invalid
- color: f0db4f
  description: Pull requests that update JavaScript code
  name: javascript
- color: ce099a
  description: This pull request is ready to merge during the next Lineage Kraken release
  name: kraken 🐙
- color: a4fc5d
  description: This issue or pull request requires further information
  name: need info
- color: fcdb45
  description: This pull request is awaiting an action or decision to move forward
  name: on hold
- color: 02a8ef
  description: Pull requests that update Packer code
  name: packer
- color: 3776ab
  description: Pull requests that update Python code
  name: python
- color: ef476c
  description: This issue is a request for information or needs discussion
  name: question
- color: d73a4a
  description: This issue or pull request addresses a security issue
  name: security
- color: 4eaa25
  description: Pull requests that update shell scripts
  name: shell script
- color: 7b42bc
  description: Pull requests that update Terraform code
  name: terraform
- color: 00008b
  description: This issue or pull request adds or otherwise modifies test code
  name: test
- color: 2678c5
  description: Pull requests that update TypeScript code
  name: typescript
- color: 1d76db
  description: This issue or pull request pulls in upstream updates
  name: upstream update
- color: d4c5f9
  description: This issue or pull request increments the version number
  name: version bump
- color: ffffff
  description: This issue will not be incorporated
  name: wontfix


================================================
FILE: .github/lineage.yml
================================================
---
lineage:
  skeleton:
    remote-url: https://github.com/cisagov/skeleton-generic.git
version: "1"


================================================
FILE: .github/workflows/build.yml
================================================
---
name: build

on:  # yamllint disable-line rule:truthy
  merge_group:
    types:
      - checks_requested
  # We use the default activity types for the pull_request event as specified here:
  # https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request
  pull_request:
  push:
  repository_dispatch:
    types:
      - apb

# Set a default shell for any run steps. The `-Eueo pipefail` sets errtrace,
# nounset, errexit, and pipefail. The `-x` will print all commands as they are
# run. Please see the GitHub Actions documentation for more information:
# https://docs.github.com/en/actions/using-jobs/setting-default-values-for-jobs
defaults:
  run:
    shell: bash -Eueo pipefail -x {0}

env:
  PIP_CACHE_DIR: ~/.cache/pip
  PRE_COMMIT_CACHE_DIR: ~/.cache/pre-commit
  RUN_TMATE: ${{ secrets.RUN_TMATE }}
  TERRAFORM_DOCS_REPO_BRANCH_NAME: cisagov
  TERRAFORM_DOCS_REPO_DEPTH: 1
  TERRAFORM_DOCS_REPO_URL: https://github.com/mcdonnnj/terraform-docs.git

jobs:
  diagnostics:
    name: Run diagnostics
    # This job does not need any permissions
    permissions: {}
    runs-on: ubuntu-latest
    steps:
      # Note that a duplicate of this step must be added at the top of
      # each job.
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          check_github_status: "true"
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          output_workflow_context: "true"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
  lint:
    needs:
      - diagnostics
    permissions:
      # actions/checkout needs this to fetch code
      contents: read
    runs-on: ubuntu-latest
    steps:
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
      - id: setup-env
        uses: cisagov/setup-env-github-action@v1
      - uses: actions/checkout@v6
      - id: setup-python
        uses: actions/setup-python@v6
        with:
          python-version: ${{ steps.setup-env.outputs.python-version }}
      # We need the Go version and Go cache location for the actions/cache step,
      # so the Go installation must happen before that.
      - id: setup-go
        uses: actions/setup-go@v6
        with:
          # There is no expectation for actual Go code so we disable caching as
          # it relies on the existence of a go.sum file.
          cache: false
          go-version: ${{ steps.setup-env.outputs.go-version }}
      - id: go-cache
        name: Lookup Go cache directory
        run: |
          echo "dir=$(go env GOCACHE)" >> $GITHUB_OUTPUT
      - uses: actions/cache@v5
        env:
          BASE_CACHE_KEY: >-
            ${{ github.job }}-${{ runner.os
            }}-py${{ steps.setup-python.outputs.python-version
            }}-go${{ steps.setup-go.outputs.go-version
            }}-packer${{ steps.setup-env.outputs.packer-version
            }}-tf${{ steps.setup-env.outputs.terraform-version }}-
        with:
          key: >-
            ${{ env.BASE_CACHE_KEY }}${{
            hashFiles('**/requirements-test.txt') }}-${{
            hashFiles('**/requirements.txt') }}-${{
            hashFiles('**/.pre-commit-config.yaml') }}
          # Note that the .terraform directory IS NOT included in the
          # cache because if we were caching, then we would need to use
          # the `-upgrade=true` option. This option blindly pulls down the
          # latest modules and providers instead of checking to see if an
          # update is required. That behavior defeats the benefits of caching.
          # so there is no point in doing it for the .terraform directory.
          path: |
            ${{ env.PIP_CACHE_DIR }}
            ${{ env.PRE_COMMIT_CACHE_DIR }}
            ${{ steps.go-cache.outputs.dir }}
          restore-keys: |
            ${{ env.BASE_CACHE_KEY }}
      - uses: hashicorp/setup-packer@v3
        with:
          version: ${{ steps.setup-env.outputs.packer-version }}
      - uses: hashicorp/setup-terraform@v4
        with:
          terraform_version: ${{ steps.setup-env.outputs.terraform-version }}
      - name: Install go-critic
        env:
          PACKAGE_URL: github.com/go-critic/go-critic/cmd/go-critic
          PACKAGE_VERSION: ${{ steps.setup-env.outputs.go-critic-version }}
        run: go install ${PACKAGE_URL}@${PACKAGE_VERSION}
      - name: Install goimports
        env:
          PACKAGE_URL: golang.org/x/tools/cmd/goimports
          PACKAGE_VERSION: ${{ steps.setup-env.outputs.goimports-version }}
        run: go install ${PACKAGE_URL}@${PACKAGE_VERSION}
      - name: Install gosec
        env:
          PACKAGE_URL: github.com/securego/gosec/v2/cmd/gosec
          PACKAGE_VERSION: ${{ steps.setup-env.outputs.gosec-version }}
        run: go install ${PACKAGE_URL}@${PACKAGE_VERSION}
      - name: Install staticcheck
        env:
          PACKAGE_URL: honnef.co/go/tools/cmd/staticcheck
          PACKAGE_VERSION: ${{ steps.setup-env.outputs.staticcheck-version }}
        run: go install ${PACKAGE_URL}@${PACKAGE_VERSION}
      # TODO: https://github.com/cisagov/skeleton-generic/issues/165
      # We are temporarily using a branch of @mcdonnnj's fork of terraform-docs that
      # groups changes from his PRs until they are approved and merged:
      # https://github.com/terraform-docs/terraform-docs/pull/745
      # https://github.com/terraform-docs/terraform-docs/pull/901
      # This temporary fix will allow for ATX header support when terraform-docs is run
      # during linting and output delimiter rows with cell spacing that passes
      # Markdownlint's MD060/table-column-style rule.
      - name: Clone ATX headers branch from terraform-docs fork
        run: |
          git clone \
           --branch $TERRAFORM_DOCS_REPO_BRANCH_NAME \
           --depth $TERRAFORM_DOCS_REPO_DEPTH \
           --single-branch \
           $TERRAFORM_DOCS_REPO_URL /tmp/terraform-docs
      - name: Build and install terraform-docs binary
        run: |
          go build \
          -C /tmp/terraform-docs \
          -o $(go env GOPATH)/bin/terraform-docs
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip setuptools
          pip install --upgrade --requirement requirements-test.txt
      - name: Set up pre-commit hook environments
        run: pre-commit install-hooks
      - name: Run pre-commit on all files
        run: pre-commit run --all-files
      - name: Setup tmate debug session
        uses: mxschmitt/action-tmate@v3
        if: env.RUN_TMATE


================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
---
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: CodeQL

# The use of on here as a key is part of the GitHub actions syntax.
# yamllint disable-line rule:truthy
on:
  merge_group:
    types:
      - checks_requested
  # We use the default activity types for the pull_request event as specified here:
  # https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request
  pull_request:
    # The branches here must be a subset of the ones in the push key
    branches:
      - develop
  push:
    # Dependabot-triggered push events have read-only access, but uploading code
    # scanning requires write access.
    branches-ignore:
      - dependabot/**
  schedule:
    - cron: 0 2 * * 6

jobs:
  diagnostics:
    name: Run diagnostics
    # This job does not need any permissions
    permissions: {}
    runs-on: ubuntu-latest
    steps:
      # Note that a duplicate of this step must be added at the top of
      # each job.
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          check_github_status: "true"
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          output_workflow_context: "true"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
  analyze:
    name: Analyze
    needs:
      - diagnostics
    runs-on: ubuntu-latest
    permissions:
      # actions/checkout needs this to fetch code
      contents: read
      # required for all workflows
      security-events: write
    strategy:
      fail-fast: false
      matrix:
        # Override automatic language detection by changing the below
        # list
        #
        # Supported options are actions, c-cpp, csharp, go,
        # java-kotlin, javascript-typescript, python, ruby, and swift.
        language:
          - actions
        # Learn more...
        # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection

    steps:
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}

      - name: Checkout repository
        uses: actions/checkout@v6

      # Initializes the CodeQL tools for scanning.
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v4
        with:
          languages: ${{ matrix.language }}

      # Autobuild attempts to build any compiled languages (C/C++, C#, or
      # Java). If this step fails, then you should remove it and run the build
      # manually (see below).
      - name: Autobuild
        uses: github/codeql-action/autobuild@v4

      # ℹ️ Command-line programs to run using the OS shell.
      # 📚 https://git.io/JvXDl

      # ✏️ If the Autobuild fails above, remove it and uncomment the following
      #    three lines and modify them (or add more) to build your code if your
      #    project uses a compiled language

      # - run: |
      #     make bootstrap
      #     make release

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v4


================================================
FILE: .github/workflows/dependency-review.yml
================================================
---
name: Dependency review

on:  # yamllint disable-line rule:truthy
  merge_group:
    types:
      - checks_requested
  # We use the default activity types for the pull_request event as specified here:
  # https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request
  pull_request:

# Set a default shell for any run steps. The `-Eueo pipefail` sets errtrace,
# nounset, errexit, and pipefail. The `-x` will print all commands as they are
# run. Please see the GitHub Actions documentation for more information:
# https://docs.github.com/en/actions/using-jobs/setting-default-values-for-jobs
defaults:
  run:
    shell: bash -Eueo pipefail -x {0}

jobs:
  diagnostics:
    name: Run diagnostics
    # This job does not need any permissions
    permissions: {}
    runs-on: ubuntu-latest
    steps:
      # Note that a duplicate of this step must be added at the top of
      # each job.
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          check_github_status: "true"
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          output_workflow_context: "true"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
  dependency-review:
    name: Dependency review
    needs:
      - diagnostics
    permissions:
      # actions/checkout needs this to fetch code
      contents: read
    runs-on: ubuntu-latest
    steps:
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
      - id: checkout-repo
        name: Checkout the repository
        uses: actions/checkout@v6
      - id: dependency-review
        name: Review dependency changes for vulnerabilities and license changes
        uses: actions/dependency-review-action@v4


================================================
FILE: .github/workflows/label-prs.yml
================================================
---
name: Label pull requests

on:  # yamllint disable-line rule:truthy
  # We use the default activity types for the pull_request event as specified here:
  # https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request
  pull_request:

# Set a default shell for any run steps. The `-Eueo pipefail` sets errtrace,
# nounset, errexit, and pipefail. The `-x` will print all commands as they are
# run. Please see the GitHub Actions documentation for more information:
# https://docs.github.com/en/actions/using-jobs/setting-default-values-for-jobs
defaults:
  run:
    shell: bash -Eueo pipefail -x {0}

jobs:
  diagnostics:
    name: Run diagnostics
    # This job does not need any permissions
    permissions: {}
    runs-on: ubuntu-latest
    steps:
      # Note that a duplicate of this step must be added at the top of
      # each job.
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          check_github_status: "true"
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          output_workflow_context: "true"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
  label:
    needs:
      - diagnostics
    permissions:
      # Permissions required by actions/labeler
      contents: read
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
      - name: Apply suitable labels to a pull request
        uses: actions/labeler@v6


================================================
FILE: .github/workflows/sync-labels.yml
================================================
---
name: sync-labels

on:  # yamllint disable-line rule:truthy
  push:
    paths:
      - .github/labels.yml
      - .github/workflows/sync-labels.yml
  workflow_dispatch:

permissions:
  contents: read

jobs:
  diagnostics:
    name: Run diagnostics
    # This job does not need any permissions
    permissions: {}
    runs-on: ubuntu-latest
    steps:
      # Note that a duplicate of this step must be added at the top of
      # each job.
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          check_github_status: "true"
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          output_workflow_context: "true"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
  labeler:
    needs:
      - diagnostics
    permissions:
      # actions/checkout needs this to fetch code
      contents: read
      # crazy-max/ghaction-github-labeler needs this to manage repository labels
      issues: write
    runs-on: ubuntu-latest
    steps:
      - name: Apply standard cisagov job preamble
        uses: cisagov/action-job-preamble@v1
        with:
          # This functionality is poorly implemented and has been
          # causing problems due to the MITM implementation hogging or
          # leaking memory.  As a result we disable it by default.  If
          # you want to temporarily enable it, simply set
          # monitor_permissions equal to "true".
          #
          # TODO: Re-enable this functionality when practical.  See
          # cisagov/skeleton-generic#207 for more details.
          monitor_permissions: "false"
          # Use a variable to specify the permissions monitoring
          # configuration. By default this will yield the
          # configuration stored in the cisagov organization-level
          # variable, but if you want to use a different configuration
          # then simply:
          # 1. Create a repository-level variable with the name
          # ACTIONS_PERMISSIONS_CONFIG.
          # 2. Set this new variable's value to the configuration you
          # want to use for this repository.
          #
          # Note in particular that changing the permissions
          # monitoring configuration *does not* require you to modify
          # this workflow.
          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
      - uses: actions/checkout@v6
      - name: Sync repository labels
        if: success()
        uses: crazy-max/ghaction-github-labeler@v6
        with:
          # This is a hideous ternary equivalent so we only do a dry run unless
          # this workflow is triggered by the develop branch.
          dry-run: ${{ github.ref_name == 'develop' && 'false' || 'true' }}


================================================
FILE: .gitignore
================================================
# This file specifies intentionally untracked files that Git should ignore.
# Files already tracked by Git are not affected.
# See: https://git-scm.com/docs/gitignore

## Python ##
__pycache__
.mypy_cache
.python-version


================================================
FILE: .isort.cfg
================================================
[settings]
combine_star=true
force_sort_within_sections=true

import_heading_stdlib=Standard Python Libraries
import_heading_thirdparty=Third-Party Libraries
import_heading_firstparty=cisagov Libraries

# Run isort under the black profile to align with our other Python linting
profile=black


================================================
FILE: .mdl_config.yaml
================================================
---

# Default state for all rules
default: true

# MD003/heading-style/header-style - Heading style
MD003:
  # Enforce the ATX-closed style of header
  style: atx_closed

# MD004/ul-style - Unordered list style
MD004:
  # Enforce dashes for unordered lists
  style: dash

# MD013/line-length - Line length
MD013:
  # Do not enforce for code blocks
  code_blocks: false
  # Do not enforce for tables
  tables: false

# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the
# same content
MD024:
  # Allow headers with the same content as long as they are not in the same
  # parent heading
  allow_different_nesting: true

# MD029/ol-prefix - Ordered list item prefix
MD029:
  # Enforce the `1.` style for ordered lists
  style: one

# MD033/no-inline-html - Inline HTML
MD033:
  # The h1 and img elements are allowed to permit header images
  allowed_elements:
    - div
    - h1
    - img

# MD035/hr-style - Horizontal rule style
MD035:
  # Enforce dashes for horizontal rules
  style: ---

# MD046/code-block-style - Code block style
MD046:
  # Enforce the fenced style for code blocks
  style: fenced

# MD049/emphasis-style - Emphasis style should be consistent
MD049:
  # Enforce asterisks as the style to use for emphasis
  style: asterisk

# MD050/strong-style - Strong style should be consistent
MD050:
  # Enforce asterisks as the style to use for strong
  style: asterisk


================================================
FILE: .pre-commit-config.yaml
================================================
---
ci:
  # Do not commit changes from running pre-commit for pull requests.
  autofix_prs: false
  # Autoupdate hooks weekly (this is the default).
  autoupdate_schedule: weekly

default_language_version:
  # force all unspecified python hooks to run python3
  python: python3

repos:
  # Check the pre-commit configuration
  - repo: meta
    hooks:
      - id: check-useless-excludes

  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: check-case-conflict
      - id: check-executables-have-shebangs
      - id: check-json
      - id: check-merge-conflict
      - id: check-shebang-scripts-are-executable
      - id: check-symlinks
      - id: check-toml
      - id: check-vcs-permalinks
      - id: check-xml
      - id: debug-statements
      - id: destroyed-symlinks
      - id: detect-aws-credentials
        args:
          - --allow-missing-credentials
      - id: detect-private-key
      - id: end-of-file-fixer
      - id: mixed-line-ending
        args:
          - --fix=lf
      - id: pretty-format-json
        args:
          - --autofix
      - id: requirements-txt-fixer
      - id: trailing-whitespace

  # Text file hooks
  - repo: https://github.com/igorshubovych/markdownlint-cli
    rev: v0.48.0
    hooks:
      - id: markdownlint
        args:
          - --config=.mdl_config.yaml
  - repo: https://github.com/rbubley/mirrors-prettier
    rev: v3.8.1
    hooks:
      - id: prettier
  - repo: https://github.com/adrienverge/yamllint
    rev: v1.38.0
    hooks:
      - id: yamllint
        args:
          - --strict

  # GitHub Actions hooks
  - repo: https://github.com/python-jsonschema/check-jsonschema
    rev: 0.37.0
    hooks:
      - id: check-github-actions
      - id: check-github-workflows

  # pre-commit hooks
  - repo: https://github.com/pre-commit/pre-commit
    rev: v4.5.1
    hooks:
      - id: validate_manifest

  # Go hooks
  - repo: https://github.com/TekWizely/pre-commit-golang
    rev: v1.0.0-rc.4
    hooks:
      # Go Build
      - id: go-build-repo-mod
      # Style Checkers
      - id: go-critic
      # goimports
      - id: go-imports-repo
        args:
          # Write changes to files
          - -w
      # Go Mod Tidy
      - id: go-mod-tidy-repo
      # GoSec
      - id: go-sec-repo-mod
      # StaticCheck
      - id: go-staticcheck-repo-mod
      # Go Test
      - id: go-test-repo-mod
      # Go Vet
      - id: go-vet-repo-mod
  # Nix hooks
  - repo: https://github.com/nix-community/nixpkgs-fmt
    rev: v1.3.0
    hooks:
      - id: nixpkgs-fmt

  # Shell script hooks
  - repo: https://github.com/scop/pre-commit-shfmt
    rev: v3.13.0-1
    hooks:
      - id: shfmt
        args:
          # List files that will be formatted
          - --list
          # Write result to file instead of stdout
          - --write
          # Indent by two spaces
          - --indent
          - "2"
          # Binary operators may start a line
          - --binary-next-line
          # Switch cases are indented
          - --case-indent
          # Redirect operators are followed by a space
          - --space-redirects
  - repo: https://github.com/shellcheck-py/shellcheck-py
    rev: v0.11.0.1
    hooks:
      - id: shellcheck

  # Python hooks
  - repo: https://github.com/PyCQA/bandit
    rev: 1.9.4
    hooks:
      - id: bandit
  - repo: https://github.com/psf/black-pre-commit-mirror
    rev: 26.3.1
    hooks:
      - id: black
  - repo: https://github.com/PyCQA/flake8
    rev: 7.3.0
    hooks:
      - id: flake8
        additional_dependencies:
          - dlint==0.16.0
          - flake8-bugbear==25.11.29
          - flake8-comprehensions==3.17.0
          - flake8-docstrings==1.7.0
          - flake8-noqa==1.5.0
          - pep8-naming==0.15.1
  - repo: https://github.com/PyCQA/isort
    rev: 8.0.1
    hooks:
      - id: isort
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.19.1
    hooks:
      - id: mypy
  - repo: https://github.com/pypa/pip-audit
    rev: v2.10.0
    hooks:
      - id: pip-audit
        args:
          # We have to ignore this vulnerability for now since an
          # update for pygments has not yet been released.
          #
          # In any event, this vulnerability is unlikely to cause us
          # any problems since we don't feed any regexes to pygments
          # directly.  pygments is pulled in as a dependency of
          # pytest.
          #
          # See also:
          # - https://nvd.nist.gov/vuln/detail/CVE-2026-4539
          # - https://github.com/pygments/pygments/issues/3058
          #
          # TODO: Remove this when it becomes possible.  See
          # cisagov/skeleton-generic#257 for more details.
          - --ignore-vuln
          - CVE-2026-4539
          # Add any pip requirements files to scan
          - --requirement
          - requirements-dev.txt
          - --requirement
          - requirements-test.txt
          - --requirement
          - requirements.txt
  - repo: https://github.com/asottile/pyupgrade
    rev: v3.21.2
    hooks:
      - id: pyupgrade
        args:
          # Python 3.10 is currently the oldest non-EOL version of
          # Python, so we want to apply all rules that apply to this
          # version or later.  See here for more details:
          # https://www.gyford.com/phil/writing/2025/08/26/how-to-use-pyupgrade/
          - --py310-plus

  # Ansible hooks
  - repo: https://github.com/ansible/ansible-lint
    # We need to stay on this version because we are still using Python 3.13 in
    # our GitHub Actions configuration. Later versions require Python 3.14 for
    # the hook to run.
    rev: v26.1.1
    hooks:
      - id: ansible-lint
        additional_dependencies:
          # On its own ansible-lint does not pull in ansible, only
          # ansible-core.  Therefore, if an Ansible module lives in
          # ansible instead of ansible-core, the linter will complain
          # that the module is unknown.  In these cases it is
          # necessary to add the ansible package itself as an
          # additional dependency, with the same pinning as is done in
          # requirements-test.txt of cisagov/skeleton-ansible-role.
          #
          # Version 10 is required because the pip-audit pre-commit
          # hook identifies a vulnerability in ansible-core 2.16.13,
          # but all versions of ansible 9 have a dependency on
          # ~=2.16.X.
          # - ansible>=10,<11
          # ansible-core<2.17.7 suffers from GHSA-99w6-3xph-cx78.
          #
          # Note that any changes made to this dependency must also be
          # made in requirements.txt in cisagov/skeleton-packer and
          # requirements-test.txt in cisagov/skeleton-ansible-role.
          - ansible-core>=2.17.7

  # Terraform hooks
  - repo: https://github.com/antonbabenko/pre-commit-terraform
    rev: v1.105.0
    hooks:
      - id: terraform_fmt
      - id: terraform_validate
      # This needs to run after the terraform_validate hook so that any Terraform
      # configurations are initialized.
      - id: terraform_providers_lock
        args:
          - --args=-platform=darwin_amd64
          - --args=-platform=darwin_arm64
          - --args=-platform=linux_amd64
          - --args=-platform=linux_arm64
          - --hook-config=--mode=always-regenerate-lockfile

  # Docker hooks
  - repo: https://github.com/IamTheFij/docker-pre-commit
    rev: v3.0.1
    hooks:
      - id: docker-compose-check

  # Packer hooks
  - repo: https://github.com/cisagov/pre-commit-packer
    rev: v0.3.1
    hooks:
      - id: packer_fmt
      - id: packer_validate


================================================
FILE: .prettierignore
================================================
# Already being linted by pretty-format-json
*.json
# Already being linted by mdl
*.md
# Already being linted by yamllint
*.yaml
*.yml


================================================
FILE: .yamllint
================================================
---
extends: default

rules:
  braces:
    # Do not allow non-empty flow mappings
    forbid: non-empty
    # Allow up to one space inside braces. This is required for Ansible compatibility.
    max-spaces-inside: 1

  brackets:
    # Do not allow non-empty flow sequences
    forbid: non-empty

  comments:
    # Ensure that inline comments have at least one space before the preceding content.
    # This is required for Ansible compatibility.
    min-spaces-from-content: 1

  # yamllint does not like it when you comment out different parts of
  # dictionaries in a list. You can see
  # https://github.com/adrienverge/yamllint/issues/384 for some examples of
  # this behavior.
  comments-indentation: disable

  indentation:
    # Ensure that block sequences inside of a mapping are indented
    indent-sequences: true
    # Enforce a specific number of spaces
    spaces: 2

  # yamllint does not allow inline mappings that exceed the line length by
  # default. There are many scenarios where the inline mapping may be a key,
  # hash, or other long value that would exceed the line length but cannot
  # reasonably be broken across lines.
  line-length:
    # This rule implies the allow-non-breakable-words rule
    allow-non-breakable-inline-mappings: true
    # Allows a 10% overage from the default limit of 80
    max: 88

  # Using anything other than strings to express octal values can lead to unexpected
  # and potentially unsafe behavior. Ansible strongly recommends against such practices
  # and these rules are needed for Ansible compatibility. Please see the following for
  # more information:
  # https://ansible.readthedocs.io/projects/lint/rules/risky-octal/
  octal-values:
    # Do not allow explicit octal values (those beginning with a leading 0o).
    forbid-explicit-octal: true
    # Do not allow implicit octal values (those beginning with a leading 0).
    forbid-implicit-octal: true

  quoted-strings:
    # Allow disallowed quotes (single quotes) for strings that contain allowed quotes
    # (double quotes).
    allow-quoted-quotes: true
    # Apply these rules to keys in mappings as well
    check-keys: true
    # We prefer double quotes for strings when they are needed
    quote-type: double
    # Only require quotes when they are necessary for proper processing
    required: only-when-needed


================================================
FILE: CONTRIBUTING.md
================================================
# Welcome #

We're so glad you're thinking about contributing to this open source
project!  If you're unsure or afraid of anything, just ask or submit
the issue or pull request anyway.  The worst that can happen is that
you'll be politely asked to change something.  We appreciate any sort
of contribution, and don't want a wall of rules to get in the way of
that.

Before contributing, we encourage you to read our CONTRIBUTING policy
(you are here), our [LICENSE](LICENSE), and our [README](README.md),
all of which should be in this repository.

## Issues ##

If you want to report a bug or request a new feature, the most direct
method is to [create an
issue](https://github.com/cisagov/bad-practices/issues) in this
repository.  We recommend that you first search through existing
issues (both open and closed) to check if your particular issue has
already been reported.  If it has then you might want to add a comment
to the existing issue.  If it hasn't then feel free to create a new
one.

## Pull requests ##

If you choose to [submit a pull
request](https://github.com/cisagov/bad-practices/pulls), you will
notice that our continuous integration (CI) system runs a fairly
extensive set of linters and syntax checkers.  Your pull request may
fail these checks, and that's OK.  If you want you can stop there and
wait for us to make the necessary corrections to ensure your code
passes the CI checks.

If you want to make the changes yourself, or if you want to become a
regular contributor, then you will want to set up
[pre-commit](https://pre-commit.com/) on your local machine.  Once you
do that, the CI checks will run locally before you even write your
commit message.  This speeds up your development cycle considerably.

### Setting up pre-commit ###

There are a few ways to do this, but we prefer to use
[`pyenv`](https://github.com/pyenv/pyenv) and
[`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv) to
create and manage a Python virtual environment specific to this
project.

We recommend using the `setup-env` script located in this repository,
as it automates the entire environment configuration process. The
dependencies required to run this script are
[GNU `getopt`](https://github.com/util-linux/util-linux/blob/master/misc-utils/getopt.1.adoc),
[`pyenv`](https://github.com/pyenv/pyenv), and [`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv).
If these tools are already configured on your system, you can simply run the
following command:

```console
./setup-env
```

Otherwise, follow the steps below to manually configure your
environment.

#### Installing and using GNU `getopt`, `pyenv`, and `pyenv-virtualenv` ####

On macOS, we recommend installing [brew](https://brew.sh/).  Then
installation is as simple as `brew install gnu-getopt pyenv pyenv-virtualenv` and
adding this to your profile:

```bash
# GNU getopt must be explicitly added to the path since it is
# keg-only (https://docs.brew.sh/FAQ#what-does-keg-only-mean)
export PATH="$(brew --prefix)/opt/gnu-getopt/bin:$PATH"

# Setup pyenv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
```

For Linux, Windows Subsystem for Linux (WSL), or macOS (if you
don't want to use `brew`) you can use
[pyenv/pyenv-installer](https://github.com/pyenv/pyenv-installer) to
install the necessary tools. Before running this ensure that you have
installed the prerequisites for your platform according to the
[`pyenv` wiki
page](https://github.com/pyenv/pyenv/wiki/common-build-problems).
GNU `getopt` is included in most Linux distributions as part of the
[`util-linux`](https://github.com/util-linux/util-linux) package.

On WSL you should treat your platform as whatever Linux distribution
you've chosen to install.

Once you have installed `pyenv` you will need to add the following
lines to your `.bash_profile` (or `.profile`):

```bash
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
```

and then add the following lines to your `.bashrc`:

```bash
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
```

If you want more information about setting up `pyenv` once installed, please run

```console
pyenv init
```

and

```console
pyenv virtualenv-init
```

for the current configuration instructions.

If you are using a shell other than `bash` you should follow the
instructions that the `pyenv-installer` script outputs.

You will need to reload your shell for these changes to take effect so
you can begin to use `pyenv`.

For a list of Python versions that are already installed and ready to
use with `pyenv`, use the command `pyenv versions`.  To see a list of
the Python versions available to be installed and used with `pyenv`
use the command `pyenv install --list`.  You can read more about
the [many things that `pyenv` can do](https://github.com/pyenv/pyenv/blob/master/COMMANDS.md).
See the [usage information](https://github.com/pyenv/pyenv-virtualenv#usage)
for the additional capabilities that pyenv-virtualenv adds to the `pyenv`
command.

#### Creating the Python virtual environment ####

Once `pyenv` and `pyenv-virtualenv` are installed on your system, you
can create and configure the Python virtual environment with these
commands:

```console
cd bad-practices
pyenv virtualenv <python_version_to_use> bad-practices
pyenv local bad-practices
pip install --requirement requirements-dev.txt
```

#### Installing the pre-commit hook ####

Now setting up pre-commit is as simple as:

```console
pre-commit install
```

At this point the pre-commit checks will run against any files that
you attempt to commit.  If you want to run the checks against the
entire repo, just execute `pre-commit run --all-files`.

## Public domain ##

This project is in the public domain within the United States, and
copyright and related rights in the work worldwide are waived through
the [CC0 1.0 Universal public domain
dedication](https://creativecommons.org/publicdomain/zero/1.0/).

All contributions to this project will be released under the CC0
dedication. By submitting a pull request, you are agreeing to comply
with this waiver of copyright interest.


================================================
FILE: LICENSE
================================================
CC0 1.0 Universal

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.

For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:

  i. the right to reproduce, adapt, distribute, perform, display, communicate,
  and translate a Work;

  ii. moral rights retained by the original author(s) and/or performer(s);

  iii. publicity and privacy rights pertaining to a person's image or likeness
  depicted in a Work;

  iv. rights protecting against unfair competition in regards to a Work,
  subject to the limitations in paragraph 4(a), below;

  v. rights protecting the extraction, dissemination, use and reuse of data in
  a Work;

  vi. database rights (such as those arising under Directive 96/9/EC of the
  European Parliament and of the Council of 11 March 1996 on the legal
  protection of databases, and under any national implementation thereof,
  including any amended or successor version of such directive); and

  vii. other similar, equivalent or corresponding rights throughout the world
  based on applicable law or treaty, and any national implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.

4. Limitations and Disclaimers.

  a. No trademark or patent rights held by Affirmer are waived, abandoned,
  surrendered, licensed or otherwise affected by this document.

  b. Affirmer offers the Work as-is and makes no representations or warranties
  of any kind concerning the Work, express, implied, statutory or otherwise,
  including without limitation warranties of title, merchantability, fitness
  for a particular purpose, non infringement, or the absence of latent or
  other defects, accuracy, or the present or absence of errors, whether or not
  discoverable, all to the greatest extent permissible under applicable law.

  c. Affirmer disclaims responsibility for clearing rights of other persons
  that may apply to the Work or any use thereof, including without limitation
  any person's Copyright and Related Rights in the Work. Further, Affirmer
  disclaims responsibility for obtaining any necessary consents, permissions
  or other rights required for any use of the Work.

  d. Affirmer understands and acknowledges that Creative Commons is not a
  party to this document and has no duty or obligation with respect to this
  CC0 or use of the Work.

For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>


================================================
FILE: README.md
================================================
# 👋 Welcome to CISA's Bad Practices Catalog #

[![GitHub Build Status](https://github.com/cisagov/bad-practices/workflows/build/badge.svg)](https://github.com/cisagov/bad-practices/actions)
[![License](https://img.shields.io/github/license/cisagov/bad-practices)](https://spdx.org/licenses/)
[![CodeQL](https://github.com/cisagov/bad-practices/workflows/CodeQL/badge.svg)](https://github.com/cisagov/bad-practices/actions/workflows/codeql-analysis.yml)

<div align="center">
<img alt="Banner" width="460" src="assets/banner.png">
</div>

We’re using [GitHub
discussions](https://github.com/cisagov/bad-practices/discussions) as a place to
connect and engage in a critical conversations with other members in the
community. We hope that you will:

- Ask questions if something doesn't make sense.
- Share your thoughts on existing, and ideas for future, bad practice entries.
- Engage with us and other community members on ideas and actions to eradicate
  bad practices.
- Welcome others and maintain an open mind.

---

## Bad Practices ##

As recent incidents have demonstrated, cyber attacks against critical
infrastructure can have significant impacts on the critical functions of
government and the private sector. All organizations, and particularly those
supporting designated critical infrastructure or [national critical functions
(NCF)](https://www.cisa.gov/national-critical-functions) should implement an
effective cybersecurity program to protect against cyber threats and manage
cyber risk in a manner commensurate with the criticality of those NCFs to
national security, national economic security, and/or national public health and
safety.

CISA is developing a catalog of bad practices that are exceptionally risky,
especially in organizations supporting critical infrastructure or NCFs. The
presence of these bad practices in organizations that support critical
infrastructure or NCFs is exceptionally dangerous and increases risk to our
critical infrastructure, on which we rely for national security, economic
stability, and life, health, and safety of the public. Entries in the catalog
will be listed here as they are added.

1. Use of unsupported (or end-of-life) software in service of critical
   infrastructure and national critical functions is dangerous and significantly
   elevates risk to national security, national economic security, and national
   public health and safety. This dangerous practice is especially egregious in
   technologies accessible from the internet.

1. Use of known/fixed/default passwords and credentials in service of Critical
   Infrastructure and national critical functions is dangerous and significantly
   elevates risk to national security, national economic security, and national
   public health and safety. This dangerous practice is especially egregious in
   technologies accessible from the internet.

1. The use of single-factor authentication for remote or administrative access
   to systems supporting the operation of Critical Infrastructure and national
   critical functions (NCF) is dangerous and significantly elevates risk to
   national security, national economic security, and national public health and
   safety. This dangerous practice is especially egregious in technologies
   accessible from the internet.

While these practices are dangerous for critical infrastructure and NCFs, CISA
encourages all organizations to engage in the necessary actions and critical
conversations to address bad practices.

*Note: This list is focused and does not include every possible inadvisable
cybersecurity practice. The lack of inclusion of any particular cybersecurity
practice does not indicate that CISA endorses such a practice or deems such a
practice to present acceptable levels of risk.*

## Contributing ##

Join the [bad practices
discussion](https://github.com/cisagov/bad-practices/discussions).  We welcome
feedback about our current catalog of bad practices and want to hear your
suggestions for additions.

## License ##

This project is in the worldwide [public domain](LICENSE).

This project is in the public domain within the United States, and
copyright and related rights in the work worldwide are waived through
the [CC0 1.0 Universal public domain
dedication](https://creativecommons.org/publicdomain/zero/1.0/).

All contributions to this project will be released under the CC0
dedication. By submitting a pull request, you are agreeing to comply
with this waiver of copyright interest.


================================================
FILE: bump-version
================================================
#!/usr/bin/env bash

# bump-version [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
# bump-version --list-files

set -o nounset
set -o errexit
set -o pipefail

# Stores the canonical version for the project.
VERSION_FILE=version.txt
# Files that should be updated with the new version.
VERSION_FILES=("$VERSION_FILE")

USAGE=$(
  cat << END_OF_LINE
Update the version of the project.

Usage:
  ${0##*/} [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
  ${0##*/} --list-files
  ${0##*/} (-h | --help)

Options:
  -h | --help    Show this message.
  --push         Perform a \`git push\` after updating the version.
  --label LABEL  Specify the label to use when updating the build or prerelease version.
  --list-files   List the files that will be updated when the version is bumped.
END_OF_LINE
)

old_version=$(< "$VERSION_FILE")
# Comment out periods so they are interpreted as periods and don't
# just match any character
old_version_regex=${old_version//\./\\\.}
new_version="$old_version"

bump_part=""
label=""
commit_prefix="Bump"
with_push=false
commands_with_label=("build" "prerelease")
commands_with_prerelease=("major" "minor" "patch")
with_prerelease=false

#######################################
# Display an error message, the help information, and exit with a non-zero status.
# Arguments:
#   Error message.
#######################################
function invalid_option() {
  echo "$1"
  echo "$USAGE"
  exit 1
}

#######################################
# Bump the version using the provided command.
# Arguments:
#   The version to bump.
#   The command to bump the version.
# Returns:
#   The new version.
#######################################
function bump_version() {
  local temp_version
  temp_version=$(python -c "import semver; print(semver.parse_version_info('$1').${2})")
  echo "$temp_version"
}

if [ $# -eq 0 ]; then
  echo "$USAGE"
  exit 1
else
  while [ $# -gt 0 ]; do
    case $1 in
      --push)
        if [ "$with_push" = true ]; then
          invalid_option "Push has already been set."
        fi

        with_push=true
        shift
        ;;
      --label)
        if [ -n "$label" ]; then
          invalid_option "Label has already been set."
        fi

        label="$2"
        shift 2
        ;;
      build | finalize | major | minor | patch)
        if [ -n "$bump_part" ]; then
          invalid_option "Only one version part should be bumped at a time."
        fi

        bump_part="$1"
        shift
        ;;
      prerelease)
        with_prerelease=true
        shift
        ;;
      show)
        echo "$old_version"
        exit 0
        ;;
      -h | --help)
        echo "$USAGE"
        exit 0
        ;;
      --list-files)
        printf '%s\n' "${VERSION_FILES[@]}"
        exit 0
        ;;
      *)
        invalid_option "Invalid option: $1"
        ;;
    esac
  done
fi

if [ -n "$label" ] && [ "$with_prerelease" = false ] && [[ ! " ${commands_with_label[*]} " =~ [[:space:]]${bump_part}[[:space:]] ]]; then
  invalid_option "Setting the label is only allowed for the following commands: ${commands_with_label[*]}"
fi

if [ "$with_prerelease" = true ] && [ -n "$bump_part" ] && [[ ! " ${commands_with_prerelease[*]} " =~ [[:space:]]${bump_part}[[:space:]] ]]; then
  invalid_option "Changing the prerelease is only allowed in conjunction with the following commands: ${commands_with_prerelease[*]}"
fi

label_option=""
if [ -n "$label" ]; then
  label_option="token='$label'"
fi

if [ -n "$bump_part" ]; then
  if [ "$bump_part" = "finalize" ]; then
    commit_prefix="Finalize"
    bump_command="finalize_version()"
  elif [ "$bump_part" = "build" ]; then
    bump_command="bump_${bump_part}($label_option)"
  else
    bump_command="bump_${bump_part}()"
  fi
  new_version=$(bump_version "$old_version" "$bump_command")
  echo Changing version from "$old_version" to "$new_version"
fi

if [ "$with_prerelease" = true ]; then
  bump_command="bump_prerelease($label_option)"
  temp_version=$(bump_version "$new_version" "$bump_command")
  echo Changing version from "$new_version" to "$temp_version"
  new_version="$temp_version"
fi

tmp_file=/tmp/version.$$
for version_file in "${VERSION_FILES[@]}"; do
  if [ ! -f "$version_file" ]; then
    echo Missing expected file: "$version_file"
    exit 1
  fi
  sed "s/$old_version_regex/$new_version/" "$version_file" > $tmp_file
  mv $tmp_file "$version_file"
done

git add "${VERSION_FILES[@]}"
git commit --message "$commit_prefix version from $old_version to $new_version"

if [ "$with_push" = true ]; then
  git push
fi


================================================
FILE: requirements-dev.txt
================================================
--requirement requirements-test.txt
ipython
# The bump-version script requires at least version 3 of semver.
semver>=3


================================================
FILE: requirements-test.txt
================================================
--requirement requirements.txt
pre-commit


================================================
FILE: requirements.txt
================================================
setuptools>=70.1


================================================
FILE: setup-env
================================================
#!/usr/bin/env bash

set -o nounset
set -o errexit
set -o pipefail

USAGE=$(
  cat << 'END_OF_LINE'
Configure a development environment for this repository.

It does the following:
  - Allows the user to specify the Python version to use for the virtual environment.
  - Allows the user to specify a name for the virtual environment.
  - Verifies pyenv and pyenv-virtualenv are installed.
  - Creates the Python virtual environment.
  - Configures the activation of the virtual enviroment for the repo directory.
  - Installs the requirements needed for development.
  - Installs git pre-commit hooks.
  - Configures git remotes for upstream "lineage" repositories.

Usage:
  setup-env [--venv-name venv_name] [--python-version python_version]
  setup-env (-h | --help)

Options:
  -f | --force             Delete virtual enviroment if it already exists.
  -h | --help              Show this message.
  -i | --install-hooks     Install hook environments for all environments in the
                           pre-commit config file.
  -l | --list-versions     List available Python versions and select one interactively.
  -v | --venv-name         Specify the name of the virtual environment.
  -p | --python-version    Specify the Python version for the virtual environment.

END_OF_LINE
)

# Display pyenv's installed Python versions
python_versions() {
  pyenv versions --bare --skip-aliases --skip-envs
}

check_python_version() {
  local version=$1

  # This is a valid regex for semantically correct Python version strings.
  # For more information see here:
  # https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
  # Break down the regex into readable parts major.minor.patch
  local major="0|[1-9]\d*"
  local minor="0|[1-9]\d*"
  local patch="0|[1-9]\d*"

  # Splitting the prerelease part for readability
  # Start of the prerelease
  local prerelease="(?:-"
  # Numeric or alphanumeric identifiers
  local prerelease+="(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"
  # Additional dot-separated identifiers
  local prerelease+="(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*"
  # End of the prerelease, making it optional
  local prerelease+=")?"
  # Optional build metadata
  local build="(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?"

  # Final regex composed of parts
  local regex="^($major)\.($minor)\.($patch)$prerelease$build$"

  # This checks if the Python version does not match the regex pattern specified in $regex,
  # using Perl for regex matching. If the pattern is not found, then prompt the user with
  # the invalid version message.
  if ! echo "$version" | perl -ne "exit(!/$regex/)"; then
    echo "Invalid version of Python: Python follows semantic versioning," \
      "so any version string that is not a valid semantic version is an" \
      "invalid version of Python."
    exit 1
  # Else if the Python version isn't installed then notify the user.
  # grep -E is used for searching through text lines that match the
  # specific version.
  elif ! python_versions | grep -E "^${version}$" > /dev/null; then
    echo "Error: Python version $version is not installed."
    echo "Installed Python versions are:"
    python_versions
    exit 1
  else
    echo "Using Python version $version"
  fi
}

# Flag to force deletion and creation of virtual environment
FORCE=0

# Initialize the other flags
INSTALL_HOOKS=0
LIST_VERSIONS=0
PYTHON_VERSION=""
VENV_NAME=""

# Define long options
LONGOPTS="force,help,install-hooks,list-versions,python-version:,venv-name:"

# Define short options for getopt
SHORTOPTS="fhilp:v:"

# Check for GNU getopt by testing for long option support. GNU getopt supports
# the "--test" option and will return exit code 4 while POSIX/BSD getopt does
# not and will return exit code 0.
if getopt --test > /dev/null 2>&1; then
  cat << 'END_OF_LINE'

  Please note, this script requires GNU getopt due to its enhanced
  functionality and compatibility with certain script features that
  are not supported by the POSIX getopt found in some systems, particularly
  those with a non-GNU version of getopt. This distinction is crucial
  as a system might have a non-GNU version of getopt installed by default,
  which could lead to unexpected behavior.

  On macOS, we recommend installing brew (https://brew.sh/).  Then installation
  is as simple as `brew install gnu-getopt` and adding this to your
  profile:

  export PATH="$(brew --prefix)/opt/gnu-getopt/bin:$PATH"

  GNU getopt must be explicitly added to the PATH since it
  is keg-only (https://docs.brew.sh/FAQ#what-does-keg-only-mean).

END_OF_LINE
  exit 1
fi

# Check to see if pyenv is installed
if [ -z "$(command -v pyenv)" ] || { [ -z "$(command -v pyenv-virtualenv)" ] && [ ! -f "$(pyenv root)/plugins/pyenv-virtualenv/bin/pyenv-virtualenv" ]; }; then
  echo "pyenv and pyenv-virtualenv are required."
  if [[ "$OSTYPE" == "darwin"* ]]; then
    cat << 'END_OF_LINE'

  On macOS, we recommend installing brew, https://brew.sh/.  Then installation
  is as simple as `brew install pyenv pyenv-virtualenv` and adding this to your
  profile:

  eval "$(pyenv init -)"
  eval "$(pyenv virtualenv-init -)"

END_OF_LINE

  fi
  cat << 'END_OF_LINE'
  For Linux, Windows Subsystem for Linux (WSL), or macOS (if you don't want
  to use "brew") you can use https://github.com/pyenv/pyenv-installer to install
  the necessary tools. Before running this ensure that you have installed the
  prerequisites for your platform according to the pyenv wiki page,
  https://github.com/pyenv/pyenv/wiki/common-build-problems.

  On WSL you should treat your platform as whatever Linux distribution you've
  chosen to install.

  Once you have installed "pyenv" you will need to add the following lines to
  your ".bashrc":

  export PATH="$PATH:$HOME/.pyenv/bin"
  eval "$(pyenv init -)"
  eval "$(pyenv virtualenv-init -)"
END_OF_LINE
  exit 1
fi

# Use GNU getopt to parse options
if ! PARSED=$(getopt --options $SHORTOPTS --longoptions $LONGOPTS --name "$0" -- "$@"); then
  echo "Error parsing options"
  exit 1
fi
eval set -- "$PARSED"

while true; do
  case "$1" in
    -f | --force)
      FORCE=1
      shift
      ;;
    -h | --help)
      echo "$USAGE"
      exit 0
      ;;
    -i | --install-hooks)
      INSTALL_HOOKS=1
      shift
      ;;
    -l | --list-versions)
      LIST_VERSIONS=1
      shift
      ;;
    -p | --python-version)
      PYTHON_VERSION="$2"
      shift 2
      # Check the Python version being passed in.
      check_python_version "$PYTHON_VERSION"
      ;;
    -v | --venv-name)
      VENV_NAME="$2"
      shift 2
      ;;
    --)
      shift
      break
      ;;
    *)
      # Unreachable due to GNU getopt handling all options
      echo "Programming error"
      exit 64
      ;;
  esac
done

# Determine the virtual environment name
if [ -n "$VENV_NAME" ]; then
  # Use the user-provided environment name
  env_name="$VENV_NAME"
else
  # Set the environment name to the last part of the working directory.
  env_name=${PWD##*/}
fi

# List Python versions and select one interactively.
if [ $LIST_VERSIONS -ne 0 ]; then
  echo Available Python versions:
  python_versions
  # Read the user's desired Python version.
  # -r: treat backslashes as literal, -p: display prompt before input.
  read -r -p "Enter the desired Python version: " PYTHON_VERSION
  # Check the Python version being passed in.
  check_python_version "$PYTHON_VERSION"
fi

# Remove any lingering local configuration.
if [ $FORCE -ne 0 ]; then
  rm -f .python-version
  pyenv virtualenv-delete --force "${env_name}" || true
elif [[ -f .python-version ]]; then
  cat << 'END_OF_LINE'
  An existing .python-version file was found.  Either remove this file yourself
  or re-run with the --force option to have it deleted along with the associated
  virtual environment.

  rm .python-version

END_OF_LINE
  exit 1
fi

# Create a new virtual environment for this project
#
# If $PYTHON_VERSION is undefined then the current pyenv Python version will be used.
#
# We can't quote ${PYTHON_VERSION:=} below since if the variable is
# undefined then we want nothing to appear; this is the reason for the
# "shellcheck disable" line below.
#
# shellcheck disable=SC2086
if ! pyenv virtualenv ${PYTHON_VERSION:=} "${env_name}"; then
  cat << END_OF_LINE
  An existing virtual environment named $env_name was found.  Either delete this
  environment yourself or re-run with the --force option to have it deleted.

  pyenv virtualenv-delete ${env_name}

END_OF_LINE
  exit 1
fi

# Set the local application-specific Python version(s) by writing the
# version name to a file named `.python-version'.
pyenv local "${env_name}"

# Upgrade pip and friends
python3 -m pip install --upgrade pip setuptools

# Find a requirements file (if possible) and install
for req_file in "requirements-dev.txt" "requirements-test.txt" "requirements.txt"; do
  if [[ -f $req_file ]]; then
    pip install --requirement $req_file
    break
  fi
done

# Install git pre-commit hooks now or later.
pre-commit install ${INSTALL_HOOKS:+"--install-hooks"}

# Setup git remotes from lineage configuration
# This could fail if the remotes are already setup, but that is ok.
set +o errexit

eval "$(
  python3 << 'END_OF_LINE'
from pathlib import Path
import yaml
import sys

LINEAGE_CONFIG = Path(".github/lineage.yml")

if not LINEAGE_CONFIG.exists():
    print("No lineage configuration found.", file=sys.stderr)
    sys.exit(0)

with LINEAGE_CONFIG.open("r") as f:
    lineage = yaml.safe_load(stream=f)

if lineage["version"] == "1":
    for parent_name, v in lineage["lineage"].items():
        remote_url = v["remote-url"]
        print(f"git remote add {parent_name} {remote_url};")
        print(f"git remote set-url --push {parent_name} no_push;")
else:
    print(f'Unsupported lineage version: {lineage["version"]}', file=sys.stderr)
END_OF_LINE
)"

# Qapla'
echo "Success!"


================================================
FILE: version.txt
================================================
1.0.0
Download .txt
gitextract_x1k3vyxe/

├── .ansible-lint
├── .flake8
├── .github/
│   ├── CODEOWNERS
│   ├── dependabot.yml
│   ├── labeler.yml
│   ├── labels.yml
│   ├── lineage.yml
│   └── workflows/
│       ├── build.yml
│       ├── codeql-analysis.yml
│       ├── dependency-review.yml
│       ├── label-prs.yml
│       └── sync-labels.yml
├── .gitignore
├── .isort.cfg
├── .mdl_config.yaml
├── .pre-commit-config.yaml
├── .prettierignore
├── .yamllint
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── bump-version
├── requirements-dev.txt
├── requirements-test.txt
├── requirements.txt
├── setup-env
└── version.txt
Condensed preview — 27 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (86K chars).
[
  {
    "path": ".ansible-lint",
    "chars": 807,
    "preview": "---\n# See https://ansible-lint.readthedocs.io/configuring/ for a list of\n# the configuration elements that can exist in "
  },
  {
    "path": ".flake8",
    "chars": 2100,
    "preview": "[flake8]\nmax-line-length = 80\n\n# Select (turn on)\n# * C: Complexity violations reported by mccabe -\n#   https://flake8.p"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 1072,
    "preview": "# Each line is a file pattern followed by one or more owners.\n\n# These owners will be the default owners for everything "
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 1481,
    "preview": "---\n\n# Any ignore directives should be uncommented in downstream projects to disable\n# Dependabot updates for the given "
  },
  {
    "path": ".github/labeler.yml",
    "chars": 2165,
    "preview": "---\n# Each entry in this file is a label that will be applied to pull requests\n# if there is a match based on the matchi"
  },
  {
    "path": ".github/labels.yml",
    "chars": 3421,
    "preview": "---\n# Rather than breaking up descriptions into multiline strings we disable that\n# specific rule in yamllint for this f"
  },
  {
    "path": ".github/lineage.yml",
    "chars": 102,
    "preview": "---\nlineage:\n  skeleton:\n    remote-url: https://github.com/cisagov/skeleton-generic.git\nversion: \"1\"\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 8984,
    "preview": "---\nname: build\n\non:  # yamllint disable-line rule:truthy\n  merge_group:\n    types:\n      - checks_requested\n  # We use "
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 5687,
    "preview": "---\n# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#"
  },
  {
    "path": ".github/workflows/dependency-review.yml",
    "chars": 4198,
    "preview": "---\nname: Dependency review\n\non:  # yamllint disable-line rule:truthy\n  merge_group:\n    types:\n      - checks_requested"
  },
  {
    "path": ".github/workflows/label-prs.yml",
    "chars": 3963,
    "preview": "---\nname: Label pull requests\n\non:  # yamllint disable-line rule:truthy\n  # We use the default activity types for the pu"
  },
  {
    "path": ".github/workflows/sync-labels.yml",
    "chars": 3883,
    "preview": "---\nname: sync-labels\n\non:  # yamllint disable-line rule:truthy\n  push:\n    paths:\n      - .github/labels.yml\n      - .g"
  },
  {
    "path": ".gitignore",
    "chars": 221,
    "preview": "# This file specifies intentionally untracked files that Git should ignore.\n# Files already tracked by Git are not affec"
  },
  {
    "path": ".isort.cfg",
    "chars": 292,
    "preview": "[settings]\ncombine_star=true\nforce_sort_within_sections=true\n\nimport_heading_stdlib=Standard Python Libraries\nimport_hea"
  },
  {
    "path": ".mdl_config.yaml",
    "chars": 1406,
    "preview": "---\n\n# Default state for all rules\ndefault: true\n\n# MD003/heading-style/header-style - Heading style\nMD003:\n  # Enforce "
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 7645,
    "preview": "---\nci:\n  # Do not commit changes from running pre-commit for pull requests.\n  autofix_prs: false\n  # Autoupdate hooks w"
  },
  {
    "path": ".prettierignore",
    "chars": 135,
    "preview": "# Already being linted by pretty-format-json\n*.json\n# Already being linted by mdl\n*.md\n# Already being linted by yamllin"
  },
  {
    "path": ".yamllint",
    "chars": 2342,
    "preview": "---\nextends: default\n\nrules:\n  braces:\n    # Do not allow non-empty flow mappings\n    forbid: non-empty\n    # Allow up t"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 6236,
    "preview": "# Welcome #\n\nWe're so glad you're thinking about contributing to this open source\nproject!  If you're unsure or afraid o"
  },
  {
    "path": "LICENSE",
    "chars": 6555,
    "preview": "CC0 1.0 Universal\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclus"
  },
  {
    "path": "README.md",
    "chars": 4490,
    "preview": "# 👋 Welcome to CISA's Bad Practices Catalog #\n\n[![GitHub Build Status](https://github.com/cisagov/bad-practices/workflow"
  },
  {
    "path": "bump-version",
    "chars": 4634,
    "preview": "#!/usr/bin/env bash\n\n# bump-version [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | sh"
  },
  {
    "path": "requirements-dev.txt",
    "chars": 119,
    "preview": "--requirement requirements-test.txt\nipython\n# The bump-version script requires at least version 3 of semver.\nsemver>=3\n"
  },
  {
    "path": "requirements-test.txt",
    "chars": 42,
    "preview": "--requirement requirements.txt\npre-commit\n"
  },
  {
    "path": "requirements.txt",
    "chars": 17,
    "preview": "setuptools>=70.1\n"
  },
  {
    "path": "setup-env",
    "chars": 9892,
    "preview": "#!/usr/bin/env bash\n\nset -o nounset\nset -o errexit\nset -o pipefail\n\nUSAGE=$(\n  cat << 'END_OF_LINE'\nConfigure a developm"
  },
  {
    "path": "version.txt",
    "chars": 6,
    "preview": "1.0.0\n"
  }
]

About this extraction

This page contains the full source code of the cisagov/bad-practices GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 27 files (80.0 KB), approximately 20.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!