AID-I-001.002: MicroVM & Low-Level Sandboxing
Pillars: infra
Lifecycle: operation
Scope boundary
Owns stronger-than-container execution isolation through microVMs, user-space kernels, WASM capability runtimes, or OS sandbox primitives. It defines isolation strength and permitted host interaction, but not per-invocation freshness, deterministic teardown, or artifact-analysis verdicts.
AID-I-001.001: AID-I-001.002 provides a stronger kernel or hardware isolation boundary; AID-I-001.001 uses conventional shared-kernel containers. Use the container control when its threat model is sufficient, and this control when shared-kernel escape or hostile code requires a stronger boundary.
AID-I-001.003: AID-I-001.002 selects and verifies runtime isolation strength; AID-I-001.003 creates a fresh sandbox for one tool invocation and proves teardown. A microVM can be long-lived, and a single-use sandbox can consume different approved runtime profiles. Isolation strength and one-shot lifecycle are separate controls.
Warning
Low to Medium on Startup Time & CPU/Memory Overhead
Stronger isolation technologies like gVisor or Firecracker impose a greater performance penalty than standard containers.
CPU Overhead: Can introduce a 5% to 15% CPU performance overhead compared to running in a standard container.
Startup Time: Adds a small but measurable delay, typically 5ms to 50ms of additional startup time per instance.
Implementation guidance
- AID-I-001.002-G001: Use a stronger-than-container sandbox runtime for high-risk untrusted workloads, selecting either a hardware-virtualized microVM runtime or a userspace-kernel sandbox.
- AID-I-001.002-G002: Define strict seccomp-bpf profiles to whitelist only necessary system calls for model inference.
- AID-I-001.002-G003: Utilize WebAssembly (WASM) runtimes to run AI models in a high-performance, secure sandbox.
- AID-I-001.002-G004: Layer OS sandbox primitives beneath microVM or user-space-kernel isolation for local agent and tool runners.
AID-I-001.002-G001
Concept
runtimeClassName selects a CRI handler, but reading that PodSpec field back proves only the request. A production gate must also bind the running Pod UID and node to a fresh, signed node/CRI attestation showing which runtime configuration handled the sandbox. Kubernetes admission and the node attestor remain external enforcement dependencies.
Render the workload from a signed runtime-selection profile
The profile supplies namespace, Pod name, digest-pinned image, RuntimeClass name and expected immutable handler, expected runtime type, runtime-engine digest, node runtime-configuration digest, policy digest, and the attestation validity rule. The cluster provisioner owns RuntimeClass and node configuration; application CI verifies them but does not redefine them.
# File: k8s/deploy_untrusted_runner.sh
#!/usr/bin/env bash
set -euo pipefail
umask 077
root="$(mktemp -d)"
trap 'rm -rf -- "$root"' EXIT
install -m 0400 -- "$RUNTIME_SELECTION_PROFILE" "$root/profile.json"
install -m 0400 -- "$RUNTIME_SELECTION_PROFILE_BUNDLE" "$root/profile.sigstore.json"
cosign verify-blob --key "$RUNTIME_SELECTION_PROFILE_VERIFY_KEY" --bundle "$root/profile.sigstore.json" "$root/profile.json" >/dev/null
jq -e '
.schema_version == "aidefend.runtime-selection-profile.v1"
and (.policy_sha256 | type == "string" and test("^[0-9a-f]{64}$"))
and (.namespace | type == "string" and length > 0)
and (.pod_name | type == "string" and length > 0)
and (.runtime_class_name | type == "string" and length > 0)
and (.runtime_handler | type == "string" and length > 0)
and (.runtime_type | type == "string" and length > 0)
and (.runtime_engine_sha256 | type == "string" and test("^[0-9a-f]{64}$"))
and (.node_runtime_config_sha256 | type == "string" and test("^[0-9a-f]{64}$"))
and (.image | type == "string" and test("@sha256:[0-9a-f]{64}$"))
and (.attestation_max_age_seconds | type == "number" and floor == . and . > 0)
and (.pod_ready_timeout_seconds | type == "number" and floor == . and . > 0)
and (.admission_denial_marker | type == "string" and length > 0 and length <= 256)
' "$root/profile.json" >/dev/null
namespace="$(jq -r .namespace "$root/profile.json")"
pod_name="$(jq -r .pod_name "$root/profile.json")"
runtime_class="$(jq -r .runtime_class_name "$root/profile.json")"
expected_handler="$(jq -r .runtime_handler "$root/profile.json")"
expected_runtime_type="$(jq -r .runtime_type "$root/profile.json")"
expected_runtime_engine_sha256="$(jq -r .runtime_engine_sha256 "$root/profile.json")"
expected_node_runtime_config_sha256="$(jq -r .node_runtime_config_sha256 "$root/profile.json")"
image="$(jq -r .image "$root/profile.json")"
policy_sha256="$(jq -r .policy_sha256 "$root/profile.json")"
attestation_max_age="$(jq -r .attestation_max_age_seconds "$root/profile.json")"
pod_ready_timeout="$(jq -r .pod_ready_timeout_seconds "$root/profile.json")"
admission_denial_marker="$(jq -r .admission_denial_marker "$root/profile.json")"
observed_handler="$(kubectl get runtimeclass "$runtime_class" -o json | jq -r .handler)"
[[ "$observed_handler" == "$expected_handler" ]] || {
echo "RuntimeClass handler differs from signed profile" >&2
exit 1
}
jq -n --arg namespace "$namespace" --arg name "$pod_name" --arg runtime_class "$runtime_class" --arg image "$image" --arg policy_sha256 "$policy_sha256" '{
apiVersion:"v1", kind:"Pod",
metadata:{
namespace:$namespace, name:$name,
labels:{"aidefend.io/sandbox-required":"true"},
annotations:{"aidefend.io/runtime-policy-sha256":$policy_sha256}
},
spec:{
runtimeClassName:$runtime_class,
automountServiceAccountToken:false,
restartPolicy:"Never",
containers:[{
name:"runner", image:$image,
securityContext:{
allowPrivilegeEscalation:false,
readOnlyRootFilesystem:true,
capabilities:{drop:["ALL"]}
}
}]
}
}' > "$root/pod.json"
kubectl apply --server-side --field-manager=aidefend-runtime -f "$root/pod.json"
kubectl wait -n "$namespace" --for=condition=Ready "pod/$pod_name" --timeout="${pod_ready_timeout}s"
kubectl get pod -n "$namespace" "$pod_name" -o json > "$root/pod-readback.json"
jq -e --arg runtime_class "$runtime_class" --arg policy_sha256 "$policy_sha256" --arg image_digest "${image##*@}" '
.spec.runtimeClassName == $runtime_class
and .metadata.annotations["aidefend.io/runtime-policy-sha256"] == $policy_sha256
and .status.phase == "Running"
and (.metadata.uid | type == "string" and length > 0)
and (.spec.nodeName | type == "string" and length > 0)
and ([.status.containerStatuses[] | select(.name == "runner")] | length == 1)
and (.status.containerStatuses[] | select(.name == "runner") | .imageID | endswith($image_digest))
' "$root/pod-readback.json" >/dev/null
Require a node/CRI attestation and a no-fallback admission test
The node-attestor adapter runs outside the workload identity and queries the node's CRI/provider measurement path. It emits a signed JSON receipt containing exactly the Pod UID, Kubernetes node UID, RuntimeClass name, requested handler, measured runtime type/engine digest, node runtime-config digest, image digest, policy digest, measurement time, and expiry. The adapter may use crictl inspectp or a managed-provider equivalent; a Pod label or application self-report is not acceptable.
# The platform-specific node attestor writes these two files.
install -m 0400 -- "$NODE_RUNTIME_ATTESTATION" "$root/node-attestation.json"
install -m 0400 -- "$NODE_RUNTIME_ATTESTATION_BUNDLE" "$root/node-attestation.sigstore.json"
cosign verify-blob --key "$NODE_RUNTIME_ATTESTOR_VERIFY_KEY" --bundle "$root/node-attestation.sigstore.json" "$root/node-attestation.json" >/dev/null
pod_uid="$(jq -r .metadata.uid "$root/pod-readback.json")"
node_name="$(jq -r .spec.nodeName "$root/pod-readback.json")"
node_uid="$(kubectl get node "$node_name" -o json | jq -r .metadata.uid)"
now="$(date +%s)"
min_measured_at="$((now - attestation_max_age))"
jq -e --arg pod_uid "$pod_uid" --arg node_uid "$node_uid" --arg runtime_class "$runtime_class" --arg handler "$expected_handler" --arg runtime_type "$expected_runtime_type" --arg runtime_engine_sha256 "$expected_runtime_engine_sha256" --arg node_runtime_config_sha256 "$expected_node_runtime_config_sha256" --arg policy_sha256 "$policy_sha256" --arg image_digest "${image##*@}" --argjson now "$now" --argjson min_measured_at "$min_measured_at" '
(keys | sort) == (["expires_at_unix","image_digest","measured_at_unix","node_runtime_config_sha256","node_uid","pod_uid","policy_sha256","runtime_class_name","runtime_engine_sha256","runtime_handler","runtime_type","schema_version"] | sort)
and .schema_version == "aidefend.node-runtime-attestation.v1"
and .pod_uid == $pod_uid
and .node_uid == $node_uid
and .runtime_class_name == $runtime_class
and .runtime_handler == $handler
and .policy_sha256 == $policy_sha256
and .image_digest == $image_digest
and .runtime_type == $runtime_type
and .runtime_engine_sha256 == $runtime_engine_sha256
and .node_runtime_config_sha256 == $node_runtime_config_sha256
and (.measured_at_unix | type == "number" and floor == . and . >= $min_measured_at and . <= $now)
and (.expires_at_unix | type == "number" and floor == . and . > $now)
' "$root/node-attestation.json" >/dev/null
jq '.metadata.generateName = (.metadata.name + "-negative-") | del(.metadata.name, .metadata.uid, .spec.runtimeClassName)' "$root/pod.json" > "$root/no-runtimeclass.json"
kubectl create --dry-run=client -f "$root/no-runtimeclass.json" >/dev/null
if kubectl create --dry-run=server -f "$root/no-runtimeclass.json" >/dev/null 2>"$root/admission-denial.txt"; then
echo "sandbox-required Pod was admitted without RuntimeClass" >&2
exit 1
fi
if ! grep -F -- "$admission_denial_marker" "$root/admission-denial.txt" >/dev/null; then
echo "negative admission test failed for an unrecognized reason" >&2
exit 1
fi
Action: Release only when the Pod is running with the signed image, the RuntimeClass handler matches, the attested runtime type, engine digest, and node configuration digest exactly match the signed profile, the independent attestation binds the exact Pod/node/runtime population and remains fresh under policy, and admission rejects omission. A declared field without runtime attestation is insufficient; a missing attestor or unsupported handler fails closed.
AID-I-001.002-G002
Concept:
A seccomp allowlist is deny-by-default only when defaultAction denies syscalls and the profile explicitly allows the deployment-specific set. A default-allow profile with a short denylist is useful defense in depth, but it is not a least-privilege allowlist. Build the allowlist from complete staging traces for the exact image and workload tests, review additions, and promote the profile with the image.
Step 1: Generate a reviewed deny-by-default profile
# File: tools/build_seccomp_profile.py
from __future__ import annotations
import hashlib
import json
import re
from pathlib import Path
OBSERVED = Path("artifacts/seccomp/observed-syscalls.txt")
REVIEWED_EXTRAS = Path("policy/seccomp/reviewed-extra-syscalls.txt")
OUTPUT = Path("artifacts/seccomp/inference-profile.json")
NAME = re.compile(r"^[a-z0-9_]+$")
DANGEROUS = {
"bpf", "kexec_load", "keyctl", "mount", "open_by_handle_at",
"perf_event_open", "ptrace", "reboot", "setns", "unshare",
}
def load_names(path: Path, *, allow_empty: bool = False) -> set[str]:
names = {
line.strip()
for line in path.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.lstrip().startswith("#")
}
if ((not names and not allow_empty)
or any(not NAME.fullmatch(name) for name in names)):
raise SystemExit(f"invalid or empty syscall inventory: {path}")
return names
allowed = load_names(OBSERVED) | load_names(REVIEWED_EXTRAS, allow_empty=True)
forbidden = sorted(allowed & DANGEROUS)
if forbidden:
raise SystemExit(f"dangerous syscalls require a separate exception: {forbidden}")
profile = {
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 1,
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [{"names": sorted(allowed), "action": "SCMP_ACT_ALLOW"}],
}
payload = (json.dumps(profile, sort_keys=True, indent=2) + "\n").encode("utf-8")
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
OUTPUT.write_bytes(payload)
OUTPUT.with_suffix(".json.sha256").write_text(
hashlib.sha256(payload).hexdigest() + "\n", encoding="ascii"
)The observed inventory must come from successful cold start, readiness/liveness, representative inference, model reload, telemetry, shutdown, and failure-path tests for the exact image digest. Treat the reviewed extras file as code-reviewed policy, not as an escape hatch.
Step 2: Install and bind the exact profile
# Node path: /var/lib/kubelet/seccomp/profiles/aidefend/inference-profile.json
# File: k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inference-api
namespace: ai-production
spec:
selector:
matchLabels:
app: inference-api
template:
metadata:
labels:
app: inference-api
spec:
automountServiceAccountToken: false
securityContext:
seccompProfile:
type: Localhost
localhostProfile: aidefend/inference-profile.json
containers:
- name: api
image: registry.example.com/ai/inference-api:2026.04.14
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]Verification
Admission must bind the profile digest to the exact image digest and reject nodes where the file is absent. Run the complete workload suite, then run a purpose-built negative probe that attempts a syscall such as unshare and require EPERM. Read back the pod's resolved seccomp profile and retain the profile bytes/digest, image digest, node rollout population, positive tests, and negative-probe result.
AID-I-001.002-G003
Concept:
Delivery level: reusable module. WASM isolation is practical when inference logic can be compiled and invoked through a strict host boundary. The host controls capabilities; the module gets none by default.
ABI smoke-test fixture
This tiny export is only a deterministic CI fixture for validating the host ABI and negative limit tests; the production model module is separately built, signed, and digest-bound.
// File: inference-engine/src/lib.rs
#[no_mangle]
pub extern "C" fn run_inference(input: i32) -> i32 {
input * 2
}Run with a capability-minimal Wasmtime host
The Linker is the capability boundary: the module only receives host functions, WASI handles, directories, environment variables, or stdio streams that you explicitly define. Validate requested imports before instantiation, enable fuel, and bound memory so a hostile module cannot silently gain filesystem/network access or consume unbounded resources.
# File: host_app/run_wasm.py
from __future__ import annotations
import hashlib
import hmac
from dataclasses import dataclass
from pathlib import Path
from wasmtime import Config, Engine, Linker, Module, Store, WasmtimeError
@dataclass(frozen=True)
class VerifiedWasmPolicy:
policy_sha256: str
module_sha256: str
max_fuel: int
max_memory_bytes: int
max_table_elements: int
allowed_imports: frozenset[tuple[str, str]]
required_exports: frozenset[str]
def run_verified_module(
module_path: Path,
policy: VerifiedWasmPolicy,
input_value: int,
) -> tuple[int, dict[str, object]]:
if min(policy.max_fuel, policy.max_memory_bytes, policy.max_table_elements) <= 0:
raise ValueError("verified WASM policy limits must be positive")
module_bytes = module_path.read_bytes()
observed_sha256 = "sha256:" + hashlib.sha256(module_bytes).hexdigest()
if not hmac.compare_digest(observed_sha256, policy.module_sha256):
raise PermissionError("WASM module digest does not match signed policy")
config = Config()
config.consume_fuel = True
engine = Engine(config)
module = Module(engine, module_bytes)
observed_imports = frozenset((item.module, item.name) for item in module.imports)
if observed_imports != policy.allowed_imports:
raise PermissionError("WASM import population differs from signed policy")
observed_exports = frozenset(item.name for item in module.exports)
if not policy.required_exports.issubset(observed_exports):
raise PermissionError("required WASM export is absent")
store = Store(engine)
store.set_fuel(policy.max_fuel)
store.set_limits(
memory_size=policy.max_memory_bytes,
table_elements=policy.max_table_elements,
memories=1,
tables=1,
instances=1,
)
linker = Linker(engine)
try:
instance = linker.instantiate(store, module)
run_inference = instance.exports(store)["run_inference"]
output = int(run_inference(store, input_value))
except (KeyError, TypeError, WasmtimeError) as exc:
raise RuntimeError("bounded WASM execution failed") from exc
return output, {
"policy_sha256": policy.policy_sha256,
"module_sha256": observed_sha256,
"imports": sorted([list(item) for item in observed_imports]),
"exports": sorted(observed_exports),
"fuel_remaining": store.get_fuel(),
}Action: Obtain VerifiedWasmPolicy only from a signature-verifying policy adapter, then execute the exact module bytes through this capability-minimal host. Any WASI import, host function, directory, environment variable, stdio stream, network adapter, or clock/random source must appear in the exact signed import set.
AID-I-001.002-G004
Concept:
MicroVMs and gVisor provide the main isolation boundary, but local agent execution often still needs an OS primitive that limits file writes, process visibility, and network access before the code reaches a managed cluster. Use Landlock or bubblewrap for Linux local execution. On macOS, prefer App Sandbox, managed VDI, or VM/container isolation for production; sandbox-exec/Seatbelt profiles are a deprecated command-line fallback suitable only for local smoke tests and must not be the sole production boundary. Treat network egress as the hardest part: outbound allowlists must be enforced outside the process as well, because application-level checks are easy to miss during redirects, package installation, browser prefetch, and helper subprocesses.
Linux example: run a local tool with bubblewrap and a read-only root
# File: sandbox/run_local_tool.sh
#!/usr/bin/env bash
set -euo pipefail
SANDBOX_ROOT="$(mktemp -d)"
trap 'rm -rf "$SANDBOX_ROOT"' EXIT
mkdir -p "$SANDBOX_ROOT"/{work,tmp,home}
cp "$1" "$SANDBOX_ROOT/work/tool.py"
bwrap --die-with-parent --unshare-all --new-session --ro-bind /usr /usr --ro-bind /lib /lib --ro-bind /lib64 /lib64 --ro-bind /bin /bin --proc /proc --dev /dev --tmpfs /tmp --dir /run --chdir /work --setenv HOME /home/sandbox --setenv PYTHONNOUSERSITE 1 --bind "$SANDBOX_ROOT/work" /work --bind "$SANDBOX_ROOT/home" /home/sandbox --unshare-net /usr/bin/python3 /work/tool.pyWhen an in-process Linux runner uses Landlock, bind a specific reviewed library/version and test its actual kernel ABI; do not copy a binding-shaped snippet whose API or handled access rights are unverified. The authoritative production boundary remains the outer microVM/userspace-kernel runtime plus external egress enforcement.
macOS deprecated fallback example: Seatbelt profile for local smoke tests only
; File: sandbox/tool.sb
(version 1)
(deny default)
(allow process-exec)
(allow file-read* (subpath "/usr") (subpath "/bin") (subpath "/System"))
(allow file-read* file-write* (subpath "/tmp/aidefend-tool-work"))
(deny network*)sandbox-exec -f sandbox/tool.sb /usr/bin/python3 /tmp/aidefend-tool-work/tool.pyAction: Use OS sandbox primitives for local development, self-hosted tool workers, and CI smoke tests, but treat macOS sandbox-exec as deprecated and non-authoritative. Production macOS desktop/app workloads should use App Sandbox entitlement boundaries, managed VDI, or VM/container isolation, and high-risk production invocations still belong in AID-I-001.003 single-use sandboxes with network egress enforced by policy.
Independently verify isolation
Population: enumerate every governed runner, invocation, host/kernel build, outer runtime, sandbox policy, workspace, child process, mount, and credential/network capability; incomplete population coverage is never PASS.
Open-source tools
- Kata Containers
- Firecracker
- gVisor
- libseccomp
- Wasmtime
- Wasmer
- Cilium Tetragon
- Cloud Hypervisor
- bubblewrap
- QEMU
- E2B (Firecracker microVM sandbox infrastructure)
Commercial / hosted tools
- AWS Lambda
- Google Cloud Run
- Azure Container Instances
- Red Hat OpenShift sandboxed containers
- Fastly Compute
Threat mappings
MITRE ATLAS
- AML.T0011 User Execution
- AML.T0018 Manipulate AI Model
- AML.T0011.000 User Execution: Unsafe AI Artifacts
- AML.T0053 AI Agent Tool Invocation
- AML.T0072 Cyber Communication Channel (microVM network policy constrains callback channels from untrusted code)
- AML.T0089 Enterprise Environment Discovery (guest-kernel isolation limits enumeration of host processes, configuration, and network state)
- AML.T0050 Command and Scripting Interpreter
- AML.T0018.002 Manipulate AI Model: Embed Malware
- AML.T0105 Escape to Host
- AML.T0106 Exploitation for Credential Access
- AML.T0011.002 User Execution: Poisoned AI Agent Tool
MAESTRO
- Compromised Container Images (L4)
- Lateral Movement (Cross-Layer)
- Agent Tool Misuse (L7)
- Privilege Escalation (Cross-Layer)
- Lateral Movement (L4) (microVM isolation prevents lateral movement)
OWASP LLM Top 10 2026
- LLM03:2026 Excessive Agency (strong sandbox boundaries confine over-privileged or compromised tool execution)
- LLM04:2026 Supply Chain (low-level isolation contains malicious third-party model or loader execution)
- LLM05:2026 Data and Model Poisoning (sandbox isolation limits poisoned models from reaching external tools and systems)
- LLM10:2026 Improper Output Handling (low-level sandboxing contains generated code after unsafe model output reaches execution)
OWASP ML Top 10 2023
- ML06:2023 AI Supply Chain Attacks
OWASP Top 10 for Agentic Applications 2026
- ASI05:2026 Unexpected Code Execution (RCE)
- ASI02:2026 Tool Misuse and Exploitation
- ASI04:2026 Agentic Supply Chain Vulnerabilities (stronger isolation for compromised components)
- ASI10:2026 Rogue Agents
NIST Adversarial Machine Learning 2025
- N/A
Cisco Integrated AI Security and Safety Framework
- AISubtech-12.1.3 Unsafe System / Browser / File Execution (untrusted agent code and tool execution are confined to the verified sandbox)
- AISubtech-13.1.1 Compute Exhaustion (WASM fuel and memory limits bound hostile-module resource consumption)
- AISubtech-13.1.2 Memory Flooding (WASM fuel and memory limits bound hostile-module resource consumption)
- AISubtech-13.2.1 Service Misuse for Cost Inflation (WASM fuel and memory limits bound hostile-module resource consumption)
- AISubtech-14.1.2 Insufficient Access Controls (verified runtime and host-capability boundaries constrain infrastructure access)
- AISubtech-8.2.3 Data Exfiltration via Agent Tooling (tool-worker filesystem capabilities and outbound network access are restricted)
- AISubtech-9.1.1 Code Execution (untrusted agent code and tool execution are confined to the verified sandbox)
- AISubtech-9.1.2 Unauthorized or Unsolicited System Access (untrusted agent code and tool execution are confined to the verified sandbox)
- AISubtech-9.1.3 Unauthorized or Unsolicited Network Access (untrusted agent code and tool execution are confined to the verified sandbox)
- AITech-12.1 Tool Exploitation (untrusted agent code and tool execution are confined to the verified sandbox)
- AITech-13.1 Disruption of Availability (WASM fuel and memory limits bound hostile-module resource consumption)
- AITech-13.2 Cost Harvesting / Repurposing (WASM fuel and memory limits bound hostile-module resource consumption)
- AITech-14.1 Unauthorized Access (verified runtime and host-capability boundaries constrain infrastructure access)
- AITech-8.2 Data Exfiltration / Exposure (tool-worker filesystem capabilities and outbound network access are restricted)
- AITech-9.1 Model or Agentic System Manipulation (untrusted agent code and tool execution are confined to the verified sandbox)
Google Secure AI Framework 2.0 - Risks
- IIC: Insecure Integrated Component (hardware-level isolation contains compromised components)
- RA: Rogue Actions (microVM isolation prevents rogue actions from escaping to host)
Databricks AI Security Framework 3.0
- Agents - Core 13.11: Unexpected RCE and Code Attacks
- Model Serving - Inference requests 9.3: Model breakout (microVM prevents model breakout to host)
- Algorithms 5.4: Malicious libraries (microVM isolation contains malicious library execution)
- Platform 12.4: Unauthorized privileged access