Skip to content

fix: add securityContext support to ephemeral debug containers for restricted PodSecurity namespaces#5050

Open
harshitrwt wants to merge 2 commits intokubernetes-sigs:mainfrom
harshitrwt:feature/addEphemeralContainer
Open

fix: add securityContext support to ephemeral debug containers for restricted PodSecurity namespaces#5050
harshitrwt wants to merge 2 commits intokubernetes-sigs:mainfrom
harshitrwt:feature/addEphemeralContainer

Conversation

@harshitrwt
Copy link
Copy Markdown

This PR fixes #4969 by introducing two complementary changes:

  1. Safe default: addEphemeralContainer() now applies a restricted-compatible securityContext by default:

    • allowPrivilegeEscalation: false
    • capabilities.drop: ["ALL"]
    • runAsNonRoot: true
    • seccompProfile.type: RuntimeDefault
  2. User control: A new "Restricted Security Context" toggle is added to Pod Debug Settings (alongside the existing image and enable/disable settings). It defaults to on, but users can turn it off for clusters where they need elevated permissions in their debug container.

Files Changed

  • frontend/src/helpers/clusterSettings.ts : added useRestrictedSecurityContext field to ClusterSettings type
  • frontend/src/lib/k8s/pod.ts : addEphemeralContainer() accepts and applies securityContext
  • frontend/src/components/pod/PodDebugTerminal.tsx : reads setting from cluster config and passes it through
  • frontend/src/components/App/Settings/PodDebugSettings.tsx : new toggle row in the Pod Debug Settings UI

Testing

To reproduce the original bug and verify the fix:

# Create a restricted namespace
kubectl create namespace restricted-test
kubectl label namespace restricted-test \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest

# Deploy a compliant pod
kubectl apply -f 
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: restricted-test
spec:
  containers:
  - name: app
    image: nginx:alpine
    securityContext:
      allowPrivilegeEscalation: false
      runAsNonRoot: true
      runAsUser: 1000
      capabilities:
        drop: ["ALL"]
      seccompProfile:
        type: RuntimeDefault

Notes

  • The securityContext default does not break debugging in non-restricted namespaces, a restricted context is still fully functional for shell access, log inspection, env var checks, etc.

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: harshitrwt
Once this PR has been reviewed and has the lgtm label, please assign illume for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot requested review from skoeva and sniok April 4, 2026 10:18
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

Welcome @harshitrwt!

It looks like this is your first PR to kubernetes-sigs/headlamp 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-sigs/headlamp has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Apr 4, 2026
@illume illume requested a review from Copilot April 4, 2026 18:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses #4969 by making the “Debug Pod” ephemeral container compatible with restricted PodSecurity namespaces, while still allowing users to opt out per-cluster via settings.

Changes:

  • Add a per-cluster “Restricted Security Context” toggle (default on) in Pod Debug Settings and persist it in ClusterSettings.
  • Pass the toggle value through the debug terminal flow to Pod.addEphemeralContainer().
  • Apply a restricted-compatible securityContext to the created ephemeral container when the toggle is enabled.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
frontend/src/helpers/clusterSettings.ts Extends ClusterSettings.podDebugTerminal with useRestrictedSecurityContext.
frontend/src/lib/k8s/pod.ts Adds a boolean flag to addEphemeralContainer() and conditionally injects a restricted securityContext.
frontend/src/components/pod/PodDebugTerminal.tsx Reads the new setting and passes it to the ephemeral container creation path.
frontend/src/components/App/Settings/PodDebugSettings.tsx Adds a new settings row + state/update logic for the restricted security context toggle.

Comment on lines 318 to +326
imagePullPolicy: 'IfNotPresent',
...(useRestrictedSecurityContext && {
securityContext: {
allowPrivilegeEscalation: false,
capabilities: { drop: ['ALL'] },
runAsNonRoot: true,
seccompProfile: { type: 'RuntimeDefault' },
},
}),
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

securityContext is being added to an object typed as KubeContainer, but KubeContainer currently does not declare a securityContext field (see frontend/src/lib/k8s/cluster.ts where it's still marked as a TODO). This will fail TypeScript excess-property checks during build. Add an appropriate securityContext type to KubeContainer (or use a dedicated ephemeral-container type) so this compiles cleanly.

Copilot uses AI. Check for mistakes.
Comment on lines +206 to +220
{
name: (
<HoverInfoLabel
label={<span>Restricted Security Context</span>}
hoverInfo={t(
'translation|Apply a restricted-compatible securityContext to the debug container. Required for namespaces enforcing the restricted PodSecurity policy. Sets: allowPrivilegeEscalation=false, capabilities.drop=ALL, runAsNonRoot=true, seccompProfile=RuntimeDefault.'
)}
/>
),
value: (
<Switch
checked={useRestrictedSecurityContext}
onChange={e => storeNewRestrictedSecurityContext(e.target.checked)}
/>
),
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The new "Restricted Security Context" switch is missing an accessible label association. Other switches in Settings pass inputProps={{ 'aria-labelledby': ... }} and render a label element with a matching id; add the same pattern here so screen readers announce what this toggle controls.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment on lines +208 to +219
<HoverInfoLabel
label={<span>Restricted Security Context</span>}
hoverInfo={t(
'translation|Apply a restricted-compatible securityContext to the debug container. Required for namespaces enforcing the restricted PodSecurity policy. Sets: allowPrivilegeEscalation=false, capabilities.drop=ALL, runAsNonRoot=true, seccompProfile=RuntimeDefault.'
)}
/>
),
value: (
<Switch
checked={useRestrictedSecurityContext}
onChange={e => storeNewRestrictedSecurityContext(e.target.checked)}
/>
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The new "Restricted Security Context" toggle Switch is missing an accessible label association. The "Enable Pod Debug" switch wires aria-labelledby, but this one doesn’t provide inputProps (or an aria-label), so screen readers may announce it without context.

Add an id to the label element and pass inputProps={{ 'aria-labelledby': <id> }} (or an equivalent aria-label) on the Switch.

Copilot uses AI. Check for mistakes.
Comment on lines 298 to 310
/**
* Add an ephemeral container to the pod.
* @param containerName - The name of the ephemeral container to add
* @param image - The container image to use
* @param command - Optional command to run in the container (defaults to ['sh'])
* @returns Promise that resolves when the ephemeral container is added
*/
async addEphemeralContainer(
containerName: string,
image: string,
command: string[] = ['sh']
command: string[] = ['sh'],
useRestrictedSecurityContext: boolean = true
): Promise<void> {
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The JSDoc for addEphemeralContainer hasn’t been updated for the new useRestrictedSecurityContext parameter. Please document the new argument (what it does, default behavior, and why/when to disable it) so future callers understand the security implications.

Copilot uses AI. Check for mistakes.
Comment on lines 86 to 102
/**
* Creates an ephemeral debug container and waits for it to be ready.
* Polls pod status up to 30 times (30 seconds) for container to reach running state.
*
* @param item - Pod to add ephemeral container to
* @param containerName - Name for the new container
* @param debugImage - Container image for debugging
* @param onError - Error handler callback
* @returns Object with containerName if successful, empty object on error
*/
async function debugPod(
item: Pod,
containerName: string,
debugImage: string,
onError: (message: string) => void
onError: (message: string) => void,
useRestrictedSecurityContext: boolean = true
) {
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The JSDoc for debugPod lists parameters but doesn’t include the new useRestrictedSecurityContext argument. Please update the comment to document this parameter and its default, since it changes behavior and is security-relevant.

Copilot uses AI. Check for mistakes.
@harshitrwt
Copy link
Copy Markdown
Author

Thanks for the review, working on it.

@harshitrwt harshitrwt force-pushed the feature/addEphemeralContainer branch from 3ca1e8c to 29c606a Compare April 5, 2026 08:05
@harshitrwt
Copy link
Copy Markdown
Author

Hi @illume , Any reviews on new changes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Debug Pod does not set securityContext, failing PodSecurity restricted policy

3 participants