Skip to content

Protection Score Reference

The protection score is a numeric measure of which defense mechanisms are active for a CloudTaser-protected process. The maximum score is 115 points across 12 checks. This page documents every check, its point value, what it proves, and how to enable it.


Score Breakdown

Check Points What It Proves How to Enable
memfd_secret 15 Secret pages physically removed from kernel direct map Automatic (requires Linux 5.14+ kernel)
mlock 10 Secret pages pinned in RAM, cannot be swapped to disk Automatic
core_dump_exclusion 5 Secret pages excluded from core dumps via MADV_DONTDUMP Automatic
dumpable_disabled 5 Process marked non-dumpable via PR_SET_DUMPABLE(0); /proc access restricted, ptrace blocked Automatic
token_protected 10 Vault authentication token stored in protected memory (not on disk or in env) Automatic
environ_scrubbed 5 Secret environment variables scrubbed from the wrapper process itself Automatic
getenv_interposer 10 LD_PRELOAD interposer blocks getenv() from returning secrets on the heap Use a glibc-based container image (not Alpine/musl)
ebpf_agent_connected 10 eBPF enforcement agent is active and monitoring this process Add cloudtaser.io/ebpf: "true" annotation to the pod
cpu_mitigations 5 Spectre/Meltdown hardware mitigations active Automatic on modern CPUs
ebpf_enforce_mode 15 eBPF agent running in blocking mode (not just monitoring) Deploy eBPF daemonset with enforceMode: true
ebpf_kprobes 15 Synchronous syscall blocking via kprobe override Ubuntu nodes with CONFIG_BPF_KPROBE_OVERRIDE=y
confidential_vm 10 Hardware memory encryption (AMD SEV-SNP, Intel TDX) active GKE: --enable-confidential-nodes with N2D machine type

Maximum score: 115 points


Checks Explained

memfd_secret (15 points)

The highest-value automatic check. When the kernel supports memfd_secret (Linux 5.14+), the wrapper stores secrets in memory pages that are physically removed from the kernel's direct map. This means even a root attacker with kernel module access cannot read the secret pages through the direct map -- they are simply not there.

Fails when: The kernel version is below 5.14, or CONFIG_SECRETMEM is not set.

mlock (10 points)

Secrets are pinned in physical RAM using mlock(). This prevents the kernel from swapping secret pages to disk, where they could be recovered from swap partitions or swap files.

Fails when: CAP_IPC_LOCK is not available and the RLIMIT_MEMLOCK limit is too low. Most Kubernetes runtimes grant sufficient limits by default.

core_dump_exclusion (5 points)

Secret pages are marked with MADV_DONTDUMP, which excludes them from core dump files. If the application crashes, the core dump will not contain secret values.

Fails when: The madvise syscall fails (extremely rare).

dumpable_disabled (5 points)

The wrapper calls prctl(PR_SET_DUMPABLE, 0) to mark itself as non-dumpable. This restricts /proc/pid/mem access and blocks ptrace attach from non-root processes. Combined with the eBPF agent, this closes the /proc attack surface.

Fails when: The prctl syscall fails (extremely rare).

token_protected (10 points)

The Vault authentication token is stored in the same protected memory as the secrets themselves (memfd_secret when available, mlock-ed pages otherwise). The token never appears in environment variables, files, or unprotected memory.

Fails when: memfd_secret is not available and mlock also fails.

environ_scrubbed (5 points)

After the wrapper passes secret environment variables to the child process, it scrubs them from its own /proc/pid/environ. An attacker inspecting the wrapper's environment will not find secret values.

Fails when: The wrapper cannot modify its own /proc/self/environ mapping (extremely rare).

getenv_interposer (10 points)

The wrapper injects an LD_PRELOAD library that intercepts getenv() calls in the child process. When the application calls getenv("PGPASSWORD"), the interposer returns a pointer to the memfd_secret-backed memory instead of a heap-allocated copy. This prevents secrets from leaking onto the application's heap.

Fails when: The container uses musl libc (Alpine) or statically linked binaries, which do not support LD_PRELOAD. Switch to a Debian, Ubuntu, or glibc-based image to enable this check.

ebpf_agent_connected (10 points)

The eBPF enforcement agent running on the node has registered this process for protection. The agent monitors all relevant syscalls and will block or kill any process attempting to read the protected process's memory, environment, or file descriptors.

Fails when: The eBPF daemonset is not deployed, or the pod does not have the cloudtaser.io/ebpf: "true" annotation.

cpu_mitigations (5 points)

The kernel has Spectre and Meltdown mitigations active. These hardware mitigations prevent speculative execution side-channel attacks that could leak secret values across process boundaries.

Fails when: The kernel is booted with mitigations=off, or the CPU does not support the required microcode updates. Modern cloud provider kernels always have mitigations enabled.

ebpf_enforce_mode (15 points)

The eBPF agent is running in enforce (blocking) mode, not just monitoring mode. In enforce mode, the agent actively blocks syscalls that would leak secrets (returning EPERM or overriding the syscall to return an error). In monitoring mode, the agent only logs violations without blocking them.

Fails when: The eBPF daemonset is deployed with enforceMode: false (monitoring only).

ebpf_kprobes (15 points)

The eBPF agent is using kprobe-based synchronous syscall blocking. With CONFIG_BPF_KPROBE_OVERRIDE=y, the agent can prevent a syscall from executing by overriding its return value before it completes. Without this kernel option, the agent falls back to reactive kill (SIGKILL after tracepoint detection), which has a theoretical window between syscall execution and process termination.

Fails when: The kernel does not have CONFIG_BPF_KPROBE_OVERRIDE=y. This is the case on GKE COS nodes, EKS Bottlerocket, AKS Azure Linux, and RHEL 8. Use Ubuntu nodes for this check.

confidential_vm (10 points)

The node is running on Confidential Computing hardware (AMD SEV-SNP, Intel TDX, or ARM CCA). Hardware memory encryption ensures that the hypervisor and cloud provider cannot read VM memory, even with physical access to the host machine.

Fails when: The node is not a Confidential Computing instance. On GKE, enable with --enable-confidential-nodes and --machine-type n2d-standard-2.


Score Interpretation

Score Range Assessment Recommendation
105--115 Full protection All critical defenses active. Suitable for regulated production workloads.
80--104 Strong protection Most defenses active. One or two non-critical checks missing. Review which and evaluate risk.
55--79 Partial protection Key mechanisms missing. Not recommended for regulated workloads without a documented risk acceptance.
Below 55 Insufficient Multiple critical mechanisms inactive. Investigate immediately.

A score below 55 means secrets are vulnerable to a determined attacker

Without memfd_secret (15 points), ebpf_enforce_mode (15 points), and ebpf_kprobes (15 points), a determined root attacker can read process memory through standard kernel interfaces. These are the three most critical checks.


Achieving Maximum Score by Platform

Platform Max Score Missing Checks How to Get 115
GKE Ubuntu + Confidential Nodes 115 None --image-type UBUNTU_CONTAINERD --enable-confidential-nodes --machine-type n2d-standard-2
GKE Ubuntu (non-confidential) 105 confidential_vm Add --enable-confidential-nodes
GKE COS + Confidential Nodes 100 ebpf_kprobes Switch to --image-type UBUNTU_CONTAINERD
GKE COS (non-confidential) 90 ebpf_kprobes, confidential_vm Switch to Ubuntu + Confidential
EKS Ubuntu 105 confidential_vm No AWS equivalent yet
AKS Ubuntu 22.04 105 confidential_vm Use DCasv5/ECasv5 Confidential VMs
AKS Azure Linux 3.0 90 ebpf_kprobes, confidential_vm Switch to Ubuntu node image
GKE Autopilot 65 ebpf_* (3 checks), confidential_vm Use GKE Standard

Checking the Score

Wrapper Logs

The wrapper logs the protection score at startup:

[cloudtaser-wrapper] Protection score: 115/115
[cloudtaser-wrapper]   memfd_secret:          OK  (+15)
[cloudtaser-wrapper]   mlock:                 OK  (+10)
[cloudtaser-wrapper]   core_dump_exclusion:   OK  (+5)
[cloudtaser-wrapper]   dumpable_disabled:     OK  (+5)
[cloudtaser-wrapper]   token_protected:       OK  (+10)
[cloudtaser-wrapper]   environ_scrubbed:      OK  (+5)
[cloudtaser-wrapper]   getenv_interposer:     OK  (+10)
[cloudtaser-wrapper]   ebpf_agent_connected:  OK  (+10)
[cloudtaser-wrapper]   cpu_mitigations:       OK  (+5)
[cloudtaser-wrapper]   ebpf_enforce_mode:     OK  (+15)
[cloudtaser-wrapper]   ebpf_kprobes:          OK  (+15)
[cloudtaser-wrapper]   confidential_vm:       OK  (+10)

CLI Status Command

cloudtaser target status --pod my-app-7d8f9c6b4-xk2mn --namespace production

Kubernetes Events

The wrapper emits Kubernetes events on the pod for score changes:

Events:
  Type     Reason              Message
  ----     ------              -------
  Normal   ProtectionActive    Protection score: 115/115 (all defenses active)
  Warning  ProtectionDegraded  Protection score: 90/115 (ebpf_kprobes, confidential_vm unavailable)

Prometheus Metrics

# HELP cloudtaser_protection_score Current protection score
# TYPE cloudtaser_protection_score gauge
cloudtaser_protection_score{pod="my-app-7d8f9c6b4-xk2mn",namespace="production"} 115

# HELP cloudtaser_protection_max Maximum possible protection score
# TYPE cloudtaser_protection_max gauge
cloudtaser_protection_max{pod="my-app-7d8f9c6b4-xk2mn",namespace="production"} 115

Enforcing Minimum Scores

Use the CLOUDTASER_MIN_PROTECTION_SCORE environment variable to prevent the wrapper from starting if the score is too low:

env:
  - name: CLOUDTASER_MIN_PROTECTION_SCORE
    value: "80"
Environment Recommended Minimum Rationale
Production (regulated) 105 All software protections active
Production (general) 80 Core protections with eBPF enforcement
Staging 55 Allow testing without full enforcement
Development 0 No enforcement