Get unstuck

Hint 1: The pod is more than the application process

Init and ephemeral containers share the workload boundary.

Hint 2: Only runAsNonRoot inherits

Read runAsNonRoot from the container, falling back to spec.securityContext. allowPrivilegeEscalation and capabilities exist only on containers, so absence there is not the explicit setting.

Reveal the reference patch and explanation
Fixedpod-policy.mjsJavaScript
export function allowPod(pod) {
  const s = pod?.spec;
  if (!s || s.hostNetwork || s.hostPID || s.hostIPC
      || !Array.isArray(s.containers) || !s.containers.length) return false;
  // runAsNonRoot is the one setting here with a Pod-level default; a container value overrides it.
  const podNonRoot = s.securityContext?.runAsNonRoot;
  if (podNonRoot === false) return false;
  const all = [...s.containers, ...(s.initContainers || []), ...(s.ephemeralContainers || [])];
  return all.every(c => {
    const x = c.securityContext || {};
    return (x.runAsNonRoot ?? podNonRoot) === true && x.allowPrivilegeEscalation === false
      && x.privileged !== true && Array.isArray(x.capabilities?.drop)
      && x.capabilities.drop.includes('ALL');
  });
}

The safe app and safe sidecar pass because every listed container meets the policy. The Pod-level fixture, the guide’s Deployment shape, passes because each container leaves runAsNonRoot unset and inherits true from spec.securityContext, while setting allowPrivilegeEscalation:false and dropping ALL itself. A container that sets runAsNonRoot:false fails even under a Pod-level true, because the container value overrides it, and a Pod-level false fails outright. A privileged init or ephemeral container fails even when the main app is safe. hostNetwork fails at Pod scope. Missing securityContext, allowPrivilegeEscalation=true or dropping only NET_RAW fails the container predicate. An empty application-container list is rejected before every(), preventing an empty-list truth from authorizing a malformed workload.

Compare it with your own fix, then rerun the tests. The editor is not changed when you open this explanation.

Inspect the actual test harness

The browser and the lab download run the same cases, including cases that catch common wrong fixes, such as comparing with one fixture value instead of the real rule. The download includes the complete test adapter and cryptographic fixtures.

Download cases.mjs
How the browser sandbox runs your code

Your code runs in QuickJS 2025-09-13 (quickjs-emscripten 0.32.0) inside a Web Worker, isolated from the page, with a 32 MiB memory limit and a 2.5-second time limit. The test cases and the pass or fail verdict run outside that sandbox, so changing built-ins such as Array.prototype.push cannot change the result. The lab download runs the same cases under Node.js, where your code runs directly.

The same as in current Node.js:

  • ES2025 syntax and built-ins, including Set methods such as intersection, iterator helpers, Promise.try, RegExp.escape and the RegExp v flag

Added to the sandbox so that it behaves like Node.js:

  • structuredClone, Array.fromAsync, queueMicrotask, atob and btoa
  • URL and URLSearchParams, parsed by your browser’s own URL implementation
  • TextEncoder and TextDecoder for UTF-8
  • Intl.Collator and a locale-aware String.prototype.localeCompare
  • console.log and related methods, whose output appears with your results

Not available in the browser sandbox:

  • Timers (setTimeout, setInterval), fetch and other network or storage APIs; the exercises are deterministic and offline
  • Node.js modules and globals: import, require, process and Buffer
  • Web Crypto (crypto.getRandomValues, crypto.subtle); each workshop supplies the cryptographic operations it needs
  • Intl other than Collator: toLocaleString and toLocaleDateString ignore the locale, so numbers have no digit grouping and dates use one fixed format in the device’s time zone
  • using declarations, Symbol.dispose and DisposableStack (explicit resource management)
  • Uint8Array.fromBase64 and toBase64, JSON.rawJSON, Atomics and Error.captureStackTrace

Use the lesson in your own system

This is a small policy model for normalized fixtures, not a complete implementation of the Pod Security Standards. The Restricted profile also requires a RuntimeDefault or Localhost seccomp profile (which, like runAsNonRoot, may be set at Pod level), allows adding back only NET_BIND_SERVICE, and restricts volume types, runAsUser 0 and OS-specific fields; real admission also handles exemptions, API versions and controller-generated Pods. Verify enforcement with Pod Security Admission in a disposable cluster.

Your next task: Which admission mechanism evaluates generated Pods and ephemeral-container updates in your cluster?

Kubernetes Pod Security Standards

Related guide: Run Kubernetes workloads with only the privileges they need