Entry-Point Dynamic Analysis
When a running container is available — for example, during runtime posture checks — the Stella Ops scanner augments its static entry-point inference with live process signals. This guide describes the Observational Exec Graph (OEG) that powers that dynamic mode: how it is captured, how steady-state processes are selected, and how its output merges with the static pipeline.
It is the dynamic counterpart to Entry-Point Static Analysis; both feed the same Runtime Detector Overview classification stage.
1) Goals
- Capture the actual process tree and exec lineage after the container starts.
- Identify steady-state processes (long-lived, listening, non-wrapper) even when supervision stacks are present.
- Feed the same reduction and runtime-classification pipeline as the static analyser.
2) Observational Exec Graph (OEG)
2.1 Data sources
- Tracepoints / eBPF:
sched_process_exec,sched_process_fork/clone, and corresponding exit events give us pid, ppid, namespace, binary path, and argv snapshots with minimal overhead. - /proc sampling: for each tracked PID, capture
/proc/<pid>/{exe,cmdline,cwd}and file descriptors (especially listening sockets). - Namespace mapping: normalise host PIDs to container PIDs (
NStgid) so the graph is stable across runtimes.
2.2 Graph model
public sealed record ExecNode(int HostPid, int NsPid, int Ppid, string Exe, string[] Argv, long StartTicks);
public sealed record ExecEdge(int ParentHostPid, int ChildHostPid, string Kind); // "clone" | "exec"
- Nodes represent
exec()events (post-exec image) and contain the final argv. - Edges labelled
clonecapture forks;execedges show program replacements.
2.3 Steady-state candidate selection
For each node compute features:
| Feature | Rationale |
|---|---|
| Lifetime (until sampling end) | Long-lived processes are more likely to be the real workload. |
| Additional execs downstream | Zero execs after start implies terminal. |
| Listening sockets | Owning LISTEN sockets strongly suggests a server. |
| Wrapper catalogue hit | Mark nodes that match known shims (tini, gosu, supervisord, etc.). |
| Children fan-out | Supervisors spawn multiple children and remain parents. |
Feed these into a scoring function; retain Top‑K candidates (usually 1–3) along with evidence.
3) Integration with static pipeline
- For each steady-state candidate, snapshot the command/argv and normalise via
ResolvedCommand(as in static mode). - Run wrapper reduction and ShellFlow analysis if the candidate is a script.
- Invoke runtime detectors to classify the binary.
- Merge dynamic evidence with static evidence. Conflicts drop confidence or trigger the “supervisor” classification.
4) Supervisors & multi-service containers
Some images (e.g., supervisord, s6, runit) intentionally start multiple long-lived processes. Handle them as follows:
- Detect supervisor binaries from the wrapper catalogue.
- Analyse their configuration (
/etc/supervisord.conf,/etc/services.d/*, etc.) to enumerate child services statically. - Emit multiple
TerminalProcessentries with individual confidence scores but mark the parent astype = supervisor.
5) Operational hints
- Sampling window: 1–3 seconds after start is usually sufficient; extend in debug mode.
- Overhead: prefer eBPF/tracepoints; fall back to periodic
/procwalks when instrumentation isn’t available. - Security: honour namespace boundaries; never inspect processes outside the target container’s cgroup/namespace.
- Failure mode: if dynamic capture fails, fall back to static mode and flag evidence accordingly (
"Dynamic capture unavailable").
6) Deliverables
The dynamic reducer returns an EntryTraceResult populated with:
ExecGraphcontaining nodes and edges for audit/debug.Terminalslisting steady-state processes (possibly multiple).Evidencestrings referencing dynamic signals ("pid 47 listening on 0.0.0.0:8080","wrapper tini collapsed into /usr/local/bin/python").
Downstream modules (Policy, Vuln Explorer, Export Center) treat the result identically to static scans, enabling easy comparison between build-time and runtime observations.
7) Related
- Entry-Point Static Analysis — the build-time counterpart that produces the predictions this mode reconciles against.
- Runtime Detector Overview — the shared classification stage both modes feed.
- Language heuristics: the
entrypoint-lang-*.mdfamily (linked from the overview).
