Under an unprivileged account, how can a process still gain privilege when it executes another program?
answer
- the id binds the process, not its programs
- a program file can carry its own identity
- one step back up the chain
- inherited by children, sticky once set
- cannot be cleared from inside
basics
~20 sImages can ship program files marked to run with their owner's identity or extra powers rather than the caller's, so executing one raises privilege even from an unprivileged account. A declaration that forbids any privilege gain at exec blocks that, permanently and for every child.
solid answer
~50 sAn unprivileged id constrains the process you started, not every program it might run. A filesystem can mark a program file so that executing it grants the caller the file owner's identity or a specific extra power - the mechanism that lets ordinary accounts run a small number of privileged utilities on a normal host. If such a file is in the image, a compromised unprivileged process can execute it and come out with more than it had. The hardening is a one-line declaration that forbids privilege gain at exec: the kernel then refuses any elevation for that process and, importantly, for everything it starts, and the setting cannot be undone from inside. The cost is that any legitimate helper relying on that marking stops working, which in a container image is usually a sign it should not be there. The complementary fix is to build images with no such files at all.
go deeper
Know that declaring an unprivileged id fixes who the process is, and that a program it executes can, in principle, run with more privilege than the caller had.
Explain the mechanism: a program file marked to run with its owner's identity or an extra power, and a spec flag that makes the kernel decline that elevation.
Place it in the escalation chain and name its three properties - kernel-enforced at every execution, inherited by children, irreversible from inside - plus the helper it typically breaks.
Decide how the estate gets it: base images built without such files, a build-time check for reintroduction, and admission refusing specs that omit the flag.
## The gap an unprivileged id leaves Declaring an unprivileged numeric id fixes the identity of the process the runtime starts. It does not say anything about the identity of programs that process goes on to execute, and that distinction is where the last gap in start-time hardening lives. Filesystems can mark a program file so that running it does not run as the caller. Two variants matter: - **Run as the file's owner rather than the caller.** A process running as id `10001` executes the file and the new program runs as the owner - id `0` if the build installed it. - **Grant a named extra power on execution.** The program starts holding one specific privileged capability that the caller did not have, without changing identity. On a general-purpose host this is a deliberate, useful feature: it is how an ordinary account changes its own password or runs a diagnostic that needs a privileged socket. Inside a workload image it is almost always residue - a package installed for one binary dragged in a handful of marked files nobody looked at. ## Why this matters after a compromise Put it in the chain an attacker actually walks. Code execution as an unprivileged id, in a container with a read-only root filesystem and an empty privilege set, is a poor position: nothing to write, no powers to use. But if the image ships one marked program file, executing it is a single step that restores identity or a power, and the rest of the hardening was built on the assumption that the process holds neither. The severity is not that the marked file is dangerous in itself; it is that it converts a contained compromise back into a privileged one **inside** the container, which is where the remaining boundary weaknesses become worth something. ## What the declaration does The spec can carry a flag that forbids a process from gaining privilege when it executes another program. Once set, three properties make it unusually valuable for its size: 1. **It is enforced by the kernel at every execution**, not by a scanner that ran at build time and may have missed a file. 2. **It is inherited by every child process** the workload starts, so a wrapper script, a spawned helper and anything they start are all covered. 3. **It cannot be removed from inside.** A process that has it cannot clear it for itself or its children, so a compromised process cannot simply turn it off before it starts the marked program. The practical effect is that a marked file still executes - it just executes as the caller, with the caller's powers, exactly as an unmarked one would. Nothing crashes the boundary; the elevation is silently declined. ## What it costs - **Any legitimate helper relying on the marking stops working.** In a workload image that is usually an argument for removing the helper, not for removing the flag. - **The failure is confusing the first time.** The program runs, and then fails at the specific operation that needed the privilege it did not get, which can look like an unrelated bug some way into the work. - **A supervisor that starts privileged and drops down** is incompatible with this shape in general. The container-native answer is to start as the target id directly and skip the supervisor. ## Defence in layers, in order | layer | what it does | what it misses on its own | |---|---|---| | build without marked files | removes the mechanism entirely | a later base-image update can reintroduce one | | scan the image for marked files | catches reintroduction at build time | only as current as the last scan | | forbid privilege gain at exec | declines the elevation at every execution | the marked file is still present in the image | | refuse specs lacking the flag at admission | makes it uniform across an estate | nothing, for this specific gap | They compose deliberately: the build removes the mechanism, the flag makes its reintroduction harmless, and the gate makes the flag non-optional. ## Why this is a differentiator rather than a basic Most candidates get as far as the unprivileged account and the read-only root filesystem, because those are visible: something breaks and you fix it. This one breaks nothing in a well-built image, so it is never forced on anyone's attention, and it defends a step in an escalation chain rather than an obvious asset. Naming it - and being able to say that it is inherited, kernel-enforced and irreversible from inside - is a reasonable signal that the candidate has hardened workloads rather than read a checklist.
- If the image contains no such marked files, is the flag redundant?Not quite. It costs nothing, and it holds when the assumption stops being true - a base-image update, a new package, a layer added by another team. A scan tells you about the image you built today; the declaration keeps the guarantee for every image that spec ever runs, which is the version that survives contact with a real pipeline.
- What is the first symptom when this breaks something legitimate?The program starts normally and then fails at the one operation that needed the privilege, often well into its work and with an error naming that operation rather than the execution. Look for a helper in the image that is marked to run as its owner. The usual resolution is to remove the helper or replace it with something that does not need the elevation.
- Does this flag replace dropping the default privilege set?No - they cover different moments. Dropping the set empties what the process holds when it starts; this flag stops it acquiring more when it executes something. A workload with an empty set but no such flag can execute a marked file and pick a power back up, and one with the flag but a full set never needed to.
saying these in an interview costs you the question
- An unprivileged account makes privilege gain at exec impossible.
- The flag stops the process executing other programs entirely.
- It applies only to the first process, not to its children.
- A compromised process can clear the flag before executing.
- Scanning the image at build time makes the declaration unnecessary.