Skip to main content

agent-k8s-harden-check: Kubernetes Agent Workload Hardening Checker

Read local Kubernetes YAML and flag AI-agent workloads that are missing isolation. One Python script. PyYAML is the only dependency.

Use it on manifests you own or are explicitly allowed to review.

Why it matters

Agent workloads often run with a tool that can open HTTP connections. Three public write-ups are the reason this checker exists:

Those are links to the public pages. This repository does not restate procedures from them. It reads the YAML you already have and tells you which of those controls are missing from the text.

Quickstart

Requires Python 3.9 or newer.

pip install agent-k8s-harden-check

To match CI exactly:

pip install -r requirements.txt

requirements.txt pins PyYAML. The script imports that package and the standard library only.

From this directory, the script and the installed command take the same path:

python3 agent_k8s_harden_check.py examples/bad-agent-pod.yaml
agent-k8s-harden-check examples/bad-agent-pod.yaml

python3 agent_k8s_harden_check.py examples/good-agent-pod.yaml examples/egress-networkpolicy.yaml
agent-k8s-harden-check examples/good-agent-pod.yaml examples/egress-networkpolicy.yaml

python3 agent_k8s_harden_check.py examples --json
agent-k8s-harden-check examples --json

PATH is a YAML file, or a directory. A directory is scanned for .yaml and .yml files. Hidden directories are skipped. Multi-document YAML is read. The examples are fictional and are there for a local offline check.

examples/bad-agent-pod.yaml is a pod with no runtime class, a service-account token automount, a privileged root container, host networking, and no limits. That run exits 1:

Kubernetes agent workload hardening check

examples/bad-agent-pod.yaml
  FAIL  runtime-class                         Pod/fictional-unisolated-agent  ns=agent-lab
        runtimeClassName is not set
  FAIL  automount-service-account-token       Pod/fictional-unisolated-agent  ns=agent-lab
        pod automountServiceAccountToken is true
  PASS  projected-service-account-token       Pod/fictional-unisolated-agent  ns=agent-lab
        no projected volume mounts a serviceAccountToken
  FAIL  privileged                            Pod/fictional-unisolated-agent  ns=agent-lab
        privileged is true on container agent
  FAIL  run-as-non-root                       Pod/fictional-unisolated-agent  ns=agent-lab
        root is set: container agent (runAsUser is 0)
  FAIL  host-namespaces                       Pod/fictional-unisolated-agent  ns=agent-lab
        host namespace enabled: hostNetwork
  WARN  resource-limits                       Pod/fictional-unisolated-agent  ns=agent-lab
        cpu or memory limits are missing: container agent (cpu, memory)
  WARN  egress-metadata-rfc1918               Pod/fictional-unisolated-agent  ns=agent-lab
        no NetworkPolicy with policyTypes Egress was found for namespace agent-lab. Manifest text only; this does not show the cluster enforces it.

summary: pass=1 warn=2 fail=5 errors=0
A pass is a reading of the local YAML. It is not cluster enforcement.

examples/good-agent-pod.yaml sets runtimeClassName: gvisor, turns automount off, runs as a non-root user, and sets cpu and memory limits. Scanned on its own, the egress check warns, because no NetworkPolicy was in that file. Exit 0. Pass the egress example on the same command line and that warning clears. Exit stays 0.

--json prints the same findings as JSON.

What it checks

The script reads these kinds: Pod, Deployment, StatefulSet, DaemonSet, Job, CronJob, ReplicaSet, NetworkPolicy, plus Sandbox and SandboxTemplate. A document whose apiVersion contains agent-sandbox is read as a workload too. For Deployments and the other owners, the pod spec is spec.template.spec. For a CronJob it is spec.jobTemplate.spec.template.spec. For Sandbox and SandboxTemplate it is spec.podTemplate.spec (or spec.template.spec when that is where the fields are).

Check Pass Otherwise
runtime-class runtimeClassName contains gvisor or kata, case-insensitive fail when it is missing or names something else
automount-service-account-token the pod, or the ServiceAccount it names in the same scan, sets automountServiceAccountToken: false fail when it is true, or unset (Kubernetes defaults that to true)
projected-service-account-token no projected volume source has serviceAccountToken fail when one is present
privileged privileged is not true on the pod or on any container, init container, or ephemeral container fail when it is true
run-as-non-root runAsNonRoot: true and runAsUser is not 0 fail when a container is clearly root (runAsUser: 0 or runAsNonRoot: false); warn when neither field says
host-namespaces hostNetwork, hostPID, and hostIPC are false or absent fail when any is true
resource-limits every container has cpu and memory limits warn when one is missing
egress-metadata-rfc1918 NetworkPolicy text in the same namespace does not allow 169.254.169.254/32, 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16 warn when no egress policy was in the scan, or the text is unclear

The egress check looks for policyTypes containing Egress. Empty egress is read as default-deny text. An allow rule passes this check only when the four destinations above are outside the allow, including when they appear in an except list. Policies in one namespace are unioned, because Kubernetes unions allows. A pod or namespace selector is unclear for the RFC1918 ranges, since those selectors name pods rather than CIDRs. A podSelector with matchLabels is applied only when those labels are on the pod, or on the pod template. If the selector is not a clear match, that policy is not counted as coverage.

A pass on the egress check means those four destinations were excluded or omitted in the files you scanned. Other destinations may still be allowed. An empty egress list is the case where the text allows no destinations.

Every egress line says the same thing in prose: this is a reading of manifest text. It is not evidence that a cluster enforces the policy.

What it does

It parses the files you name, prints a pass / warn / fail line per object and check, and returns the exit code below. --json prints summary, findings, and errors.

What it does not do

  • It does not connect to a cluster, run kubectl, or apply, create, or edit a resource.
  • It does not decide that a cluster is safe. A clean file can still be absent from the cluster, and a failing file can describe a workload you have not deployed.
  • It does not review admissions controllers, runtime installation, or identity systems that are not in the YAML you passed.
  • It does not follow Helm or Kustomize. Give it rendered YAML.
  • It does not treat a warning as success-of-the-control. Warnings are gaps the text did not settle. They do not fail the process exit code.

Authorized use

This repository is MIT licensed. It is for defensive checks only.

  • Review manifests you own or are authorized to assess.
  • Keep the examples as local fixtures. They are fictional and are not a deployment guide.
  • Do not point the script at files you are not allowed to read.

Exit codes

Code Meaning
0 No check failed. Warnings are allowed.
1 One or more checks failed.
2 A path, flag, or YAML document could not be used (missing path, unknown flag, invalid YAML, or a directory with no .yaml / .yml files).

Tests

From this directory, with PyYAML installed:

python3 -m unittest discover -s tests -v

The workflow in .github/workflows/test.yml installs requirements.txt and runs that command. It does not contact a cluster.

Examples

File What it is
examples/bad-agent-pod.yaml Fictional pod missing the isolation fields: no runtime class, automount on, privileged root, host network, no limits
examples/good-agent-pod.yaml Fictional pod with runtimeClassName: gvisor, automount off, non-root, no host namespaces, and limits
examples/egress-networkpolicy.yaml Illustrative NetworkPolicy text that excludes the metadata address and the three RFC1918 ranges. Checker fixture, not an apply guide
examples/sandbox-like.yaml Fictional Sandbox and SandboxTemplate documents using the public podTemplate.spec field names

For more from Digital Fortress

This checker reads a handful of fields in local YAML. The paid packs are the longer review set: prompts, templates, and checklists for the same kinds of systems.

For more from Digital Fortress:

Free siblings:

Sources

License

MIT © 2026 Digital Fortress · github.com/digitalfortressaudit. Authorized defensive use only, as described above.

Metadata

Release files for agent-k8s-harden-check 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-k8s-harden-check 0.1.0
File Size Uploaded Provenance
agent_k8s_harden_check-0.1.0.tar.gz 21.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-k8s-harden-check 0.1.0
File Interpreter ABI Platform
agent_k8s_harden_check-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.0 kB

Release files / agent_k8s_harden_check-0.1.0.tar.gz

Download URL agent_k8s_harden_check-0.1.0.tar.gz
Size 21.1 kB
Tags Source
SHA-256 checksum
How to use checksums
85e6d441457cde61e8c0064c28cd3c757f51ec7f4b2cb516099c4793836d5274
BLAKE2b-256 checksum
How to use checksums
aedf01a0953040bb55788b3fce252d49fccc38d955b2599955d6c40889247fc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / agent_k8s_harden_check-0.1.0-py3-none-any.whl

Download URL agent_k8s_harden_check-0.1.0-py3-none-any.whl
Size 16.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
144f6ed302bea7234c7df42ac91d1556e413297730f40cfcf1bace94c1fb323e
BLAKE2b-256 checksum
How to use checksums
0ddd2b4c5688359f3dc32e6ded1b84bd7716e61956e15ea756650ff6704ef759
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for agent-k8s-harden-check 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for agent_k8s_harden_check-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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