Full Code of undistro/marvin for AI

main 8ecf9a6c1f66 cached
128 files
324.5 KB
93.9k tokens
138 symbols
1 requests
Download .txt
Showing preview only (358K chars total). Download the full file or copy to clipboard to get everything.
Repository: undistro/marvin
Branch: main
Commit: 8ecf9a6c1f66
Files: 128
Total size: 324.5 KB

Directory structure:
gitextract_roenwdf7/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .goreleaser.yaml
├── .krew.yaml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── MAINTAINERS.md
├── Makefile
├── README.md
├── checks.md
├── cmd/
│   ├── root.go
│   ├── scan.go
│   └── version.go
├── examples/
│   ├── labels.yml
│   └── replicas.yml
├── go.mod
├── go.sum
├── install.sh
├── internal/
│   └── builtins/
│       ├── cis/
│       │   ├── M-500_workload_in_default_namespace.yaml
│       │   └── M-500_workload_in_default_namespace_test.yaml
│       ├── embed.go
│       ├── embed_test.go
│       ├── general/
│       │   ├── M-400_image_tagged_latest.yaml
│       │   ├── M-400_image_tagged_latest_test.yaml
│       │   ├── M-401_unmanaged_pod.yaml
│       │   ├── M-401_unmanaged_pod_test.yaml
│       │   ├── M-402_readiness_probe.yaml
│       │   ├── M-402_readiness_probe_test.yaml
│       │   ├── M-403_liveness_probe.yaml
│       │   ├── M-403_liveness_probe_test.yaml
│       │   ├── M-404_memory_requests.yaml
│       │   ├── M-404_memory_requests_test.yaml
│       │   ├── M-405_cpu_requests.yaml
│       │   ├── M-405_cpu_requests_test.yaml
│       │   ├── M-406_memory_limit.yaml
│       │   ├── M-406_memory_limit_test.yaml
│       │   ├── M-407_cpu_limit.yaml
│       │   ├── M-407_cpu_limit_test.yaml
│       │   ├── M-408_sudo_container_entrypoint.yaml
│       │   ├── M-408_sudo_container_entrypoint_test.yaml
│       │   ├── M-409_deprecated_image_registry.yaml
│       │   ├── M-409_deprecated_image_registry_test.yaml
│       │   ├── M-410_resource_using_invalid_restartpolicy.yaml
│       │   ├── M-410_resource_using_invalid_restartpolicy_test.yaml
│       │   ├── M-411_role_binding_referencing_anonymous_or_unauthenticated.yaml
│       │   └── M-411_role_binding_referencing_anonymous_or_unauthenticated_test.yaml
│       ├── mitre/
│       │   ├── M-200_allowed_registries.yml
│       │   ├── M-200_allowed_registries_test.yml
│       │   ├── M-201_app_credentials.yml
│       │   ├── M-201_app_credentials_test.yml
│       │   ├── M-202_auto_mount_service_account_token.yml
│       │   ├── M-202_auto_mount_service_account_token_test.yml
│       │   ├── M-203_ssh_server.yml
│       │   └── M-203_ssh_server_test.yml
│       ├── nsa/
│       │   ├── M-300_read_only_root_filesystem.yml
│       │   └── M-300_read_only_root_filesystem_test.yml
│       └── pss/
│           ├── baseline/
│           │   ├── M-100_host_process.yml
│           │   ├── M-100_host_process_test.yml
│           │   ├── M-101_host_namespaces.yml
│           │   ├── M-101_host_namespaces_test.yml
│           │   ├── M-102_privileged_containers.yml
│           │   ├── M-102_privileged_containers_test.yml
│           │   ├── M-103_capabilities_baseline.yml
│           │   ├── M-103_capabilities_baseline_test.yml
│           │   ├── M-104_host_path_volumes.yml
│           │   ├── M-104_host_path_volumes_test.yml
│           │   ├── M-105_host_ports.yml
│           │   ├── M-105_host_ports_test.yml
│           │   ├── M-106_apparmor.yml
│           │   ├── M-106_apparmor_test.yml
│           │   ├── M-107_selinux.yml
│           │   ├── M-107_selinux_test.yml
│           │   ├── M-108_proc_mount.yml
│           │   ├── M-108_proc_mount_test.yml
│           │   ├── M-109_seccomp_baseline.yml
│           │   ├── M-109_seccomp_baseline_test.yml
│           │   ├── M-110_sysctls.yml
│           │   └── M-110_sysctls_test.yml
│           └── restricted/
│               ├── M-111_volume_types.yml
│               ├── M-111_volume_types_test.yml
│               ├── M-112_privilege_escalation.yml
│               ├── M-112_privilege_escalation_test.yml
│               ├── M-113_run_as_non_root.yml
│               ├── M-113_run_as_non_root_test.yml
│               ├── M-114_run_as_user.yml
│               ├── M-114_run_as_user_test.yml
│               ├── M-115_seccomp_restricted.yml
│               ├── M-115_seccomp_restricted_test.yml
│               ├── M-116_capabilities_restricted.yml
│               └── M-116_capabilities_restricted_test.yml
├── main.go
├── pkg/
│   ├── cmd/
│   │   └── scan.go
│   ├── loader/
│   │   ├── builtin.go
│   │   ├── builtin_test.go
│   │   ├── loader.go
│   │   ├── loader_test.go
│   │   └── testdata/
│   │       ├── checks/
│   │       │   ├── svc_lb.json
│   │       │   └── workloads/
│   │       │       ├── replicas.yaml
│   │       │       ├── replicas_test.yaml
│   │       │       └── unsupported.txt
│   │       └── invalid/
│   │           └── invalid.yml
│   ├── printers/
│   │   ├── interface.go
│   │   ├── json.go
│   │   ├── md.go
│   │   ├── table.go
│   │   └── yaml.go
│   ├── types/
│   │   ├── check.go
│   │   ├── check_test.go
│   │   ├── report.go
│   │   ├── report_test.go
│   │   ├── severity.go
│   │   ├── severity_test.go
│   │   ├── status.go
│   │   └── status_test.go
│   ├── validator/
│   │   ├── activation.go
│   │   ├── compiler.go
│   │   ├── compiler_test.go
│   │   ├── interface.go
│   │   ├── podspec.go
│   │   ├── podspec_test.go
│   │   └── validator.go
│   └── version/
│       ├── version.go
│       └── version_test.go
└── test/
    └── builtins_test.go

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

================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly
  - package-ecosystem: gomod
    directory: /
    schedule:
      interval: weekly


================================================
FILE: .github/workflows/release.yml
================================================
name: release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write
  packages: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: fetch tags
        run: git fetch --force --tags

      - name: setup go
        uses: actions/setup-go@v6
        with:
          go-version-file: 'go.mod'
          cache: true

      - name: release
        id: goreleaser
        uses: goreleaser/goreleaser-action@v7
        with:
          distribution: goreleaser
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: krew
        uses: rajatjindal/krew-release-bot@v0.0.50

      - name: setup qemu
        uses: docker/setup-qemu-action@v3

      - name: setup docker buildx
        uses: docker/setup-buildx-action@v3
        
      - name: login
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=semver,prefix=v,pattern={{version}}
            type=semver,prefix=v,pattern={{major}}.{{minor}}

      - name: create dockerfile.cross
        run: |
          sed -e '1 s/\(^FROM\)/FROM --platform=\$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
          cat Dockerfile.cross

      - name: build and push
        uses: docker/build-push-action@v6
        with:
          build-args: |
            VERSION=${{ fromJSON(steps.goreleaser.outputs.metadata).version }}
            COMMIT=${{ fromJSON(steps.goreleaser.outputs.metadata).commit }}
            DATE=${{ fromJSON(steps.goreleaser.outputs.metadata).date }}
          context: .
          platforms: linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
          file: Dockerfile.cross
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}


================================================
FILE: .github/workflows/test.yml
================================================
name: test
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v6

      - name: setup go
        uses: actions/setup-go@v6
        with:
          go-version-file: 'go.mod'
          cache: true

      - name: test
        run: make test

      - name: build
        run: make build

      - name: check license headers
        run: make checklicense


================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

.idea

dist/


================================================
FILE: .goreleaser.yaml
================================================
version: 2
before:
  hooks:
    - go mod tidy
builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
      - windows
      - darwin
    ldflags:
      - >-
          -s -w
          -X github.com/undistro/marvin/pkg/version.version={{.Version}}
          -X github.com/undistro/marvin/pkg/version.commit={{.Commit}} 
          -X github.com/undistro/marvin/pkg/version.date={{.Date}} 

archives:
  - formats: [tar.gz]
    name_template: >-
      {{ .ProjectName }}_
      {{- title .Os }}_
      {{- if eq .Arch "amd64" }}x86_64
      {{- else if eq .Arch "386" }}i386
      {{- else }}{{ .Arch }}{{ end }}
      {{- if .Arm }}v{{ .Arm }}{{ end }}
    format_overrides:
    - goos: windows
      formats: [zip]
checksum:
  name_template: 'checksums.txt'
snapshot:
  version_template: "{{ incpatch .Version }}-next"
changelog:
  sort: asc
  filters:
    exclude:
      - '^docs:'
      - '^test:'
release:
  prerelease: auto


================================================
FILE: .krew.yaml
================================================
apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
  name: marvin
spec:
  homepage: https://github.com/undistro/marvin
  shortDescription: Scan clusters with your own checks written in CEL.
  description: |
    Marvin scans a Kubernetes cluster by performing CEL expressions 
    to report potential issues, misconfigurations and vulnerabilities.
    
    Marvin allows you to write your own checks by using CEL expressions.
  version: {{ .TagName }}
  platforms:
  - selector:
      matchLabels:
        os: linux
        arch: amd64
    {{addURIAndSha "https://github.com/undistro/marvin/releases/download/{{ .TagName }}/marvin_Linux_x86_64.tar.gz" .TagName }}
    bin: marvin
  - selector:
      matchLabels:
        os: linux
        arch: arm64
    {{addURIAndSha "https://github.com/undistro/marvin/releases/download/{{ .TagName }}/marvin_Linux_arm64.tar.gz" .TagName }}
    bin: marvin
  - selector:
      matchLabels:
        os: darwin
        arch: amd64
    {{addURIAndSha "https://github.com/undistro/marvin/releases/download/{{ .TagName }}/marvin_Darwin_x86_64.tar.gz" .TagName }}
    bin: marvin
  - selector:
      matchLabels:
        os: darwin
        arch: arm64
    {{addURIAndSha "https://github.com/undistro/marvin/releases/download/{{ .TagName }}/marvin_Darwin_arm64.tar.gz" .TagName }}
    bin: marvin


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
undistro@getup.io.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Marvin

:+1::tada: Thanks for taking the time to contribute! :tada::+1:

The following is a set of guidelines for contributing to Marvin, 
which are hosted in the [Undistro Organization](https://github.com/undistro) on GitHub. 

## How Can I Contribute?

- **Giving us a star.** It may not seem like much, but it really makes a
  difference. This is something that everyone can do to help out Marvin.
  GitHub stars help the project gain visibility and stand out.

- **Reviewing the documentation.** 
  Most documentation just needs a review for proper spelling and grammar. 
  If you think a document can be improved in any way, 
  feel free to open a Pull Request with your suggestions.

- **Reporting bugs.** We use GitHub issues to track public bugs. 
  Report a bug by [opening a new issue](https://github.com/undistro/marvin/issues/new/choose).
  
- **Pull Request.** Unless you are fixing a known bug, we **strongly** 
  recommend discussing it with the core team via a GitHub issue before 
  getting started to ensure your work is consistent with Marvin's roadmap and architecture.



================================================
FILE: Dockerfile
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

FROM golang:1.25.4-alpine AS builder
ARG TARGETOS
ARG TARGETARCH
ARG VERSION
ARG COMMIT
ARG DATE

WORKDIR /workspace
COPY go.mod go.mod
COPY go.sum go.sum
RUN go mod download

COPY main.go main.go
COPY cmd/ cmd/
COPY internal/ internal/
COPY pkg/ pkg/

RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build \
    -ldflags="-s -w -X github.com/undistro/marvin/pkg/version.version=${VERSION:-docker} \
    -X github.com/undistro/marvin/pkg/version.commit=${COMMIT} \
    -X github.com/undistro/marvin/pkg/version.date=${DATE}" -a -o marvin main.go

FROM alpine:3.22
RUN apk update && apk upgrade && rm -rf /var/cache/apk
RUN addgroup -g 8494 -S nonroot && adduser -u 8494 -D -S nonroot -G nonroot
USER 8494:8494

WORKDIR /
COPY --from=builder /workspace/marvin .

ENTRYPOINT ["/marvin"]


================================================
FILE: LICENSE
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: MAINTAINERS.md
================================================
# Maintainers

Maintainers are approvers who have shown good technical judgement in guiding feature design & development, have 
displayed overall knowledge of the project and features in the project, and are nurturing and receptive to everyone in 
the community.

The following table lists the Marvin project core maintainers:

| Name                                                              | GitHub ID                                  | Affiliation                |
|-------------------------------------------------------------------|--------------------------------------------|----------------------------|
| [Matheus Moraes](https://www.linkedin.com/in/matheusfm/)          | [@matheusfm](https://github.com/matheusfm) | [Getup](https://getup.io/) |
| [Kevin Conner](https://www.linkedin.com/in/kevin-conner-26b5554/) | [@knrc](https://github.com/knrc)           | [Getup](https://getup.io/) |


================================================
FILE: Makefile
================================================
# Image URL to use all building/pushing image targets
TAG ?= latest
IMG ?= ghcr.io/undistro/marvin:${TAG}

# Setting SHELL to bash allows bash commands to be executed by recipes.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec

.PHONY: all
all: build

##@ General

.PHONY: help
help: ## Display this help.
	@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n  make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf "  \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

##@ Development

.PHONY: fmt
fmt: ## Run go fmt against code.
	go fmt ./...

.PHONY: vet
vet: ## Run go vet against code.
	go vet ./...

.PHONY: test
test: fmt vet ## Run tests.
	go test ./... -coverprofile cover.out

.PHONY: addlicense
addlicense: ## Add copyright license headers in source code files.
	@test -s $(LOCALBIN)/addlicense || GOBIN=$(LOCALBIN) go install github.com/google/addlicense@latest
	$(LOCALBIN)/addlicense -c "Undistro Authors" -l "apache" -ignore ".github/**" -ignore ".idea/**" -ignore "dist/**" -ignore ".goreleaser.yaml" -ignore ".krew.yaml" .

.PHONY: checklicense
checklicense: ## Check copyright license headers in source code files.
	@test -s $(LOCALBIN)/addlicense || GOBIN=$(LOCALBIN) go install github.com/google/addlicense@latest
	$(LOCALBIN)/addlicense -c "Undistro Authors" -l "apache" -ignore ".github/**" -ignore ".idea/**" -ignore "dist/**" -ignore ".goreleaser.yaml" -ignore ".krew.yaml" -check .

##@ Build

.PHONY: build
build: fmt vet ## Build marvin binary.
	go build -ldflags="-s -w -X github.com/undistro/marvin/pkg/version.version=${TAG}" -o bin/marvin main.go

.PHONY: run
run: fmt vet ## Run marvin from your host.
	go run ./main.go

PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
.PHONY: docker-buildx
docker-buildx: test ## Build and push docker image for cross-platform support.
	sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
	- docker buildx create --name cross-builder
	docker buildx use cross-builder
	- docker buildx build --push --platform=$(PLATFORMS) --build-arg VERSION=${TAG} --tag ${IMG} -f Dockerfile.cross .
	- docker buildx rm cross-builder
	rm Dockerfile.cross

.PHONY: docker-build
docker-build: test ## Build docker image.
	docker build --build-arg VERSION=${TAG} -t ${IMG} .

.PHONY: docker-push
docker-push: ## Push docker image.
	docker push ${IMG}

## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
	mkdir -p $(LOCALBIN)


================================================
FILE: README.md
================================================
<div align="center">

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="assets/banner-dark.png">
  <img alt="Marvin logo" src="assets/banner-light.png">
</picture>

[![Go Reference](https://pkg.go.dev/badge/github.com/undistro/marvin.svg)](https://pkg.go.dev/github.com/undistro/marvin)
[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/marvin)](https://artifacthub.io/packages/krew/krew-index/marvin)
[![Test](https://github.com/undistro/marvin/actions/workflows/test.yml/badge.svg?branch=main&event=push)](https://github.com/undistro/marvin/actions/workflows/test.yml)
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/undistro/marvin?sort=semver&color=brightgreen)
![GitHub](https://img.shields.io/github/license/undistro/marvin?color=brightgreen)
[![Go Report Card](https://goreportcard.com/badge/github.com/undistro/marvin)](https://goreportcard.com/report/github.com/undistro/marvin)
![GitHub all releases](https://img.shields.io/github/downloads/undistro/marvin/total)

</div>

Marvin is a CLI tool designed to help Kubernetes cluster administrators 
ensure the security and reliability of their environments. 

Using a comprehensive set of [CEL (Common Expression Language)](https://github.com/google/cel-spec) expressions, 
Marvin performs extensive checks on cluster resources, 
identifying potential issues, misconfigurations, and vulnerabilities that could pose a risk to the system. 
It helps ensure that your Kubernetes clusters are always in compliance with best practices and industry standards.

Marvin is also used as a plugin in [Zora](https://zora-docs.undistro.io/latest/).

<!-- TOC -->
* [Installation](#installation)
  * [Manually](#manually)
  * [Install via script](#install-via-script)
  * [Install via Krew](#install-via-krew)
  * [Install from source](#install-from-source)
* [Usage](#usage)
  * [Built-in checks](#built-in-checks)
  * [Custom checks](#custom-checks)
  * [Skipping resources](#skipping-resources)
  * [RBAC](#rbac)
* [Contributing](#contributing)
* [License](#license)
<!-- TOC -->

_Please [star :star:](https://github.com/undistro/marvin/stargazers) the repo if you want us to continue developing and improving Marvin!_ :grin:

# Installation

The pre-compiled binaries are available in [GitHub releases page](https://github.com/undistro/marvin/releases) 
and can be installed manually, via script or as a `kubectl` plugin with [Krew](https://krew.sigs.k8s.io).

## Manually

1. Download the file for your system/architecture from the [GitHub releases page](https://github.com/undistro/marvin/releases)
2. Unpack the downloaded archive (e.g `tar -xzf marvin_Linux_x86_64.tar.gz`)
3. Make sure the binary has execution bit turned on (`chmod +x ./marvin`)
4. Move the binary somewhere in your `$PATH` (e.g `sudo mv ./marvin /usr/local/bin/`)

## Install via script

The process above can be automated by the following script:

```shell
curl -sSfL https://raw.githubusercontent.com/undistro/marvin/main/install.sh | sh -s -- -b $HOME/.local/bin
```

## Install via [Krew](https://krew.sigs.k8s.io)

You can install Marvin as a `kubectl` plugin via [Krew](https://krew.sigs.k8s.io):
```shell
kubectl krew install marvin
```

Then you can use Marvin with `kubectl` prefix:
```shell
kubectl marvin version
```

## Install from source

```shell
go install github.com/undistro/marvin@latest
```

# Usage

## Built-in checks

Scan the current-context Kubernetes cluster performing the [built-in checks](internal/builtins):
```shell
marvin scan
```
```
SEVERITY   ID      CHECK                                                   STATUS   FAILED   PASSED   SKIPPED 
High       M-101   Host namespaces                                         Failed   8        25       0         
High       M-104   HostPath volume                                         Failed   8        25       0         
High       M-201   Application credentials stored in configuration files   Failed   2        45       0         
High       M-102   Privileged container                                    Failed   2        31       0         
High       M-103   Insecure capabilities                                   Failed   2        31       0         
High       M-100   Privileged access to the Windows node                   Passed   0        33       0         
High       M-105   Not allowed hostPort                                    Passed   0        33       0         
Medium     M-113   Container could be running as root user                 Failed   33       0        0         
Medium     M-407   CPU not limited                                         Failed   31       2        0         
Medium     M-406   Memory not limited                                      Failed   27       6        0         
Medium     M-404   Memory requests not specified                           Failed   26       7        0         
Medium     M-402   Readiness and startup probe not configured              Failed   25       8        0         
Medium     M-403   Liveness probe not configured                           Failed   25       8        0         
Medium     M-405   CPU requests not specified                              Failed   23       10       0         
Medium     M-106   Forbidden AppArmor profile                              Passed   0        33       0         
Medium     M-107   Forbidden SELinux options                               Passed   0        33       0         
Medium     M-108   Forbidden proc mount type                               Passed   0        33       0         
Medium     M-109   Forbidden seccomp profile                               Passed   0        33       0         
Medium     M-110   Unsafe sysctls                                          Passed   0        33       0         
Medium     M-112   Allowed privilege escalation                            Passed   0        33       0         
Medium     M-114   Container running as root UID                           Passed   0        33       0         
Medium     M-200   Image registry not allowed                              Passed   0        33       0         
Medium     M-400   Image tagged latest                                     Passed   0        33       0         
Medium     M-408   Sudo in container entrypoint                            Passed   0        33       0         
Medium     M-409   Deprecated image registry                               Passed   0        33       0         
Medium     M-500   Workload in default namespace                           Passed   0        33       0         
Medium     M-410   Not allowed restartPolicy                               Passed   0        18       0         
Low        M-116   Not allowed added/dropped capabilities                  Failed   33       0        0         
Low        M-202   Automounted service account token                       Failed   33       0        0         
Low        M-115   Not allowed seccomp profile                             Failed   29       4        0         
Low        M-300   Root filesystem write allowed                           Failed   29       4        0         
Low        M-111   Not allowed volume type                                 Failed   8        25       0         
Low        M-203   SSH server running inside container                     Passed   0        39       0         
Low        M-401   Unmanaged Pod                                           Passed   0        15       0         
```

The default output format is `table` which represents a summary of checks result. 
You can provide `json` or `yaml` in the `-o/--output` flag to get more details.

Run `marvin scan --help` to see all available options.

## Custom checks

Marvin allows you to write your own checks by using [CEL expressions](https://github.com/google/cel-spec) in a YAML file like the example below.

```yaml
id: CUSTOM-001
severity: Medium
message: "Replicas limit"
match:
  resources:
    - group: apps
      version: v1
      resource: deployments
validations:
  - expression: >
      object.spec.replicas <= 5
    message: "Deployment with more than 5 replicas"
```

If an expression evaluates to `false`, the check fails.

This is how built-in Marvin checks are defined as well.
You can see all the built-in checks in the [`internal/builtins` folder](internal/builtins) for examples.

If you want to quickly test CEL expressions from your browser, check out the [CEL Playground](https://playcel.undistro.io/).

Then provide the directory path with your custom check files in the `-f/--checks` flag:

```shell
marvin scan --disable-builtin --checks ./examples/
```
```
SEVERITY   ID           CHECK            STATUS   FAILED   PASSED   SKIPPED 
Medium     CUSTOM-001   Replicas limit   Passed   0        2        0         
```

The flag `--disable-builtin` disables the built-in Marvin checks.

If the check matches a PodSpec (`Pod`, `ReplicationController`, `ReplicaSet`, `Deployment`, `StatefulSet`, `DaemonSet`, `Job` or `CronJob`)
the `podSpec` and `allContainers` inputs are available for expressions.

The `allContainers` input is a list of all containers including `initContainers` and `ephemeralContainers`.

## Skipping resources

You can use annotations to skip certain checks for specific resources in your cluster.
By adding the `marvin.undistro.io/skip` annotation to a resource, 
you can specify a comma-separated list of check IDs to skip.

Example:
```shell
kubectl annotate deployment nginx marvin.undistro.io/skip='M-202, M-111'
```

By default, Marvin will respect the `marvin.undistro.io/skip` annotation when performing checks. 
However, you can disable this behavior by using the `--disable-annotation-skip` flag.
This flag will cause Marvin to perform all checks on all resources.

If you prefer to use a different annotation to skip checks, 
you can use the `--skip-annotation` flag to specify the annotation name. 
Example: `--skip-annotation='my-company.com/skip-checks'`

## RBAC

Currently, the built-in checks look for the below resources
and Marvin needs view (`get` and `list`) permission to verify them.

- `v1/pods`
- `v1/configmaps`
- `v1/services`
- `apps/v1/deployments`
- `apps/v1/daemonsets`
- `apps/v1/statefulsets`
- `apps/v1/replicasets`
- `batch/v1/cronjobs`
- `batch/v1/jobs`

<details>

<summary> Here is a sample `ClusterRole` for Marvin: </summary>

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: marvin
rules:
  - apiGroups: [ "" ]
    resources:
      - configmaps
      - pods
      - services
    verbs: [ "get", "list" ]
  - apiGroups: [ "apps" ]
    resources:
      - daemonsets
      - deployments
      - statefulsets
      - replicasets
    verbs: [ "get", "list" ]
  - apiGroups: [ batch ]
    resources:
      - jobs
      - cronjobs
    verbs: [ "get", "list" ]
```

</details>

> **Note**
> You can write a custom check to look at any resource. 
> But Marvin needs view permission. 
> Remember to update RBAC for new resources you want to check.

# Contributing

We appreciate your contribution.
Please refer to our [contributing guideline](https://github.com/undistro/marvin/blob/main/CONTRIBUTING.md) for further information.
This project adheres to the Contributor Covenant [code of conduct](https://github.com/undistro/marvin/blob/main/CODE_OF_CONDUCT.md).

# License

Marvin is available under the Apache 2.0 license. See the [LICENSE](LICENSE) file for more info.


================================================
FILE: checks.md
================================================
# Checks Overview  

In the table below, you can view all checks present on Marvin. Click on the #ID column item for more details about each check.


| Framework        | #ID                                                                                                  | Severity | Message                                                          |
|------------------|------------------------------------------------------------------------------------------------------|----------|------------------------------------------------------------------|
| CIS Benchmarks   | [M-500](/internal/builtins/cis/M-500_default_namespace.yaml)                                         | Medium   | Workloads in default namespace                                   |
| General          | [M-400](/internal/builtins/general/M-400_image_tag_latest.yaml)                                      | Medium   | Image tagged latest                                              |
|                  | [M-401](/internal/builtins/general/M-401_unmanaged_pod.yaml)                                         | Low      | Unmanaged Pod                                                    |
|                  | [M-402](/internal/builtins/general/M-402_readiness_probe.yaml)                                       | Medium   | Readiness and startup probe not configured                       |
|                  | [M-403](/internal/builtins/general/M-403_liveness_probe.yaml)                                        | Medium   | Liveness probe not configured                                    |
|                  | [M-404](/internal/builtins/general/M-404_memory_requests.yaml)                                       | Medium   | Memory requests not specified                                    |
|                  | [M-405](/internal/builtins/general/M-405_cpu_requests.yaml)                                          | Medium   | CPU requests not specified                                       |
|                  | [M-406](/internal/builtins/general/M-406_memory_limit.yaml)                                          | Medium   | Memory not limited                                               |
|                  | [M-407](/internal/builtins/general/M-407_cpu_limit.yaml)                                             | Medium   | CPU not limited                                                  |
|                  | [M-408](/internal/builtins/general/M-408_sudo_container_entrypoint.yaml)                             | Medium   | Sudo in container entrypoint                                     |
|                  | [M-409](/internal/builtins/general/M-409_deprecated_image_registry.yaml)                             | Medium   | Deprecated image registry                                        |
|                  | [M-410](/internal/builtins/general/M-410_resource_using_invalid_restartpolicy.yaml)                  | Medium   | Resource is using an invalid restartPolicy                       |
|                  | [M-411](/internal/builtins/general/M-411_role_binding_referencing_anonymous_or_unauthanticated.yaml) | Medium   | Role Binding referencing anonymous user or unauthenticated group |
| NSA-CISA         | [M-300](/internal/builtins/nsa/M-300_read_only_root_filesystem.yml)                                  | Low      | Root filesystem write allowed                                    |
| MITRE ATT&CK     | [M-200](/internal/builtins/mitre/M-200_allowed_registries.yml)                                       | Medium   | Image registry not allowed                                       |
|                  | [M-201](/internal/builtins/mitre/M-201_app_credentials.yml)                                          | High     | Application credentials stored in configuration files            |
|                  | [M-202](/internal/builtins/mitre/M-202_auto_mount_service_account.yml)                               | Low      | Automounted service account token                                |
|                  | [M-203](/internal/builtins/mitre/M-203_ssh.yml)                                                      | Low      | SSH server running inside container                              |
| PSS - Baseline   | [M-100](/internal/builtins/pss/baseline/M-100_host_process.yml)                                      | High     | Privileged access to the Windows node                            |
|                  | [M-101](/internal/builtins/pss/baseline/M-101_host_namespaces.yml)                                   | High     | Host namespaces                                                  |
|                  | [M-102](/internal/builtins/pss/baseline/M-102_privileged_containers.yml)                             | High     | Privileged container                                             |
|                  | [M-103](/internal/builtins/pss/baseline/M-103_capabilities.yml)                                      | High     | Insecure capabilities                                            |
|                  | [M-104](/internal/builtins/pss/baseline/M-104_host_path_volumes.yml)                                 | High     | HostPath volume                                                  |
|                  | [M-105](/internal/builtins/pss/baseline/M-105_host_ports.yml)                                        | High     | Not allowed hostPort                                             |
|                  | [M-106](/internal/builtins/pss/baseline/M-106_apparmor.yml)                                          | Medium   | Forbidden AppArmor profile                                       |
|                  | [M-107](/internal/builtins/pss/baseline/M-107_selinux.yml)                                           | Medium   | Forbidden SELinux options                                        |
|                  | [M-108](/internal/builtins/pss/baseline/M-108_proc_mount.yml)                                        | Medium   | Forbidden proc mount type                                        |
|                  | [M-109](/internal/builtins/pss/baseline/M-109_seccomp.yml)                                           | Medium   | Forbidden seccomp profile                                        |
|                  | [M-110](/internal/builtins/pss/baseline/M-110_sysctls.yml)                                           | Medium   | Unsafe sysctls                                                   |
| PSS - Restricted | [M-111](/internal/builtins/pss/restricted/M-111_volume_types.yml)                                    | Low      | Not allowed volume type                                          |
|                  | [M-112](/internal/builtins/pss/restricted/M-112_privilege_escalation.yml)                            | Medium   | Allowed privilege escalation                                     |
|                  | [M-113](/internal/builtins/pss/restricted/M-113_run_as_non_root.yml)                                 | Medium   | Container could be running as root user                          |
|                  | [M-114](/internal/builtins/pss/restricted/M-114_run_as_user.yml)                                     | Medium   | Container running as root UID                                    |
|                  | [M-115](/internal/builtins/pss/restricted/M-115_seccomp.yml)                                         | Low      | Not allowed seccomp profile                                      |
|                  | [M-116](/internal/builtins/pss/restricted/M-116_capabilities.yml)                                    | Low      | Not allowed added/dropped capabilities                           |


================================================
FILE: cmd/root.go
================================================
// Copyright 2023 Undistro Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"context"
	"flag"
	"os"
	"path/filepath"
	"strings"

	"github.com/fatih/color"
	"github.com/go-logr/logr"
	"github.com/spf13/cobra"
	"k8s.io/klog/v2"
	"k8s.io/klog/v2/klogr"
)

var noColor bool

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "marvin",
	Short: "A Kubernetes cluster scanner",
}

func Execute() {
	err := rootCmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}

func isKubectlPlugin() bool {
	return strings.HasPrefix(filepath.Base(os.Args[0]), "kubectl-")
}

func execName() string {
	n := "marvin"
	if isKubectlPlugin() {
		return "kubectl " + n
	}
	return n
}

func init() {
	cobra.OnInitialize(initNoColor)
	if isKubectlPlugin() {
		usageTpl := strings.NewReplacer("{{.UseLine}}", "kubectl {{.UseLine}}",
			"{{.CommandPath}}", "kubectl {{.CommandPath}}").Replace(rootCmd.UsageTemplate())
		rootCmd.SetUsageTemplate(usageTpl)
	}
	rootCmd.PersistentFlags().BoolVar(&noColor, "no-color", false, "Disable color output")
	var allFlags flag.FlagSet
	klog.InitFlags(&allFlags)
	allFlags.VisitAll(func(f *flag.Flag) {
		if f.Name == "v" {
			rootCmd.PersistentFlags().AddGoFlag(f)
		}
	})
	rootCmd.SetContext(logr.NewContext(context.Background(), klogr.New()))
}

func initNoColor() {
	color.NoColor = noColor
}


================================================
FILE: cmd/scan.go
================================================
// Copyright 2023 Undistro Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"

	"github.com/undistro/marvin/pkg/cmd"
)

var (
	scanOptions = cmd.NewScanOptions()

	// scanCmd represents the scan command
	scanCmd = &cobra.Command{
		Use:   "scan [flags]",
		Short: "Scan a Kubernetes cluster",
		Example: fmt.Sprintf(`  # Scan the current cluster
  %[1]s scan

  # Scan the 'foo' namespace of the current cluster
  %[1]s scan -n foo

  # Scan the current cluster providing custom checks
  %[1]s scan --checks ./examples/

  # Scan the current cluster providing custom checks and disabling the built-in checks
  %[1]s scan --disable-builtin --checks ./examples/

  # Scan a specific cluster using a kubeconfig file
  %[1]s scan --kubeconfig /path/to/kubeconfig.yml

  # Scan the current cluster, but do not fail even if there are errors in the report
  %[1]s scan --no-fail

  # Scan the current cluster and generate output in JSON format
  %[1]s scan -o json`, execName()),
		RunE: func(c *cobra.Command, args []string) error {
			if err := scanOptions.Init(c.Context()); err != nil {
				return err
			}
			hasError, err := scanOptions.Run()
			if err != nil {
				return err
			}
			if hasError && !*scanOptions.NoFail {
				os.Exit(2)
			}
			return nil
		},
	}
)

func init() {
	rootCmd.AddCommand(scanCmd)
	scanOptions.AddFlags(scanCmd.Flags())
}


================================================
FILE: cmd/version.go
================================================
// Copyright 2023 Undistro Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"encoding/json"
	"fmt"

	"github.com/spf13/cobra"
	"sigs.k8s.io/yaml"

	"github.com/undistro/marvin/pkg/version"
)

var (
	versionOutput string
	// versionCmd represents the version command
	versionCmd = &cobra.Command{
		Use:   "version",
		Short: "Show the version of Marvin",
		RunE: func(c *cobra.Command, args []string) error {
			v := version.Get()
			var s string
			switch versionOutput {
			case "json":
				b, err := json.MarshalIndent(&v, "", "    ")
				if err != nil {
					return err
				}
				s = string(b)
			case "yaml":
				b, err := yaml.Marshal(&v)
				if err != nil {
					return err
				}
				s = string(b)
			default:
				s = v.String()
			}
			fmt.Println(s)
			return nil
		},
	}
)

func init() {
	rootCmd.AddCommand(versionCmd)
	versionCmd.Flags().StringVarP(&versionOutput, "output", "o", "", `Output format. One of: ("json", "yaml")`)
}


================================================
FILE: examples/labels.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: CUSTOM-002
severity: Low
message: "Required labels"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
params:
  requiredLabels:
    - app
validations:
  - expression: >
      has(object.metadata.labels) &&
      params.requiredLabels.all(req, 
        req in object.metadata.labels
      )
    message: "Pod without required labels"


================================================
FILE: examples/replicas.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: CUSTOM-001
severity: Medium
message: "Replicas limit"
match:
  resources:
    - group: apps
      version: v1
      resource: deployments
validations:
  - expression: >
      object.spec.replicas <= 5
    message: "Deployment with more than 5 replicas"


================================================
FILE: go.mod
================================================
module github.com/undistro/marvin

go 1.25.4

require (
	github.com/Masterminds/semver/v3 v3.4.0
	github.com/fatih/color v1.18.0
	github.com/go-logr/logr v1.4.3
	github.com/google/cel-go v0.26.0
	github.com/olekukonko/tablewriter v0.0.5
	github.com/spf13/cobra v1.10.2
	github.com/spf13/pflag v1.0.10
	github.com/stretchr/testify v1.11.1
	k8s.io/api v0.34.2
	k8s.io/apimachinery v0.34.2
	k8s.io/apiserver v0.34.2
	k8s.io/cli-runtime v0.34.2
	k8s.io/client-go v0.34.2
	k8s.io/klog/v2 v2.130.1
	k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
	sigs.k8s.io/yaml v1.6.0
)

require (
	cel.dev/expr v0.24.0 // indirect
	github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
	github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
	github.com/beorn7/perks v1.0.1 // indirect
	github.com/blang/semver/v4 v4.0.0 // indirect
	github.com/cespare/xxhash/v2 v2.3.0 // indirect
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/emicklei/go-restful/v3 v3.12.2 // indirect
	github.com/fxamacker/cbor/v2 v2.9.0 // indirect
	github.com/go-errors/errors v1.4.2 // indirect
	github.com/go-openapi/jsonpointer v0.21.0 // indirect
	github.com/go-openapi/jsonreference v0.20.2 // indirect
	github.com/go-openapi/swag v0.23.0 // indirect
	github.com/gogo/protobuf v1.3.2 // indirect
	github.com/google/btree v1.1.3 // indirect
	github.com/google/gnostic-models v0.7.0 // indirect
	github.com/google/uuid v1.6.0 // indirect
	github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
	github.com/inconshreveable/mousetrap v1.1.0 // indirect
	github.com/josharian/intern v1.0.0 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
	github.com/mailru/easyjson v0.7.7 // indirect
	github.com/mattn/go-colorable v0.1.13 // indirect
	github.com/mattn/go-isatty v0.0.20 // indirect
	github.com/mattn/go-runewidth v0.0.16 // indirect
	github.com/moby/term v0.5.0 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
	github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
	github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
	github.com/pkg/errors v0.9.1 // indirect
	github.com/pmezard/go-difflib v1.0.0 // indirect
	github.com/prometheus/client_golang v1.22.0 // indirect
	github.com/prometheus/client_model v0.6.1 // indirect
	github.com/prometheus/common v0.62.0 // indirect
	github.com/prometheus/procfs v0.15.1 // indirect
	github.com/rivo/uniseg v0.2.0 // indirect
	github.com/stoewer/go-strcase v1.3.0 // indirect
	github.com/x448/float16 v0.8.4 // indirect
	github.com/xlab/treeprint v1.2.0 // indirect
	go.opentelemetry.io/otel v1.35.0 // indirect
	go.opentelemetry.io/otel/trace v1.35.0 // indirect
	go.yaml.in/yaml/v2 v2.4.2 // indirect
	go.yaml.in/yaml/v3 v3.0.4 // indirect
	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
	golang.org/x/net v0.38.0 // indirect
	golang.org/x/oauth2 v0.27.0 // indirect
	golang.org/x/sync v0.12.0 // indirect
	golang.org/x/sys v0.31.0 // indirect
	golang.org/x/term v0.30.0 // indirect
	golang.org/x/text v0.23.0 // indirect
	golang.org/x/time v0.9.0 // indirect
	google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
	google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
	google.golang.org/protobuf v1.36.5 // indirect
	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
	gopkg.in/inf.v0 v0.9.1 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
	k8s.io/component-base v0.34.2 // indirect
	k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
	sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
	sigs.k8s.io/kustomize/api v0.20.1 // indirect
	sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
	sigs.k8s.io/randfill v1.0.0 // indirect
	sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
)


================================================
FILE: go.sum
================================================
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=
github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4=
k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/apiserver v0.34.2 h1:2/yu8suwkmES7IzwlehAovo8dDE07cFRC7KMDb1+MAE=
k8s.io/apiserver v0.34.2/go.mod h1:gqJQy2yDOB50R3JUReHSFr+cwJnL8G1dzTA0YLEqAPI=
k8s.io/cli-runtime v0.34.2 h1:cct1GEuWc3IyVT8MSCoIWzRGw9HJ/C5rgP32H60H6aE=
k8s.io/cli-runtime v0.34.2/go.mod h1:X13tsrYexYUCIq8MarCBy8lrm0k0weFPTpcaNo7lms4=
k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M=
k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE=
k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ=
k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=
sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM=
sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78=
sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=


================================================
FILE: install.sh
================================================
#!/bin/sh

set -e
# Code generated by godownloader on 2023-02-28T17:14:26Z. DO NOT EDIT.
#

usage() {
  this=$1
  cat <<EOF
$this: download go binaries for undistro/marvin

Usage: $this [-b] bindir [-d] [tag]
  -b sets bindir or installation directory, Defaults to ./bin
  -d turns on debug logging
   [tag] is a tag from
   https://github.com/undistro/marvin/releases
   If tag is missing, then the latest will be used.

 Generated by godownloader
  https://github.com/goreleaser/godownloader

EOF
  exit 2
}

parse_args() {
  #BINDIR is ./bin unless set be ENV
  # over-ridden by flag below

  BINDIR=${BINDIR:-./bin}
  while getopts "b:dh?x" arg; do
    case "$arg" in
      b) BINDIR="$OPTARG" ;;
      d) log_set_priority 10 ;;
      h | \?) usage "$0" ;;
      x) set -x ;;
    esac
  done
  shift $((OPTIND - 1))
  TAG=$1
}
# this function wraps all the destructive operations
# if a curl|bash cuts off the end of the script due to
# network, either nothing will happen or will syntax error
# out preventing half-done work
execute() {
  tmpdir=$(mktemp -d)
  log_debug "downloading files into ${tmpdir}"
  http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
  http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
  hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
  srcdir="${tmpdir}"
  (cd "${tmpdir}" && untar "${TARBALL}")
  test ! -d "${BINDIR}" && install -d "${BINDIR}"
  for binexe in $BINARIES; do
    if [ "$OS" = "windows" ]; then
      binexe="${binexe}.exe"
    fi
    install "${srcdir}/${binexe}" "${BINDIR}/"
    log_info "installed ${BINDIR}/${binexe}"
  done
  rm -rf "${tmpdir}"
}
get_binaries() {
  case "$PLATFORM" in
    darwin/386) BINARIES="marvin" ;;
    darwin/amd64) BINARIES="marvin" ;;
    linux/386) BINARIES="marvin" ;;
    linux/amd64) BINARIES="marvin" ;;
    windows/386) BINARIES="marvin" ;;
    windows/amd64) BINARIES="marvin" ;;
    *)
      log_crit "platform $PLATFORM is not supported.  Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
      exit 1
      ;;
  esac
}
tag_to_version() {
  if [ -z "${TAG}" ]; then
    log_info "checking GitHub for latest tag"
  else
    log_info "checking GitHub for tag '${TAG}'"
  fi
  REALTAG=$(github_release "$OWNER/$REPO" "${TAG}") && true
  if test -z "$REALTAG"; then
    log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${PREFIX}/releases for details"
    exit 1
  fi
  # if version starts with 'v', remove it
  TAG="$REALTAG"
  VERSION=${TAG#v}
}
adjust_format() {
  # change format (tar.gz or zip) based on OS
  true
}
adjust_os() {
  # adjust archive name based on OS
  case ${OS} in
    386) OS=i386 ;;
    amd64) OS=x86_64 ;;
    darwin) OS=Darwin ;;
    linux) OS=Linux ;;
    windows) OS=Windows ;;
  esac
  true
}
adjust_arch() {
  # adjust archive name based on ARCH
  case ${ARCH} in
    386) ARCH=i386 ;;
    amd64) ARCH=x86_64 ;;
    darwin) ARCH=Darwin ;;
    linux) ARCH=Linux ;;
    windows) ARCH=Windows ;;
  esac
  true
}

cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
  command -v "$1" >/dev/null
}
echoerr() {
  echo "$@" 1>&2
}
log_prefix() {
  echo "$0"
}
_logp=6
log_set_priority() {
  _logp="$1"
}
log_priority() {
  if test -z "$1"; then
    echo "$_logp"
    return
  fi
  [ "$1" -le "$_logp" ]
}
log_tag() {
  case $1 in
    0) echo "emerg" ;;
    1) echo "alert" ;;
    2) echo "crit" ;;
    3) echo "err" ;;
    4) echo "warning" ;;
    5) echo "notice" ;;
    6) echo "info" ;;
    7) echo "debug" ;;
    *) echo "$1" ;;
  esac
}
log_debug() {
  log_priority 7 || return 0
  echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
  log_priority 6 || return 0
  echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
  log_priority 3 || return 0
  echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
  log_priority 2 || return 0
  echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
  os=$(uname -s | tr '[:upper:]' '[:lower:]')
  case "$os" in
    cygwin_nt*) os="windows" ;;
    mingw*) os="windows" ;;
    msys_nt*) os="windows" ;;
  esac
  echo "$os"
}
uname_arch() {
  arch=$(uname -m)
  case $arch in
    x86_64) arch="amd64" ;;
    x86) arch="386" ;;
    i686) arch="386" ;;
    i386) arch="386" ;;
    aarch64) arch="arm64" ;;
    armv5*) arch="armv5" ;;
    armv6*) arch="armv6" ;;
    armv7*) arch="armv7" ;;
  esac
  echo ${arch}
}
uname_os_check() {
  os=$(uname_os)
  case "$os" in
    darwin) return 0 ;;
    dragonfly) return 0 ;;
    freebsd) return 0 ;;
    linux) return 0 ;;
    android) return 0 ;;
    nacl) return 0 ;;
    netbsd) return 0 ;;
    openbsd) return 0 ;;
    plan9) return 0 ;;
    solaris) return 0 ;;
    windows) return 0 ;;
  esac
  log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
  return 1
}
uname_arch_check() {
  arch=$(uname_arch)
  case "$arch" in
    386) return 0 ;;
    amd64) return 0 ;;
    arm64) return 0 ;;
    armv5) return 0 ;;
    armv6) return 0 ;;
    armv7) return 0 ;;
    ppc64) return 0 ;;
    ppc64le) return 0 ;;
    mips) return 0 ;;
    mipsle) return 0 ;;
    mips64) return 0 ;;
    mips64le) return 0 ;;
    s390x) return 0 ;;
    amd64p32) return 0 ;;
  esac
  log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value.  Please file bug report at https://github.com/client9/shlib"
  return 1
}
untar() {
  tarball=$1
  case "${tarball}" in
    *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
    *.tar) tar --no-same-owner -xf "${tarball}" ;;
    *.zip) unzip "${tarball}" ;;
    *)
      log_err "untar unknown archive format for ${tarball}"
      return 1
      ;;
  esac
}
http_download_curl() {
  local_file=$1
  source_url=$2
  header=$3
  if [ -z "$header" ]; then
    code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url")
  else
    code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url")
  fi
  if [ "$code" != "200" ]; then
    log_debug "http_download_curl received HTTP status $code"
    return 1
  fi
  return 0
}
http_download_wget() {
  local_file=$1
  source_url=$2
  header=$3
  if [ -z "$header" ]; then
    wget -q -O "$local_file" "$source_url"
  else
    wget -q --header "$header" -O "$local_file" "$source_url"
  fi
}
http_download() {
  log_debug "http_download $2"
  if is_command curl; then
    http_download_curl "$@"
    return
  elif is_command wget; then
    http_download_wget "$@"
    return
  fi
  log_crit "http_download unable to find wget or curl"
  return 1
}
http_copy() {
  tmp=$(mktemp)
  http_download "${tmp}" "$1" "$2" || return 1
  body=$(cat "$tmp")
  rm -f "${tmp}"
  echo "$body"
}
github_release() {
  owner_repo=$1
  version=$2
  test -z "$version" && version="latest"
  giturl="https://github.com/${owner_repo}/releases/${version}"
  json=$(http_copy "$giturl" "Accept:application/json")
  test -z "$json" && return 1
  version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
  test -z "$version" && return 1
  echo "$version"
}
hash_sha256() {
  TARGET=${1:-/dev/stdin}
  if is_command gsha256sum; then
    hash=$(gsha256sum "$TARGET") || return 1
    echo "$hash" | cut -d ' ' -f 1
  elif is_command sha256sum; then
    hash=$(sha256sum "$TARGET") || return 1
    echo "$hash" | cut -d ' ' -f 1
  elif is_command shasum; then
    hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
    echo "$hash" | cut -d ' ' -f 1
  elif is_command openssl; then
    hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1
    echo "$hash" | cut -d ' ' -f a
  else
    log_crit "hash_sha256 unable to find command to compute sha-256 hash"
    return 1
  fi
}
hash_sha256_verify() {
  TARGET=$1
  checksums=$2
  if [ -z "$checksums" ]; then
    log_err "hash_sha256_verify checksum file not specified in arg2"
    return 1
  fi
  BASENAME=${TARGET##*/}
  want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
  if [ -z "$want" ]; then
    log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
    return 1
  fi
  got=$(hash_sha256 "$TARGET")
  if [ "$want" != "$got" ]; then
    log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
    return 1
  fi
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF

PROJECT_NAME="marvin"
OWNER=undistro
REPO="marvin"
BINARY=marvin
FORMAT=tar.gz
OS=$(uname_os)
ARCH=$(uname_arch)
PREFIX="$OWNER/$REPO"

# use in logging routines
log_prefix() {
	echo "$PREFIX"
}
PLATFORM="${OS}/${ARCH}"
GITHUB_DOWNLOAD=https://github.com/${OWNER}/${REPO}/releases/download

uname_os_check "$OS"
uname_arch_check "$ARCH"

parse_args "$@"

get_binaries

tag_to_version

adjust_format

adjust_os

adjust_arch

log_info "found version: ${VERSION} for ${TAG}/${OS}/${ARCH}"

NAME=${PROJECT_NAME}_${OS}_${ARCH}
TARBALL=${NAME}.${FORMAT}
TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL}
CHECKSUM=checksums.txt
CHECKSUM_URL=${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM}


execute


================================================
FILE: internal/builtins/cis/M-500_workload_in_default_namespace.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


id: M-500
slug: workload-in-default-namespace
severity: Medium
message: "Workload in default namespace"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: object.metadata.?namespace.orValue("default") != "default"


================================================
FILE: internal/builtins/cis/M-500_workload_in_default_namespace_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "Namespace set to default"
  pass: false
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      namespace: default
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "Namespace not specified"
  pass: false
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          volumes: []
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "Namespace specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      namespace: fooserver
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          volumes: []
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

================================================
FILE: internal/builtins/embed.go
================================================
// Copyright 2023 Undistro Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package builtins

import (
	"embed"
)

//go:embed *
var EmbedChecksFS embed.FS


================================================
FILE: internal/builtins/embed_test.go
================================================
// Copyright 2023 Undistro Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package builtins

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestEmbedChecks(t *testing.T) {
	entries, err := EmbedChecksFS.ReadDir(".")
	assert.NoError(t, err)
	assert.Greater(t, len(entries), 0)
}


================================================
FILE: internal/builtins/general/M-400_image_tagged_latest.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-400
slug: image-tagged-latest
severity: Medium
message: "Image tagged latest"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(container,
        container.image.contains(":") && // image digest contains ":"
        [container.image.substring(container.image.lastIndexOf(":")+1)].all(image,
          !image.contains("/") && !(image in ["latest", ""])
        )
      )


================================================
FILE: internal/builtins/general/M-400_image_tagged_latest_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "untagged"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "registry + untagged image"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.com/nginx

- name: "registry + port + untagged image"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.com:10443/nginx

- name: "latest tag"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest

- name: "registry + image tagged latest"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.com/nginx:latest

- name: "registry + port + image tagged latest"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.com:10443/nginx:latest

- name: "all ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx:1
          name: cont1
        - image: nginx:1.25
          name: cont2
        - image: nginx@sha256:593dac25b7733ffb7afe1a72649a43e574778bf025ad60514ef40f6b5d606247
          name: cont3
        - image: registry.com/images/nginx:1
          name: cont4
        - image: registry.com:10443/nginx:1.25
          name: cont5
        - image: registry.com/nginx@sha256:593dac25b7733ffb7afe1a72649a43e574778bf025ad60514ef40f6b5d606247
          name: cont6


================================================
FILE: internal/builtins/general/M-401_unmanaged_pod.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-401
slug: unmanaged-pod
severity: Low
message: "Unmanaged Pod"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
variables:
  - name: owners
    expression: object.metadata.?ownerReferences.orValue([])
validations:
  - expression: >
      variables.owners != null && variables.owners.exists(o, o.?controller.orValue(false) == true)


================================================
FILE: internal/builtins/general/M-401_unmanaged_pod_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-7f7b76bc5b-6vb88
      ownerReferences:
        - apiVersion: apps/v1
          blockOwnerDeletion: true
          controller: true
          kind: ReplicaSet
          name: nginx-7f7b76bc5b
          uid: daf540b6-b932-4b2d-a9b1-fa9cdfbff38b
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "controller false"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-7f7b76bc5b-6vb88
      ownerReferences:
        - apiVersion: apps/v1
          blockOwnerDeletion: true
          controller: false
          kind: ReplicaSet
          name: nginx-7f7b76bc5b
          uid: daf540b6-b932-4b2d-a9b1-fa9cdfbff38b
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "unmanaged"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "ownerReferences set to null"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      ownerReferences: null
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "ownerReferences empty"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      ownerReferences: []
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx


================================================
FILE: internal/builtins/general/M-402_readiness_probe.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-402
slug: readiness-probe
severity: Medium
message: "Readiness and startup probe not configured"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
variables:
  - name: owners
    expression: object.metadata.?ownerReferences.orValue([])
validations:
  - expression: >
      (
        object.kind == "Pod" && 
        variables.owners != null && 
        variables.owners.exists(o, o.?kind.orValue("") == "Job" && o.?apiVersion.orValue("") == "batch/v1")
      )
      || 
      podSpec.containers.all(c, has(c.readinessProbe) || has(c.startupProbe))


================================================
FILE: internal/builtins/general/M-402_readiness_probe_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "readinessProbe not specified"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "readinessProbe not specified in managed pod"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-7f7b76bc5b-6vb88
      ownerReferences:
        - apiVersion: apps/v1
          blockOwnerDeletion: true
          controller: true
          kind: ReplicaSet
          name: nginx-7f7b76bc5b
          uid: daf540b6-b932-4b2d-a9b1-fa9cdfbff38b
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "readinessProbe set to null"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          readinessProbe: null

- name: "readiness probe configured"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          readinessProbe:
            httpGet:
              port: 80

- name: "startup probe configured"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          startupProbe:
            httpGet:
              port: 80

- name: "managed pod with readiness probe configured"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-7f7b76bc5b-6vb88
      ownerReferences:
        - apiVersion: apps/v1
          blockOwnerDeletion: true
          controller: true
          kind: ReplicaSet
          name: nginx-7f7b76bc5b
          uid: daf540b6-b932-4b2d-a9b1-fa9cdfbff38b
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          readinessProbe:
            httpGet:
              port: 80

- name: "managed pod with startup probe configured"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-7f7b76bc5b-6vb88
      ownerReferences:
        - apiVersion: apps/v1
          blockOwnerDeletion: true
          controller: true
          kind: ReplicaSet
          name: nginx-7f7b76bc5b
          uid: daf540b6-b932-4b2d-a9b1-fa9cdfbff38b
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          startupProbe:
            httpGet:
              port: 80

- name: "job"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: job-28119672-9sv4f
      labels:
        app: job
      ownerReferences:
      - apiVersion: batch/v1
        blockOwnerDeletion: true
        controller: true
        kind: Job
        name: job-28119672
        uid: 3c506232-bf9b-475b-add5-d5e850ba6ceb      
    spec:
      containers:
      - name: job
        image: job

- name: "ownerReferences set to null"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      ownerReferences: null  
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx


================================================
FILE: internal/builtins/general/M-403_liveness_probe.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-403
slug: liveness-probe
severity: Medium
message: "Liveness probe not configured"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
variables:
  - name: owners
    expression: object.metadata.?ownerReferences.orValue([])
validations:
  - expression: >
      (
        object.kind == "Pod" && 
        variables.owners != null && 
        variables.owners.exists(o, o.?kind.orValue("") == "Job" && o.?apiVersion.orValue("") == "batch/v1")
      )
      || 
      podSpec.containers.all(c, has(c.livenessProbe))


================================================
FILE: internal/builtins/general/M-403_liveness_probe_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "livenessProbe not specified"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "livenessProbe not specified in managed pod"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-7f7b76bc5b-6vb88
      ownerReferences:
        - apiVersion: apps/v1
          blockOwnerDeletion: true
          controller: true
          kind: ReplicaSet
          name: nginx-7f7b76bc5b
          uid: daf540b6-b932-4b2d-a9b1-fa9cdfbff38b
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "livenessProbe set to null"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          livenessProbe: null

- name: "ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          livenessProbe:
            httpGet:
              port: 80

- name: "managed pod ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-7f7b76bc5b-6vb88
      ownerReferences:
        - apiVersion: apps/v1
          blockOwnerDeletion: true
          controller: true
          kind: ReplicaSet
          name: nginx-7f7b76bc5b
          uid: daf540b6-b932-4b2d-a9b1-fa9cdfbff38b
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          livenessProbe:
            httpGet:
              port: 80

- name: "job"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: job-28119672-9sv4f
      labels:
        app: job
      ownerReferences:
      - apiVersion: batch/v1
        blockOwnerDeletion: true
        controller: true
        kind: Job
        name: job-28119672
        uid: 3c506232-bf9b-475b-add5-d5e850ba6ceb      
    spec:
      containers:
        - name: job
          image: job


================================================
FILE: internal/builtins/general/M-404_memory_requests.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-404
slug: memory-requests
severity: Medium
message: "Memory requests not specified"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c, c.?resources.?requests.?memory.orValue("") != "")


================================================
FILE: internal/builtins/general/M-404_memory_requests_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "resources not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "resources requests not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: 128Mi

- name: "memory requests not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              cpu: 10m

- name: "ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              cpu: 10m
              memory: 64Mi


================================================
FILE: internal/builtins/general/M-405_cpu_requests.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-405
slug: cpu-requests
severity: Medium
message: "CPU requests not specified"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c, c.?resources.?requests.?cpu.orValue("") != "")


================================================
FILE: internal/builtins/general/M-405_cpu_requests_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "resources not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "resources requests not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: 128Mi

- name: "cpu requests not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              memory: 64Mi

- name: "ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              cpu: 10m
              memory: 64Mi


================================================
FILE: internal/builtins/general/M-406_memory_limit.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-406
slug: memory-limit
severity: Medium
message: "Memory not limited"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c, c.?resources.?limits.?memory.orValue("") != "")


================================================
FILE: internal/builtins/general/M-406_memory_limit_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "resources not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "resources limits not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              memory: 64Mi

- name: "memory limits not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              cpu: 500m

- name: "ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: 128Mi


================================================
FILE: internal/builtins/general/M-407_cpu_limit.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-407
slug: cpu-limit
severity: Medium
message: "CPU not limited"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c, c.?resources.?limits.?cpu.orValue("") != "")


================================================
FILE: internal/builtins/general/M-407_cpu_limit_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "resources not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "resources limits not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            requests:
              cpu: 5m

- name: "CPU limits not set"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: 128Mi

- name: "ok"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              cpu: 500m


================================================
FILE: internal/builtins/general/M-408_sudo_container_entrypoint.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-408
slug: sudo-container-entrypoint
severity: Medium
message: "Sudo in container entrypoint"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c,
        c.?command.orValue([]).all(cmd, !cmd.contains("sudo"))
      )


================================================
FILE: internal/builtins/general/M-408_sudo_container_entrypoint_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "command not set"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "command without sudo"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          command: ["printenv"]
          resources:
            requests:
              cpu: 5m


- name: "command with sudo on entrypoint"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          command: ["sudo printenv"]
          resources:
            limits:
              memory: 128Mi

================================================
FILE: internal/builtins/general/M-409_deprecated_image_registry.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-409
slug: deprecated-image-registry
severity: Medium
message: "Deprecated image registry"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c, !c.image.contains("k8s.grc.io"))


================================================
FILE: internal/builtins/general/M-409_deprecated_image_registry_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "registry not defined"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

- name: "registry deprecated"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: reg-fail
          image: k8s.grc.io/pause

- name: "registry deprecated top"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: reg-fail
          image: k8s.grc.io/pause
        - name: reg-ok1
          image: ok-registry.com:80/nginx@sha256:asdf
        - name:  reg-ok2
          image: also-ok-registry.com:80/nginx@sha256:asdf

- name: "registry deprecated middle"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: reg-ok1
          image: ok-registry.com:80/nginx@sha256:asdf
        - name: reg-fail
          image: k8s.grc.io/pause
        - name:  reg-ok2
          image: also-ok-registry.com:80/nginx@sha256:asdf

- name: "registry deprecated bottom"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: reg-ok1
          image: ok-registry.com:80/nginx@sha256:asdf
        - name:  reg-ok2
          image: also-ok-registry.com:80/nginx@sha256:asdf
        - name: reg-fail
          image: k8s.grc.io/pause




================================================
FILE: internal/builtins/general/M-410_resource_using_invalid_restartpolicy.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-410
slug: resource-using-invalid-restartpolicy
severity: Medium
message: "Not allowed restartPolicy"
match:
  resources:
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: replicasets
validations:
  - expression: >
      podSpec.?restartPolicy.orValue("Always") == 'Always'

================================================
FILE: internal/builtins/general/M-410_resource_using_invalid_restartpolicy_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "restartPolicy not defined"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx


- name: "restartPolicy set OnFailure"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
      restartPolicy: OnFailure


- name: "restartPolicy set Always"
  pass: true
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
      restartPolicy: Always


- name: "restartPolicy set Never"
  pass: false
  input: |
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
      restartPolicy: Never


================================================
FILE: internal/builtins/general/M-411_role_binding_referencing_anonymous_or_unauthenticated.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-411
slug: role-binding-referencing-anonymous-or-unauthenticated
severity: Medium
message: "Role Binding referencing anonymous user or unauthenticated group"
match:
  resources:
    - group: "rbac.authorization.k8s.io"
      version: v1
      resource: rolebindings
    - group: "rbac.authorization.k8s.io"
      version: v1
      resource: clusterrolebindings
validations:
  - expression: >
      !has(object.subjects) ||
      object.subjects.all(subject,
        !(subject.kind == "User" && subject.name == "system:anonymous") &&
        !(subject.kind == "Group" && subject.name == "system:unauthenticated")
      )


================================================
FILE: internal/builtins/general/M-411_role_binding_referencing_anonymous_or_unauthenticated_test.yaml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "anonymous user in role binding"
  pass: false
  input: |
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: binding-name
      namespace: binding-namespace
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: role-name
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: system:anonymous
    - kind: ServiceAccount
      name: zora-operator
      namespace: zora-system

- name: "anonymous user in cluster role binding"
  pass: false
  input: |
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: binding-name
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: role-name
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: system:anonymous
    - kind: ServiceAccount
      name: zora-operator
      namespace: zora-system

- name: "unauthenticated group in role binding"
  pass: false
  input: |
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: binding-name
      namespace: binding-namespace
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: role-name
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: Group
      name: system:unauthenticated
    - kind: ServiceAccount
      name: zora-operator
      namespace: zora-system

- name: "unauthenticated group in cluster role binding"
  pass: false
  input: |
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: binding-name
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: role-name
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: Group
      name: system:unauthenticated
    - kind: ServiceAccount
      name: zora-operator
      namespace: zora-system

- name: "valid role binding"
  pass: true
  input: |
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: binding-name
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: role-name
    subjects:
    - kind: ServiceAccount
      name: zora-operator
      namespace: zora-system

- name: "valid cluster role binding"
  pass: true
  input: |
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: binding-name
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: role-name
    subjects:
    - kind: ServiceAccount
      name: zora-operator
      namespace: zora-system


================================================
FILE: internal/builtins/mitre/M-200_allowed_registries.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-200
slug: allowed-registries
severity: Medium
message: "Image registry not allowed"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
params:
  # use 'docker.io' for Docker Hub
  allowedRegistries: []
validations:
  - expression: >
      size(params.allowedRegistries) == 0 ||
      allContainers.all(container,
        params.allowedRegistries.exists(registry,
          ((registry in ['docker.io', 'docker.io/library']) && !container.image.contains('/')) ||
          container.image.startsWith(registry)
        )
      )
    message: "Container image registry not allowed"


================================================
FILE: internal/builtins/mitre/M-200_allowed_registries_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "allowedRegistries param not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "docker.io allowed"
  pass: true
  params:
    allowedRegistries: [docker.io, ghcr.io]
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "docker.io allowed and container using full name"
  pass: true
  params:
    allowedRegistries: [docker.io, ghcr.io]
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: docker.io/library/nginx:latest
      selector:
        matchLabels:
          app: nginx

- name: "ghcr.io allowed"
  pass: true
  params:
    allowedRegistries: [docker.io, ghcr.io]
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: ghcr.io/nginx/nginx
      selector:
        matchLabels:
          app: nginx

- name: "docker.io/library allowed"
  pass: true
  params:
    allowedRegistries: ["docker.io/library", ghcr.io]
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "not allowed"
  pass: false
  message: "Container image registry not allowed"
  params:
    allowedRegistries: [docker.io, ghcr.io]
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: gcr.io/nginx
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/mitre/M-201_app_credentials.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-201
slug: app-credentials
severity: High
message: "Application credentials stored in configuration files"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
    - group: ""
      version: v1
      resource: configmaps
params:
  sensitiveKeys:
    - aws_access_key_id
    - aws_secret_access_key
    - azure_batchai_storage_account
    - azure_batchai_storage_key
    - azure_batch_account
    - azure_batch_key
    - secret
    - key
    - password
    - pwd
    - token
    - jwt
    - bearer
    - credential
  sensitiveValues:
    - BEGIN \w+ PRIVATE KEY
    - PRIVATE KEY
    - eyJhbGciO
    - JWT
    - Bearer
    - key
    - secret
validations:
  - expression: >
      object.kind != 'ConfigMap' ||
      !has(object.data) ||
      object.data.all(key, 
        !params.sensitiveKeys.exists(sensitiveKey,
          key.lowerAscii().contains(sensitiveKey)
        ) &&
        !params.sensitiveValues.exists(sensitiveValue,
          object.data[key].matches(sensitiveValue)
        )
      )
    message: "ConfigMap could be storing sensitive data"

  - expression: >
      allContainers.all(container,
        !has(container.env) ||
        container.env.all(env,
          !params.sensitiveKeys.exists(sensitiveKey,
            env.name.lowerAscii().contains(sensitiveKey)
          ) &&
          (!has(env.value) ||
            !params.sensitiveValues.exists(sensitiveValue,
              env.value.matches(sensitiveValue)
            )
          )
        )
      )
    message: "Container could be storing sensitive data as environment variable"


================================================
FILE: internal/builtins/mitre/M-201_app_credentials_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "ConfigMap with no sensitive keys and values"
  pass: true
  input: |
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: config
    data:
      config: value
      foo: bar
      file.yaml: content

- name: "ConfigMap with no data"
  pass: true
  input: |
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: config

- name: "ConfigMap with empty data"
  pass: true
  input: |
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: config
    data: {}

- name: "ConfigMap with sensitive key"
  pass: false
  message: "ConfigMap could be storing sensitive data"
  input: |
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: config
    data:
      config: value
      key: value

- name: "ConfigMap with sensitive value"
  pass: false
  message: "ConfigMap could be storing sensitive data"
  input: |
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: config
    data:
      foo: bar
      config: "PRIVATE KEY"

- name: "Container with no env"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "Container with empty env"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              env: []
      selector:
        matchLabels:
          app: nginx

- name: "Container with no sensitive env"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              env:
                - name: foo
                  value: bar
      selector:
        matchLabels:
          app: nginx

- name: "Container with sensitive env name"
  pass: false
  message: "Container could be storing sensitive data as environment variable"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              env:
                - name: foo
                  value: bar
                - name: key
                  value: bar
      selector:
        matchLabels:
          app: nginx

- name: "Container with sensitive env value"
  pass: false
  message: "Container could be storing sensitive data as environment variable"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              env:
                - name: foo
                  value: "Bearer token"
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/mitre/M-202_auto_mount_service_account_token.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-202
slug: auto-mount-service-account-token
severity: Low
message: "Automounted service account token"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      podSpec.?automountServiceAccountToken.orValue(true) == false
    message: "Pod with Service Account token mounted automatically"


================================================
FILE: internal/builtins/mitre/M-202_auto_mount_service_account_token_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "automountServiceAccountToken not specified"
  pass: false
  message: "Pod with Service Account token mounted automatically"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "automountServiceAccountToken set to true"
  pass: false
  message: "Pod with Service Account token mounted automatically"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          automountServiceAccountToken: true
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "automountServiceAccountToken set to false"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          automountServiceAccountToken: false
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/mitre/M-203_ssh_server.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-203
slug: ssh-server
severity: Low
message: "SSH server running inside container"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
    - group: ""
      version: v1
      resource: services
params:
  sshPorts: [22, 2222]
validations:
  - expression: >
      object.kind != 'Service' ||
      !has(object.spec.ports) ||
      object.spec.ports.all(p,
        !(p.port in params.sshPorts) &&
        !(p.?targetPort.orValue(0) in params.sshPorts)
      )
    message: "Service should not be routing to SSH server"

  - expression: >
      allContainers.all(container,
        !has(container.ports) ||
        container.ports.all(port,
          !(port.containerPort in params.sshPorts)
        )
      )
    message: "Container could be running SSH server"


================================================
FILE: internal/builtins/mitre/M-203_ssh_server_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "Service with no targetPort"
  pass: true
  input: |
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
    spec:
      ports:
        - port: 80
      selector:
        app: nginx
      type: ClusterIP

- name: "Service with SSH port"
  pass: false
  message: "Service should not be routing to SSH server"
  input: |
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
    spec:
      ports:
        - port: 22
          targetPort: 80
      selector:
        app: nginx
      type: ClusterIP

- name: "Service with SSH targetPort"
  pass: false
  message: "Service should not be routing to SSH server"
  input: |
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
    spec:
      ports:
        - port: 8080
          targetPort: 8080
          name: http
        - port: 80
          targetPort: 2222
          name: ssh
      selector:
        app: nginx
      type: ClusterIP

- name: "Container with no ports"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "Container with empty ports"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              ports: []
      selector:
        matchLabels:
          app: nginx

- name: "Container with no SSH ports"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              ports:
                - containerPort: 80
      selector:
        matchLabels:
          app: nginx

- name: "Container with SSH port"
  pass: false
  message: "Container could be running SSH server"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              ports:
                - containerPort: 80
                - containerPort: 22
      selector:
        matchLabels:
          app: nginx

- name: "Container with SSH port 2222"
  pass: false
  message: "Container could be running SSH server"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              ports:
                - containerPort: 2222
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/nsa/M-300_read_only_root_filesystem.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

id: M-300
slug: read-only-root-filesystem
severity: Low
message: "Root filesystem write allowed"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c, c.?securityContext.?readOnlyRootFilesystem.orValue(false) == true)
    message: "Container is able to write to the root filesystem"


================================================
FILE: internal/builtins/nsa/M-300_read_only_root_filesystem_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "securityContext not specified"
  pass: false
  message: "Container is able to write to the root filesystem"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.readOnlyRootFilesystem not specified"
  pass: false
  message: "Container is able to write to the root filesystem"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                runAsNonRoot: true
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.readOnlyRootFilesystem set to false"
  pass: false
  message: "Container is able to write to the root filesystem"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                readOnlyRootFilesystem: false
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.readOnlyRootFilesystem set to true"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                readOnlyRootFilesystem: true
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/pss/baseline/M-100_host_process.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_windowsHostProcess.go
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_windowsHostProcess_test.go
id: M-100
slug: host-process
severity: High
message: "Privileged access to the Windows node"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      podSpec.?securityContext.?windowsOptions.?hostProcess.orValue(false) == false
    message: "Pod with privileged access to the Windows node"
  - expression: >
      allContainers.all(c, c.?securityContext.?windowsOptions.?hostProcess.orValue(false) == false)
    message: "Container with privileged access to the Windows node"


================================================
FILE: internal/builtins/pss/baseline/M-100_host_process_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "securityContext not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.windowsOptions not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          securityContext:
            runAsNonRoot: true
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.windowsOptions.hostProcess not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          securityContext:
            windowsOptions:
              runAsUserName: user
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.windowsOptions.hostProcess set to false"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          securityContext:
            windowsOptions:
              hostProcess: false
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.windowsOptions.hostProcess set to true"
  pass: false
  message: "Pod with privileged access to the Windows node"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          os:
            name: windows
          hostNetwork: true
          securityContext:
            windowsOptions:
              hostProcess: true
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "second container with securityContext.windowsOptions.hostProcess set to true"
  pass: false
  message: "Container with privileged access to the Windows node"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          os:
            name: windows
          hostNetwork: true
          containers:
            - name: proxy
              image: proxy
              securityContext:
                windowsOptions:
                  hostProcess: true
            - name: nginx
              image: nginx
              securityContext:
                windowsOptions:
                  hostProcess: true
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/pss/baseline/M-101_host_namespaces.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_hostNamespaces.go
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_hostNamespaces_test.go
id: M-101
slug: host-namespaces
severity: High
message: "Host namespaces"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      podSpec.?hostNetwork.orValue(false) == false &&
      podSpec.?hostPID.orValue(false) == false &&
      podSpec.?hostIPC.orValue(false) == false
    message: "Pod sharing host namespace"


================================================
FILE: internal/builtins/pss/baseline/M-101_host_namespaces_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "host options not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "hostNetwork set to true"
  pass: false
  message: "Pod sharing host namespace"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          hostNetwork: true
          hostIPC: false
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "hostPID set to true"
  pass: false
  message: "Pod sharing host namespace"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          hostNetwork: false
          hostPID: true
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "hostIPC set to true"
  pass: false
  message: "Pod sharing host namespace"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          hostIPC: true
          hostPID: false
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "all host options set to false"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          hostNetwork: false
          hostIPC: false
          hostPID: false
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "all host options set to true"
  pass: false
  message: "Pod sharing host namespace"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          hostNetwork: true
          hostIPC: true
          hostPID: true
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/pss/baseline/M-102_privileged_containers.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_privileged.go
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_privileged_test.go
id: M-102
slug: privileged-containers
severity: High
message: "Privileged container"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      allContainers.all(c, c.?securityContext.?privileged.orValue(false) == false)
    message: "Container running in privileged mode"


================================================
FILE: internal/builtins/pss/baseline/M-102_privileged_containers_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "securityContext not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.privileged not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: proxy
              image: proxy
            - name: nginx
              image: nginx
              securityContext:
                runAsNonRoot: true
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.privileged set to true"
  pass: false
  message: "Container running in privileged mode"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: proxy
              image: proxy
            - name: nginx
              image: nginx
              securityContext:
                privileged: true
      selector:
        matchLabels:
          app: nginx

- name: "initContainer securityContext.privileged set to true"
  pass: false
  message: "Container running in privileged mode"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          initContainers:
            - name: init
              image: busybox
              securityContext:
                privileged: true
          containers:
            - name: proxy
              image: proxy
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/pss/baseline/M-103_capabilities_baseline.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_capabilities_baseline.go
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_capabilities_baseline_test.go
id: M-103
slug: capabilities-baseline
severity: High
message: "Insecure capabilities"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
params:
  allowedCapabilities:
    - AUDIT_WRITE
    - CHOWN
    - DAC_OVERRIDE
    - FOWNER
    - FSETID
    - KILL
    - MKNOD
    - NET_BIND_SERVICE
    - SETFCAP
    - SETGID
    - SETPCAP
    - SETUID
    - SYS_CHROOT
validations:
  - expression: >
      allContainers.all(c, c.?securityContext.?capabilities.?add.orValue([]).all(cap, cap in params.allowedCapabilities))
    message: "Container running with not allowed capabilities"


================================================
FILE: internal/builtins/pss/baseline/M-103_capabilities_baseline_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "securityContext not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.capabilities not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                runAsNonRoot: true
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.capabilities.add not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                capabilities:
                  drop: [NET_BIND_SERVICE]
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.capabilities.add set with allowed capabilities"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                capabilities:
                  add: [CHOWN, NET_BIND_SERVICE, SETGID, SETUID]
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.capabilities.add set only with forbidden capabilities"
  pass: false
  message: "Container running with not allowed capabilities"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                capabilities:
                  add: [NET_ADMIN, SYS_TIME]
      selector:
        matchLabels:
          app: nginx

- name: "securityContext.capabilities.add set with one forbidden capability"
  pass: false
  message: "Container running with not allowed capabilities"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
              securityContext:
                capabilities:
                  add: [NET_BIND_SERVICE, NET_ADMIN]
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/pss/baseline/M-104_host_path_volumes.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_hostPathVolumes.go
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_hostPathVolumes_test.go
id: M-104
slug: host-path-volumes
severity: High
message: "HostPath volume"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
validations:
  - expression: >
      podSpec.?volumes.orValue([]).all(v, !has(v.hostPath))
    message: "Pod with mounted host volume"


================================================
FILE: internal/builtins/pss/baseline/M-104_host_path_volumes_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "volumes not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "hostPath volumes not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          volumes:
            - name: config
              configMap:
                name: nginx-config
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "hostPath set to null"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          volumes:
            - name: config
              hostPath: null
              configMap:
                name: nginx-config
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx

- name: "hostPath volume specified"
  pass: false
  message: "Pod with mounted host volume"
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          volumes:
            - name: cont1
              hostPath:
                path: path
          containers:
            - name: nginx
              image: nginx
      selector:
        matchLabels:
          app: nginx


================================================
FILE: internal/builtins/pss/baseline/M-105_host_ports.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_hostPorts.go
# https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/pod-security-admission/policy/check_hostPorts_test.go
id: M-105
slug: host-ports
severity: High
message: "Not allowed hostPort"
match:
  resources:
    - group: ""
      version: v1
      resource: pods
    - group: apps
      version: v1
      resource: deployments
    - group: apps
      version: v1
      resource: daemonsets
    - group: apps
      version: v1
      resource: statefulsets
    - group: apps
      version: v1
      resource: replicasets
    - group: batch
      version: v1
      resource: cronjobs
    - group: batch
      version: v1
      resource: jobs
params:
  allowedHostPorts: [0]
validations:
  - expression: >
      allContainers.all(c, c.?ports.orValue([]).all(p, p.?hostPort.orValue(0) in params.allowedHostPorts))
    message: "Container exposing not allowed port on the host"


================================================
FILE: internal/builtins/pss/baseline/M-105_host_ports_test.yml
================================================
# Copyright 2023 Undistro Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

- name: "ports not specified"
  pass: true
  input: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      template:
        metadata:
          name: nginx
          labels:
            app: nginx
        spec:
          containers:
   
Download .txt
gitextract_roenwdf7/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .goreleaser.yaml
├── .krew.yaml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── MAINTAINERS.md
├── Makefile
├── README.md
├── checks.md
├── cmd/
│   ├── root.go
│   ├── scan.go
│   └── version.go
├── examples/
│   ├── labels.yml
│   └── replicas.yml
├── go.mod
├── go.sum
├── install.sh
├── internal/
│   └── builtins/
│       ├── cis/
│       │   ├── M-500_workload_in_default_namespace.yaml
│       │   └── M-500_workload_in_default_namespace_test.yaml
│       ├── embed.go
│       ├── embed_test.go
│       ├── general/
│       │   ├── M-400_image_tagged_latest.yaml
│       │   ├── M-400_image_tagged_latest_test.yaml
│       │   ├── M-401_unmanaged_pod.yaml
│       │   ├── M-401_unmanaged_pod_test.yaml
│       │   ├── M-402_readiness_probe.yaml
│       │   ├── M-402_readiness_probe_test.yaml
│       │   ├── M-403_liveness_probe.yaml
│       │   ├── M-403_liveness_probe_test.yaml
│       │   ├── M-404_memory_requests.yaml
│       │   ├── M-404_memory_requests_test.yaml
│       │   ├── M-405_cpu_requests.yaml
│       │   ├── M-405_cpu_requests_test.yaml
│       │   ├── M-406_memory_limit.yaml
│       │   ├── M-406_memory_limit_test.yaml
│       │   ├── M-407_cpu_limit.yaml
│       │   ├── M-407_cpu_limit_test.yaml
│       │   ├── M-408_sudo_container_entrypoint.yaml
│       │   ├── M-408_sudo_container_entrypoint_test.yaml
│       │   ├── M-409_deprecated_image_registry.yaml
│       │   ├── M-409_deprecated_image_registry_test.yaml
│       │   ├── M-410_resource_using_invalid_restartpolicy.yaml
│       │   ├── M-410_resource_using_invalid_restartpolicy_test.yaml
│       │   ├── M-411_role_binding_referencing_anonymous_or_unauthenticated.yaml
│       │   └── M-411_role_binding_referencing_anonymous_or_unauthenticated_test.yaml
│       ├── mitre/
│       │   ├── M-200_allowed_registries.yml
│       │   ├── M-200_allowed_registries_test.yml
│       │   ├── M-201_app_credentials.yml
│       │   ├── M-201_app_credentials_test.yml
│       │   ├── M-202_auto_mount_service_account_token.yml
│       │   ├── M-202_auto_mount_service_account_token_test.yml
│       │   ├── M-203_ssh_server.yml
│       │   └── M-203_ssh_server_test.yml
│       ├── nsa/
│       │   ├── M-300_read_only_root_filesystem.yml
│       │   └── M-300_read_only_root_filesystem_test.yml
│       └── pss/
│           ├── baseline/
│           │   ├── M-100_host_process.yml
│           │   ├── M-100_host_process_test.yml
│           │   ├── M-101_host_namespaces.yml
│           │   ├── M-101_host_namespaces_test.yml
│           │   ├── M-102_privileged_containers.yml
│           │   ├── M-102_privileged_containers_test.yml
│           │   ├── M-103_capabilities_baseline.yml
│           │   ├── M-103_capabilities_baseline_test.yml
│           │   ├── M-104_host_path_volumes.yml
│           │   ├── M-104_host_path_volumes_test.yml
│           │   ├── M-105_host_ports.yml
│           │   ├── M-105_host_ports_test.yml
│           │   ├── M-106_apparmor.yml
│           │   ├── M-106_apparmor_test.yml
│           │   ├── M-107_selinux.yml
│           │   ├── M-107_selinux_test.yml
│           │   ├── M-108_proc_mount.yml
│           │   ├── M-108_proc_mount_test.yml
│           │   ├── M-109_seccomp_baseline.yml
│           │   ├── M-109_seccomp_baseline_test.yml
│           │   ├── M-110_sysctls.yml
│           │   └── M-110_sysctls_test.yml
│           └── restricted/
│               ├── M-111_volume_types.yml
│               ├── M-111_volume_types_test.yml
│               ├── M-112_privilege_escalation.yml
│               ├── M-112_privilege_escalation_test.yml
│               ├── M-113_run_as_non_root.yml
│               ├── M-113_run_as_non_root_test.yml
│               ├── M-114_run_as_user.yml
│               ├── M-114_run_as_user_test.yml
│               ├── M-115_seccomp_restricted.yml
│               ├── M-115_seccomp_restricted_test.yml
│               ├── M-116_capabilities_restricted.yml
│               └── M-116_capabilities_restricted_test.yml
├── main.go
├── pkg/
│   ├── cmd/
│   │   └── scan.go
│   ├── loader/
│   │   ├── builtin.go
│   │   ├── builtin_test.go
│   │   ├── loader.go
│   │   ├── loader_test.go
│   │   └── testdata/
│   │       ├── checks/
│   │       │   ├── svc_lb.json
│   │       │   └── workloads/
│   │       │       ├── replicas.yaml
│   │       │       ├── replicas_test.yaml
│   │       │       └── unsupported.txt
│   │       └── invalid/
│   │           └── invalid.yml
│   ├── printers/
│   │   ├── interface.go
│   │   ├── json.go
│   │   ├── md.go
│   │   ├── table.go
│   │   └── yaml.go
│   ├── types/
│   │   ├── check.go
│   │   ├── check_test.go
│   │   ├── report.go
│   │   ├── report_test.go
│   │   ├── severity.go
│   │   ├── severity_test.go
│   │   ├── status.go
│   │   └── status_test.go
│   ├── validator/
│   │   ├── activation.go
│   │   ├── compiler.go
│   │   ├── compiler_test.go
│   │   ├── interface.go
│   │   ├── podspec.go
│   │   ├── podspec_test.go
│   │   └── validator.go
│   └── version/
│       ├── version.go
│       └── version_test.go
└── test/
    └── builtins_test.go
Download .txt
SYMBOL INDEX (138 symbols across 33 files)

FILE: cmd/root.go
  function Execute (line 39) | func Execute() {
  function isKubectlPlugin (line 46) | func isKubectlPlugin() bool {
  function execName (line 50) | func execName() string {
  function init (line 58) | func init() {
  function initNoColor (line 76) | func initNoColor() {

FILE: cmd/scan.go
  function init (line 69) | func init() {

FILE: cmd/version.go
  function init (line 58) | func init() {

FILE: internal/builtins/embed_test.go
  function TestEmbedChecks (line 23) | func TestEmbedChecks(t *testing.T) {

FILE: main.go
  function main (line 19) | func main() {

FILE: pkg/cmd/scan.go
  type ScanOptions (line 42) | type ScanOptions struct
    method AddFlags (line 80) | func (o *ScanOptions) AddFlags(flags *pflag.FlagSet) {
    method Init (line 106) | func (o *ScanOptions) Init(ctx context.Context) error {
    method Validate (line 155) | func (o *ScanOptions) Validate() error {
    method ToDynamicClient (line 163) | func (o *ScanOptions) ToDynamicClient() (*dynamic.DynamicClient, error) {
    method Run (line 172) | func (o *ScanOptions) Run() (bool, error) {
    method getChecks (line 192) | func (o *ScanOptions) getChecks() ([]types.Check, error) {
    method runCheck (line 212) | func (o *ScanOptions) runCheck(check types.Check) *types.CheckResult {
    method loadResources (line 253) | func (o *ScanOptions) loadResources(check types.Check) (map[string][]u...
    method isSkipped (line 281) | func (o *ScanOptions) isSkipped(checkID string, annotations map[string...
    method addGVR (line 302) | func (o *ScanOptions) addGVR(obj unstructured.Unstructured, gvr string) {
  function NewScanOptions (line 65) | func NewScanOptions() *ScanOptions {

FILE: pkg/loader/builtin.go
  function init (line 28) | func init() {

FILE: pkg/loader/builtin_test.go
  function TestBuiltins (line 23) | func TestBuiltins(t *testing.T) {

FILE: pkg/loader/loader.go
  type ChecksMap (line 31) | type ChecksMap
    method toList (line 37) | func (cm ChecksMap) toList() []types.Check {
  type TestsMap (line 32) | type TestsMap
  type readFileFunc (line 33) | type readFileFunc
  function LoadChecks (line 56) | func LoadChecks(root string) ([]types.Check, error) {
  function LoadChecksAndTests (line 62) | func LoadChecksAndTests(root string) (ChecksMap, TestsMap, error) {
  function load (line 66) | func load(root string) (ChecksMap, TestsMap, error) {
  function walkDir (line 75) | func walkDir(readFileFn readFileFunc, builtin bool) (ChecksMap, TestsMap...
  function parseCheck (line 117) | func parseCheck(ext string, bs []byte) (types.Check, error) {
  function parseTests (line 122) | func parseTests(ext string, bs []byte) ([]types.Test, error) {
  function parse (line 127) | func parse[T any](ext string, bs []byte, obj T) (T, error) {

FILE: pkg/loader/loader_test.go
  function TestLoadChecks (line 23) | func TestLoadChecks(t *testing.T) {
  function TestLoadChecksAndTests (line 88) | func TestLoadChecksAndTests(t *testing.T) {

FILE: pkg/printers/interface.go
  type Printer (line 24) | type Printer interface

FILE: pkg/printers/json.go
  type JSONPrinter (line 25) | type JSONPrinter struct
    method PrintObj (line 27) | func (*JSONPrinter) PrintObj(report types.Report, w io.Writer) error {

FILE: pkg/printers/md.go
  type MarkdownPrinter (line 26) | type MarkdownPrinter struct
    method PrintObj (line 28) | func (*MarkdownPrinter) PrintObj(report types.Report, w io.Writer) err...

FILE: pkg/printers/table.go
  type TablePrinter (line 38) | type TablePrinter struct
    method PrintObj (line 41) | func (r *TablePrinter) PrintObj(report types.Report, w io.Writer) error {
  function renderTable (line 59) | func renderTable(report types.Report, t *tablewriter.Table) {
  function colorSeverity (line 87) | func colorSeverity(s types.Severity) string {
  function colorStatus (line 101) | func colorStatus(s types.CheckStatus) string {

FILE: pkg/printers/yaml.go
  type YAMLPrinter (line 27) | type YAMLPrinter struct
    method PrintObj (line 29) | func (*YAMLPrinter) PrintObj(report types.Report, w io.Writer) error {

FILE: pkg/types/check.go
  type Check (line 22) | type Check struct
  type Match (line 36) | type Match struct
  type ResourceRule (line 40) | type ResourceRule struct
    method ToGVR (line 46) | func (r *ResourceRule) ToGVR() schema.GroupVersionResource {
  type Validation (line 50) | type Validation struct
  type Variable (line 55) | type Variable struct
  type Test (line 60) | type Test struct

FILE: pkg/types/check_test.go
  function TestResourceRule_ToGVR (line 26) | func TestResourceRule_ToGVR(t *testing.T) {

FILE: pkg/types/report.go
  type Report (line 24) | type Report struct
    method Add (line 34) | func (r *Report) Add(cr *CheckResult) {
    method HasError (line 38) | func (r *Report) HasError() bool {
  function NewReport (line 30) | func NewReport(kubeVersion *version.Info) *Report {
  type CheckResult (line 47) | type CheckResult struct
    method AddFailed (line 82) | func (r *CheckResult) AddFailed(obj unstructured.Unstructured) {
    method AddPassed (line 87) | func (r *CheckResult) AddPassed(obj unstructured.Unstructured) {
    method AddSkipped (line 92) | func (r *CheckResult) AddSkipped(obj unstructured.Unstructured) {
    method AddError (line 97) | func (r *CheckResult) AddError(err error) {
    method AddErrors (line 101) | func (r *CheckResult) AddErrors(errs ...error) {
    method UpdateStatus (line 107) | func (r *CheckResult) UpdateStatus() {
  function NewCheckResult (line 66) | func NewCheckResult(check Check) *CheckResult {
  function GVK (line 125) | func GVK(obj unstructured.Unstructured) string {
  function NamespacedName (line 131) | func NamespacedName(obj unstructured.Unstructured) string {
  function addResource (line 138) | func addResource(obj unstructured.Unstructured, m map[string][]string) {

FILE: pkg/types/report_test.go
  function TestReport (line 42) | func TestReport(t *testing.T) {
  function obj (line 118) | func obj(apiVersion, kind, ns, name string) unstructured.Unstructured {

FILE: pkg/types/severity.go
  type Severity (line 22) | type Severity
    method String (line 32) | func (s Severity) String() string {
    method UnmarshalJSON (line 62) | func (s *Severity) UnmarshalJSON(b []byte) error {
    method MarshalJSON (line 67) | func (s Severity) MarshalJSON() ([]byte, error) {
  constant SeverityUnknown (line 25) | SeverityUnknown Severity = iota
  constant SeverityLow (line 26) | SeverityLow
  constant SeverityMedium (line 27) | SeverityMedium
  constant SeverityHigh (line 28) | SeverityHigh
  constant SeverityCritical (line 29) | SeverityCritical
  function ParseSeverity (line 47) | func ParseSeverity(s string) Severity {

FILE: pkg/types/severity_test.go
  type severityHolder (line 24) | type severityHolder struct
  function TestSeverityMarshalJSON (line 28) | func TestSeverityMarshalJSON(t *testing.T) {
  function TestSeverityUnmarshalJSON (line 68) | func TestSeverityUnmarshalJSON(t *testing.T) {

FILE: pkg/types/status.go
  type CheckStatus (line 22) | type CheckStatus
    method String (line 32) | func (s CheckStatus) String() string {
    method UnmarshalJSON (line 62) | func (s *CheckStatus) UnmarshalJSON(b []byte) error {
    method MarshalJSON (line 67) | func (s CheckStatus) MarshalJSON() ([]byte, error) {
  constant StatusUnknown (line 25) | StatusUnknown CheckStatus = iota
  constant StatusPassed (line 26) | StatusPassed
  constant StatusSkipped (line 27) | StatusSkipped
  constant StatusFailed (line 28) | StatusFailed
  constant StatusError (line 29) | StatusError
  function ParseStatus (line 47) | func ParseStatus(s string) CheckStatus {

FILE: pkg/types/status_test.go
  type statusHolder (line 24) | type statusHolder struct
  function TestCheckStatusMarshalJSON (line 28) | func TestCheckStatusMarshalJSON(t *testing.T) {
  function TestCheckStatusUnmarshalJSON (line 59) | func TestCheckStatusUnmarshalJSON(t *testing.T) {

FILE: pkg/validator/activation.go
  constant ObjectVarName (line 22) | ObjectVarName        = "object"
  constant ParamsVarName (line 23) | ParamsVarName        = "params"
  constant PodMetaVarName (line 24) | PodMetaVarName       = "podMeta"
  constant PodSpecVarName (line 25) | PodSpecVarName       = "podSpec"
  constant AllContainersVarName (line 26) | AllContainersVarName = "allContainers"
  constant APIVersionsVarName (line 27) | APIVersionsVarName   = "apiVersions"
  constant KubeVersionVarName (line 28) | KubeVersionVarName   = "kubeVersion"
  constant VariableVarName (line 29) | VariableVarName      = "variables"
  type activation (line 33) | type activation struct
    method ResolveName (line 44) | func (a *activation) ResolveName(name string) (any, bool) {
    method Parent (line 67) | func (a *activation) Parent() interpreter.Activation {

FILE: pkg/validator/compiler.go
  function Compile (line 73) | func Compile(check types.Check, apiResources []*metav1.APIResourceList, ...
  function newEnv (line 99) | func newEnv(check types.Check) (*cel.Env, error) {
  function compileVariables (line 113) | func compileVariables(env *cel.Env, vars []types.Variable, costLimit uin...
  function compileValidations (line 125) | func compileValidations(env *cel.Env, vals []types.Validation, costLimit...
  function compileExpression (line 137) | func compileExpression(env *cel.Env, exp string, costLimit uint64, allow...

FILE: pkg/validator/compiler_test.go
  function TestCompile (line 27) | func TestCompile(t *testing.T) {

FILE: pkg/validator/interface.go
  type Validator (line 23) | type Validator interface

FILE: pkg/validator/podspec.go
  function MatchesPodSpec (line 32) | func MatchesPodSpec(rules []types.ResourceRule) bool {
  function HasPodSpec (line 55) | func HasPodSpec(u unstructured.Unstructured) bool {
  function ExtractPodSpec (line 62) | func ExtractPodSpec(u unstructured.Unstructured) (*metav1.ObjectMeta, *c...
  function extractPodSpecFromTemplate (line 108) | func extractPodSpecFromTemplate(template *corev1.PodTemplateSpec) (*meta...
  function extractAllContainers (line 115) | func extractAllContainers(podSpec *corev1.PodSpec) []corev1.Container {

FILE: pkg/validator/podspec_test.go
  function TestMatchesPodSpec (line 28) | func TestMatchesPodSpec(t *testing.T) {
  function TestExtractPodSpec (line 104) | func TestExtractPodSpec(t *testing.T) {
  function TestExtractAllContainers (line 237) | func TestExtractAllContainers(t *testing.T) {

FILE: pkg/validator/validator.go
  type CELValidator (line 31) | type CELValidator struct
    method SetAPIVersions (line 44) | func (r *CELValidator) SetAPIVersions(apiVersions []string) {
    method SetKubeVersion (line 48) | func (r *CELValidator) SetKubeVersion(v *version.Info) {
    method Validate (line 52) | func (r *CELValidator) Validate(obj unstructured.Unstructured, params ...
    method setPodSpecParams (line 87) | func (r *CELValidator) setPodSpecParams(obj unstructured.Unstructured,...
  type compiledVariable (line 39) | type compiledVariable struct
  function callback (line 77) | func callback(v compiledVariable, activation any) lazy.GetFieldFunc {

FILE: pkg/version/version.go
  type Info (line 27) | type Info struct
    method String (line 35) | func (i Info) String() string {
  function Get (line 39) | func Get() Info {

FILE: pkg/version/version_test.go
  function TestGet (line 22) | func TestGet(t *testing.T) {

FILE: test/builtins_test.go
  function TestBuiltinChecks (line 28) | func TestBuiltinChecks(t *testing.T) {
  function parse (line 59) | func parse(i string) (unstructured.Unstructured, error) {
Condensed preview — 128 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (360K chars).
[
  {
    "path": ".github/dependabot.yml",
    "chars": 195,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: weekly\n  - pack"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 2224,
    "preview": "name: release\n\non:\n  push:\n    tags:\n      - 'v*'\n\npermissions:\n  contents: write\n  packages: write\n\njobs:\n  release:\n  "
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 480,
    "preview": "name: test\non:\n  pull_request:\n    branches: [main]\n  push:\n    branches: [main]\njobs:\n  validate:\n    runs-on: ubuntu-l"
  },
  {
    "path": ".gitignore",
    "chars": 287,
    "preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin\n\n# Test binary, built with `go test -c`\n*.test\n\n"
  },
  {
    "path": ".goreleaser.yaml",
    "chars": 932,
    "preview": "version: 2\nbefore:\n  hooks:\n    - go mod tidy\nbuilds:\n  - env:\n      - CGO_ENABLED=0\n    goos:\n      - linux\n      - win"
  },
  {
    "path": ".krew.yaml",
    "chars": 1356,
    "preview": "apiVersion: krew.googlecontainertools.github.com/v1alpha2\nkind: Plugin\nmetadata:\n  name: marvin\nspec:\n  homepage: https:"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5218,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1109,
    "preview": "# Contributing to Marvin\n\n:+1::tada: Thanks for taking the time to contribute! :tada::+1:\n\nThe following is a set of gui"
  },
  {
    "path": "Dockerfile",
    "chars": 1384,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "LICENSE",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "MAINTAINERS.md",
    "chars": 904,
    "preview": "# Maintainers\n\nMaintainers are approvers who have shown good technical judgement in guiding feature design & development"
  },
  {
    "path": "Makefile",
    "chars": 2674,
    "preview": "# Image URL to use all building/pushing image targets\nTAG ?= latest\nIMG ?= ghcr.io/undistro/marvin:${TAG}\n\n# Setting SHE"
  },
  {
    "path": "README.md",
    "chars": 11488,
    "preview": "<div align=\"center\">\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"assets/banner-dark.png\">\n  <img a"
  },
  {
    "path": "checks.md",
    "chars": 7624,
    "preview": "# Checks Overview  \n\nIn the table below, you can view all checks present on Marvin. Click on the #ID column item for mor"
  },
  {
    "path": "cmd/root.go",
    "chars": 1904,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "cmd/scan.go",
    "chars": 1929,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "cmd/version.go",
    "chars": 1482,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "examples/labels.yml",
    "chars": 943,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "examples/replicas.yml",
    "chars": 838,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "go.mod",
    "chars": 4085,
    "preview": "module github.com/undistro/marvin\n\ngo 1.25.4\n\nrequire (\n\tgithub.com/Masterminds/semver/v3 v3.4.0\n\tgithub.com/fatih/color"
  },
  {
    "path": "go.sum",
    "chars": 23118,
    "preview": "cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=\ncel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX"
  },
  {
    "path": "install.sh",
    "chars": 9552,
    "preview": "#!/bin/sh\n\nset -e\n# Code generated by godownloader on 2023-02-28T17:14:26Z. DO NOT EDIT.\n#\n\nusage() {\n  this=$1\n  cat <<"
  },
  {
    "path": "internal/builtins/cis/M-500_workload_in_default_namespace.yaml",
    "chars": 1225,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/cis/M-500_workload_in_default_namespace_test.yaml",
    "chars": 1844,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/embed.go",
    "chars": 673,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "internal/builtins/embed_test.go",
    "chars": 817,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "internal/builtins/general/M-400_image_tagged_latest.yaml",
    "chars": 1414,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-400_image_tagged_latest_test.yaml",
    "chars": 2703,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-401_unmanaged_pod.yaml",
    "chars": 944,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-401_unmanaged_pod_test.yaml",
    "chars": 2237,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-402_readiness_probe.yaml",
    "chars": 1417,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-402_readiness_probe_test.yaml",
    "chars": 3991,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-403_liveness_probe.yaml",
    "chars": 1379,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-403_liveness_probe_test.yaml",
    "chars": 2812,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-404_memory_requests.yaml",
    "chars": 1230,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-404_memory_requests_test.yaml",
    "chars": 1707,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-405_cpu_requests.yaml",
    "chars": 1221,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-405_cpu_requests_test.yaml",
    "chars": 1708,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-406_memory_limit.yaml",
    "chars": 1214,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-406_memory_limit_test.yaml",
    "chars": 1679,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-407_cpu_limit.yaml",
    "chars": 1205,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-407_cpu_limit_test.yaml",
    "chars": 1671,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-408_sudo_container_entrypoint.yaml",
    "chars": 1260,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-408_sudo_container_entrypoint_test.yaml",
    "chars": 1471,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-409_deprecated_image_registry.yaml",
    "chars": 1219,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-409_deprecated_image_registry_test.yaml",
    "chars": 2277,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-410_resource_using_invalid_restartpolicy.yaml",
    "chars": 988,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-410_resource_using_invalid_restartpolicy_test.yaml",
    "chars": 1462,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-411_role_binding_referencing_anonymous_or_unauthenticated.yaml",
    "chars": 1206,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/general/M-411_role_binding_referencing_anonymous_or_unauthenticated_test.yaml",
    "chars": 3248,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-200_allowed_registries.yml",
    "chars": 1565,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-200_allowed_registries_test.yml",
    "chars": 3311,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-201_app_credentials.yml",
    "chars": 2545,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-201_app_credentials_test.yml",
    "chars": 4019,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-202_auto_mount_service_account_token.yml",
    "chars": 1306,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-202_auto_mount_service_account_token_test.yml",
    "chars": 2029,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-203_ssh_server.yml",
    "chars": 1744,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/mitre/M-203_ssh_server_test.yml",
    "chars": 3822,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/nsa/M-300_read_only_root_filesystem.yml",
    "chars": 1319,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/nsa/M-300_read_only_root_filesystem_test.yml",
    "chars": 2641,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-100_host_process.yml",
    "chars": 1837,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-100_host_process_test.yml",
    "chars": 3933,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-101_host_namespaces.yml",
    "chars": 1671,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-101_host_namespaces_test.yml",
    "chars": 3400,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-102_privileged_containers.yml",
    "chars": 1616,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-102_privileged_containers_test.yml",
    "chars": 2742,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-103_capabilities_baseline.yml",
    "chars": 1912,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-103_capabilities_baseline_test.yml",
    "chars": 3736,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-104_host_path_volumes.yml",
    "chars": 1586,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-104_host_path_volumes_test.yml",
    "chars": 2524,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-105_host_ports.yml",
    "chars": 1670,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-105_host_ports_test.yml",
    "chars": 2462,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-106_apparmor.yml",
    "chars": 1960,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-106_apparmor_test.yml",
    "chars": 3008,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-107_selinux.yml",
    "chars": 2501,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-107_selinux_test.yml",
    "chars": 6561,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-108_proc_mount.yml",
    "chars": 1622,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-108_proc_mount_test.yml",
    "chars": 2924,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-109_seccomp_baseline.yml",
    "chars": 1813,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-109_seccomp_baseline_test.yml",
    "chars": 3735,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-110_sysctls.yml",
    "chars": 1920,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/baseline/M-110_sysctls_test.yml",
    "chars": 3111,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-111_volume_types.yml",
    "chars": 1896,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-111_volume_types_test.yml",
    "chars": 2391,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-112_privilege_escalation.yml",
    "chars": 1729,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-112_privilege_escalation_test.yml",
    "chars": 2462,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-113_run_as_non_root.yml",
    "chars": 2787,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-113_run_as_non_root_test.yml",
    "chars": 4065,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-114_run_as_user.yml",
    "chars": 1664,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-114_run_as_user_test.yml",
    "chars": 3096,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-115_seccomp_restricted.yml",
    "chars": 2672,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-115_seccomp_restricted_test.yml",
    "chars": 3870,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-116_capabilities_restricted.yml",
    "chars": 2075,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "internal/builtins/pss/restricted/M-116_capabilities_restricted_test.yml",
    "chars": 4114,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "main.go",
    "chars": 680,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/cmd/scan.go",
    "chars": 9717,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/loader/builtin.go",
    "chars": 994,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/loader/builtin_test.go",
    "chars": 809,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/loader/loader.go",
    "chars": 3213,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/loader/loader_test.go",
    "chars": 3592,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/loader/testdata/checks/svc_lb.json",
    "chars": 403,
    "preview": "{\n  \"id\": \"TEST-002\",\n  \"message\": \"Type Loadbalancer detected. Could be expensive\",\n  \"severity\": \"Low\",\n  \"match\": {\n "
  },
  {
    "path": "pkg/loader/testdata/checks/workloads/replicas.yaml",
    "chars": 865,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "pkg/loader/testdata/checks/workloads/replicas_test.yaml",
    "chars": 1880,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "pkg/loader/testdata/checks/workloads/unsupported.txt",
    "chars": 21,
    "preview": "unsupported file type"
  },
  {
    "path": "pkg/loader/testdata/invalid/invalid.yml",
    "chars": 593,
    "preview": "# Copyright 2023 Undistro Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use "
  },
  {
    "path": "pkg/printers/interface.go",
    "chars": 826,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/printers/json.go",
    "chars": 993,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/printers/md.go",
    "chars": 1192,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/printers/table.go",
    "chars": 3158,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/printers/yaml.go",
    "chars": 991,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/check.go",
    "chars": 2093,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/check_test.go",
    "chars": 1617,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/report.go",
    "chars": 3701,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/report_test.go",
    "chars": 3258,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/severity.go",
    "chars": 1470,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/severity_test.go",
    "chars": 2259,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/status.go",
    "chars": 1471,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/types/status_test.go",
    "chars": 2006,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/validator/activation.go",
    "chars": 1828,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/validator/compiler.go",
    "chars": 5063,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/validator/compiler_test.go",
    "chars": 2914,
    "preview": "// Copyright 2024 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/validator/interface.go",
    "chars": 981,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/validator/podspec.go",
    "chars": 5709,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/validator/podspec_test.go",
    "chars": 6742,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/validator/validator.go",
    "chars": 3428,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/version/version.go",
    "chars": 1150,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "pkg/version/version_test.go",
    "chars": 2091,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  },
  {
    "path": "test/builtins_test.go",
    "chars": 1899,
    "preview": "// Copyright 2023 Undistro Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
  }
]

About this extraction

This page contains the full source code of the undistro/marvin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 128 files (324.5 KB), approximately 93.9k tokens, and a symbol index with 138 extracted functions, classes, methods, constants, and types. 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!