Skip to content

fix(security): harden k8s sample manifest defaults#1324

Merged
ericksoa merged 3 commits intoNVIDIA:mainfrom
jyaunches:fix/harden-k8s-manifest-defaults
Apr 15, 2026
Merged

fix(security): harden k8s sample manifest defaults#1324
ericksoa merged 3 commits intoNVIDIA:mainfrom
jyaunches:fix/harden-k8s-manifest-defaults

Conversation

@jyaunches
Copy link
Copy Markdown
Contributor

@jyaunches jyaunches commented Apr 2, 2026

Fixes #1323 — Partially addresses #803.

Summary

Hardens the experimental Kubernetes sample manifest (k8s/nemoclaw-k8s.yaml) with safer defaults. This work was cherry-picked from @13ernkastel's PR #1149, which was closed after its auth hardening portion was superseded by #1217. The k8s hardening in #1149 was independent and valuable, so we're carrying it forward here with proper attribution.

Changes

Pod-level

  • automountServiceAccountToken: false — pod does not need k8s API access
  • enableServiceLinks: false — prevents service env var injection

Workspace container security context

  • allowPrivilegeEscalation: false
  • capabilities.drop: [ALL]
  • seccompProfile.type: RuntimeDefault

Credential handling

  • COMPATIBLE_API_KEY loaded from optional Secret (nemoclaw-compatible-api-key) with dummy fallback for unauthenticated endpoints (Dynamo/vLLM)
  • NEMOCLAW_POLICY_MODE default changed from skip to suggested

Installer download

  • Replaced curl ... | bash with download-then-execute pattern using curl --proto =https --tlsv1.2

Documentation

  • Updated k8s/README.md with Secret setup instructions and revised config table

Tests

  • Added test/security-configuration-hardening.test.js with regression coverage for all k8s manifest hardening

Attribution

Co-authored-by: @13ernkastel (from PR #1149)

Context

This came up during post-merge cleanup of #1217 (fix(security): harden gateway auth defaults and restrict auto-pair). PR #1149 bundled k8s hardening with auth changes; we split them apart so the k8s work doesn't get lost.

Summary by CodeRabbit

  • New Features

    • Added optional NEMOCLAW_POLICY_MODE environment variable for non-interactive onboarding (default: suggested).
  • Documentation

    • Updated Kubernetes deployment guide with safer manifest examples and conditional secret creation instructions.
  • Configuration Changes

    • API key now optionally sourced from a Kubernetes Secret (falls back to dummy); stricter default pod security and service settings; installer fetch now downloads securely to a file (no curl|sh pipeline).
  • Tests

    • Added validation tests to verify manifest hardening and installer behavior.

Cherry-picked k8s hardening from @13ernkastel's PR NVIDIA#1149, which was
closed after its auth changes were superseded by NVIDIA#1217.

Changes to k8s/nemoclaw-k8s.yaml:
- automountServiceAccountToken: false
- enableServiceLinks: false
- workspace container: allowPrivilegeEscalation false, drop ALL caps,
  RuntimeDefault seccomp
- COMPATIBLE_API_KEY from optional Secret with dummy fallback
- NEMOCLAW_POLICY_MODE default changed from skip to suggested
- Replace curl|bash with download-then-execute pattern

Also adds k8s/README.md updates and regression test.

Co-authored-by: 13ernkastel <LennonCMJ@live.com>
@jyaunches
Copy link
Copy Markdown
Contributor Author

@ericksoa — this came up as a potential follow-up while cleaning up after our recently merged #1217. PR #1149 by @13ernkastel had bundled k8s manifest hardening (pod security context, Secret-backed credentials, safer installer download) alongside the auth changes that #1217 superseded. We closed #1149 but cherry-picked the k8s portion here so it doesn't get lost.

Do you agree this is complementary for the k8s deployment path? The changes are scoped to k8s/nemoclaw-k8s.yaml, k8s/README.md, and a new regression test — no overlap with the auth/auto-pair work.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e4afa791-63ae-44e4-b52b-d9a6d2066a6b

📥 Commits

Reviewing files that changed from the base of the PR and between 6685ef7 and 2bae1ae.

📒 Files selected for processing (1)
  • k8s/nemoclaw-k8s.yaml

📝 Walkthrough

Walkthrough

Harden Kubernetes sample manifests and docs: disable token automounting and service link injection, tighten container securityContext, switch installer to download-then-execute with strict TLS flags, make COMPATIBLE_API_KEY an optional Secret-backed value with a dummy fallback, change NEMOCLAW_POLICY_MODE to "suggested", and add tests validating these changes.

Changes

Cohort / File(s) Summary
Documentation & Deployment
k8s/README.md
Documented safer manifest defaults, added optional nemoclaw-compatible-api-key Secret creation step, marked COMPATIBLE_API_KEY as non-required (Secret-backed, default dummy), introduced NEMOCLAW_POLICY_MODE (suggested) and recommended HTTPS-only installer download flags.
Kubernetes Manifest Hardening
k8s/nemoclaw-k8s.yaml
Pod-level hardening: automountServiceAccountToken: false, enableServiceLinks: false. workspace container: securityContext with allowPrivilegeEscalation: false, capabilities.drop: [ALL], seccompProfile: RuntimeDefault. Installer changed to download-to-file (curl --proto =https --tlsv1.2/tmp/nemoclaw-install.sh, chmod 700, execute, cleanup). COMPATIBLE_API_KEY moved to optional secretKeyRef (nemoclaw-compatible-api-key, key api-key) with runtime fallback to dummy. NEMOCLAW_POLICY_MODE default set to suggested.
Tests
test/security-configuration-hardening.test.js
New Vitest file asserting presence of pod/container hardening fields, seccomp and capability drops, NEMOCLAW_POLICY_MODE: "suggested", COMPATIBLE_API_KEY secretKeyRef with optional: true, download-to-file installer steps, and absence of curl-pipe-to-shell patterns.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I dug a patch, I tightened screws,
Tokens tucked away from snoozy views,
Caps dropped gently, scripts saved to file,
Secrets tucked in, fallback with a smile,
Hoppy hardening — secure for miles! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(security): harden k8s sample manifest defaults' clearly summarizes the main objective: hardening the Kubernetes sample manifest with security improvements.
Linked Issues check ✅ Passed The PR implements all core coding requirements from issue #1323: pod-level hardening (automountServiceAccountToken and enableServiceLinks), container securityContext (allowPrivilegeEscalation, capabilities.drop, seccompProfile), credential handling (COMPATIBLE_API_KEY from Secret with fallback, NEMOCLAW_POLICY_MODE default change), and secure installer pattern.
Out of Scope Changes check ✅ Passed All changes are strictly scoped to the linked issue #1323: k8s/nemoclaw-k8s.yaml manifest hardening, k8s/README.md documentation updates, and a new regression test. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
k8s/README.md (1)

1-2: ⚠️ Potential issue | 🟡 Minor

Missing SPDX license header.

As per coding guidelines, Markdown files require an HTML comment SPDX license header at the top:

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->
<!-- SPDX-License-Identifier: Apache-2.0 -->
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@k8s/README.md` around lines 1 - 2, Add the required SPDX HTML comment header
to the top of the Markdown file that currently starts with the title "# NemoClaw
on Kubernetes": insert the two lines for Copyright and License as HTML comments
(the SPDX-FileCopyrightText and SPDX-License-Identifier) immediately before the
existing content so the README.md contains the SPDX header above the title.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@k8s/README.md`:
- Around line 1-2: Add the required SPDX HTML comment header to the top of the
Markdown file that currently starts with the title "# NemoClaw on Kubernetes":
insert the two lines for Copyright and License as HTML comments (the
SPDX-FileCopyrightText and SPDX-License-Identifier) immediately before the
existing content so the README.md contains the SPDX header above the title.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7672ed34-5739-4886-91b5-e300b1583162

📥 Commits

Reviewing files that changed from the base of the PR and between db65da8 and 6685ef7.

📒 Files selected for processing (3)
  • k8s/README.md
  • k8s/nemoclaw-k8s.yaml
  • test/security-configuration-hardening.test.js

@ericksoa
Copy link
Copy Markdown
Contributor

ericksoa commented Apr 2, 2026

Reviewed the changes — the API key fallback and policy mode switch both look safe after code analysis (no early consumers for COMPATIBLE_API_KEY; suggested mode is fully headless when NEMOCLAW_NON_INTERACTIVE=1). Two items:

Blocker: workspace securityContext breaks apt-get

Have you tried running this manifest in a real pod? The workspace container runs apt-get update && apt-get install before the installer, and apt-get internally sandboxes itself by switching to the _apt user — which requires CAP_SETUID/CAP_SETGID. With drop: [ALL], that fails:

E: setgroups 65534 failed - setgroups (1: Operation not permitted)
E: seteuid 42 failed - seteuid (1: Operation not permitted)

(Reproducible with: docker run --rm --cap-drop=ALL --security-opt no-new-privileges node:22 bash -c "apt-get update -qq")

Since the workspace container doesn't need elevated privileges beyond the package install phase, and DinD is already the privileged sidecar, would it make sense to drop the workspace securityContext from this PR and tackle it separately? The pod-level hardening (automountServiceAccountToken, enableServiceLinks), Secret-backed credentials, and installer download changes all stand on their own.

Style: We're moving all new code to TypeScript — could test/security-configuration-hardening.test.js be a .test.ts file instead?

@wscurran wscurran added security Something isn't secure priority: medium Issue that should be addressed in upcoming releases K8s Use this label to identify Kubernetes deployment issues with NemoClaw. labels Apr 3, 2026
@cv cv added the v0.0.16 Release target label Apr 14, 2026
@wscurran
Copy link
Copy Markdown
Contributor

Thanks for the k8s manifest hardening — dropping automountServiceAccountToken and capabilities is exactly the right approach. The codebase has changed significantly since April 2 — including a full TypeScript migration — so this will need a rebase on origin/main before we can review it. Please rebase and resolve any conflicts, and we'll take a look.

@wscurran wscurran added the status: rebase PR needs to be rebased against main before review can continue label Apr 14, 2026
Copy link
Copy Markdown
Contributor

@ericksoa ericksoa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — solid k8s hardening. Standard best practices across the board: no privilege escalation, drop ALL caps, RuntimeDefault seccomp, optional Secret with fallback, no pipe-to-bash. Test coverage for all of it. Nice attribution from #1149.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa ericksoa merged commit 6c10636 into NVIDIA:main Apr 15, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

K8s Use this label to identify Kubernetes deployment issues with NemoClaw. priority: medium Issue that should be addressed in upcoming releases security Something isn't secure status: rebase PR needs to be rebased against main before review can continue v0.0.16 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(security): harden k8s sample manifest defaults

4 participants