Ten detection layers
What the probe looks at, layer by layer
Each layer is a set of templates you can run on its own. A template declares inputs, steps, checks, findings and artifacts; the probe executes it and returns evidence.
The ten layers
| Layer | What you can do | Representative templates |
|---|---|---|
| 1Architecture | Audit rail and multi-plane alignment, PD-split KV channels, IMEX domains, MoE/EP collectives, long-context KV lifetime and federation. | rail-mismatch-forcing, prefill-decode-kv-channel-unauth, nvlink-imex-isolation |
| 2Product / framework | Enumerate admin and control surfaces of vLLM, SGLang, TRL, verl, AReaL, SkyRL, OpenRLHF, slime, LLaMA-Factory, ms-swift, Megatron-LM, DeepSpeed, transformers, gateways and agent platforms. | vllm-plugin-auth-bypass, sglang-admin-failopen, verl-prime-code-exec |
| 3Component / operator | Inspect Ray and LWS control planes, GPU Operator and driver containers, DRA policy, CSI node plugins, BMC/Redfish and DPU offload. | ray-dashboard-job, gpu-operator-driver-audit, gpu-dra-mig-policy |
| 4Network / fabric | Test policy bypass on hostNetwork, SR-IOV and macvlan, dual CNI planes, IB subnet manager, RoCE PFC/ECN, SHARP, NCCL bootstrap and DNS. | multus-sriov-rdma-bypass, ib-sm-partition-audit, sharp-in-network-poison |
| 5Data / weights | Check checkpoint and optimizer shards, dataset pipelines, HF cache, weight buckets, model registries and KV/prefix caches. | checkpoint-shard-poison, skyrl-fetch-weights-traversal, model-registry-exposure |
| 6Tenant / isolation | Measure MIG and MPS residue, GPU pooling schedulers, cache_salt policy and routing metric leakage. | gpu-tenant-residue, hami-scheduler-auth-gap, cache-salt-policy-audit |
| 7Supply chain / identity | Verify trust_remote_code, revision pinning, attestation chains, SBOM, IRSA/workload identity, IMDS and credential exposure. | trust-remote-code-supply-chain, gpu-cc-attestation-chain, cloud-irsa-trust-wildcard |
| 8Cache security | Test cross-tenant prefix cache, semantic false hits, eviction residue, remote KV pools, EPP metrics and TTFT timing. | prefix-cache-cross-tenant-leak, remote-kv-pool-isolation, cache-timing-sidechannel |
| 9Cross-combination | Report findings that only exist when two or three components meet, once at the combination, with component notes folded in. | sglang-weight-exfil, imex-computedomain-gpu-memory-crossing, long-context-cache-leak |
| 10Defense bypass | Measure whether HIDS, runtime eBPF, admission, image scan, host agents, WAF and network flow visibility see benign authorized activity. | defense-bypass-elkeid, defense-bypass-falco, defense-bypass-admission |
Layer detail, detection points and evidence produced: DETECTION-LAYERS.md · PRODUCT.md
Platform capabilities
- One execution path. Foothold, Rust probe, framed channel, in-pod task, child probe, evidence.
- Probe trees. probe_id and parent_id; each child has its own token and a stricter budget; the tree limits nesting depth and concurrent child probes; cleanup is child-first.
- Agent runtime. A budgeted objective graph with decision trace, journal resume and zero-execution replay.
- Cross-cluster relay. The same framed protocol between clusters, with a completion proof.
- Evidence from the probe. Task results, step logs, artifacts, SHA-256 manifests, traffic tables and cleanup receipts.
- Rules you can replay. Admission, runtime and network packs with intercepted / detected / missed matrices.
- Report and console. Bilingual pentest and remediation reports, SARIF / OCSF / VEX export, local console.
One execution path
Three components, one probe tree
The controller never executes target-side logic. It authorizes, renders templates, enforces budgets and archives evidence. The probe is the only code that runs inside the Pod.
foothold ──▶ Rust probe ──▶ framed channel ──▶ in-pod task
│
├─▶ child probe ──▶ child probe
└─▶ evidence ──▶ report / rules / console
Three components
- Templates. template.json declares inputs, payloads, steps, computed state, checks, findings and artifacts.
- Probe. A static Rust binary speaks an HMAC-authenticated framed protocol and executes http, tcp, exec, fs, k8s, socks and spawn ops.
- Controller. Python enforces consent, scope, level, backup and audit, then folds probe evidence into findings.
Probe tree
Every probe has a probe_id and a parent_id. Children inherit the parent's read-only state, command allow-list and budget, and can only be stricter. Cleanup runs child-first, so no uncleaned child probe keeps a token alive.
Static Rust probe
One binary, 286 templates
The probe is one static musl binary per architecture, linux/amd64 and linux/arm64. Templates are JSON data.
Probe operations
| Operation | What it does |
|---|---|
collect | Host, Pod, process, network and Kubernetes context. |
exec | Run an allow-listed command with a bounded budget. |
audit-exec | Run a command and record the audit trail and timing. |
read-file | Read a file with size limits and a SHA-256 hash. |
list-files | List a directory tree with metadata. |
upload | Write a file after the authorization and write-permission checks. |
download | Stream a file back in chunks. |
spawn | Start a child probe with its own token and a stricter budget. |
dial | Open a TCP or UDP connection to an in-scope target. |
socks | Expose a loopback SOCKS5 listener for local tool compatibility. |
beacon | Send heartbeat and state updates over the framed channel. |
cleanup | Remove artifacts and confirm the probe tree is empty. |
Every operation is budgeted, scoped and recorded in the evidence store; the probe tree cleans up child-first.
Every module is a template, and the registry rejects a module that ships run.py.
Proxy protocol support
Reverse transports and ML service proxies
The reverse channel and the ML proxies are separate layers: the channel carries frames between controller and probe, the proxies carry a service protocol between the probe and an in-scope target.
| Layer | Supported |
|---|---|
| Reverse channel | TLS · WSS · HTTPS · QUIC · WebTransport (experimental) · MASQUE |
| ML service proxy | gRPC · Redis · TCPStore · NCCL · UCX · ZMTP (experimental) |
| SOCKS5 | Loopback compatibility only (127.0.0.1) |
Authentication and encryption
- Every framed message carries a token and an HMAC; a wrong token or MAC closes the channel.
- TLS, WSS, HTTPS, QUIC and WebTransport validate the controller certificate against a pinned SHA-256 fingerprint and an optional CA file.
- gRPC, Redis, TCPStore, NCCL and UCX proxies are TLS-wrapped; ZMTP uses CURVE with Z85 keys when enabled.
- SOCKS5 stays on loopback and is a compatibility path for local tooling, not a network-wide proxy.
Vulnerability research
The research behind the template catalogue
The template catalogue is built on 184 vulnerability write-ups, each recording the component, affected versions, root cause, impact and detection. 68 have runnable PoCs. The research set contains 169 entries: 47 were reproduced dynamically and confirmed unpublished, 46 are ready for coordinated disclosure, and deduplication leaves 39 distinct exploit primitives. A 103-record version matrix and 121 detection rules feed 29 attack chains.
Vulnerability research
| Inventory | Count |
|---|---|
| Vulnerability entries | 184 |
| Runnable PoCs | 68 |
| Research entries | 169 |
| Confirmed unpublished | 47 |
| Ready for disclosure | 46 |
| Unique primitives | 39 |
| Version matrix rows | 103 |
| Payload packs | 47 |
| Detection rules | 121 |
| Attack chains | 29 |
The public ledger lists component, class, affected versions and disclosure status; exploit details stay private.
0DAY-PUBLIC.md · VULNERABILITY-LAYERS.md · DETECTION-LAYERS.md
From foothold to report
Nine stages, each leaving behind something the next stage can check
The order matters. Any stage can refuse, and a refusal stops the run.
- 1Footholdsession open records the entry vector, target, namespace, Pod and credential fingerprint.
→ session record - 2Rust probeprobe deploy delivers the static binary and registers its identity and hash.
→ probe identity - 3Channelchannel listen accepts the probe's reverse connection; a stdio channel is available when a local transport exists.
→ channel state - 4Detectionsession run, run and agent run execute templates across the ten layers.
→ findings, evidence - 5Escapeexecute resolves a chain; write steps pass the backup check first.
→ escape path - 6Lateralchannel forwards, child probes and agent graph edges map internal reachability.
→ reachability graph - 7Multi-probeprobe spawn extends the tree; children inherit a stricter budget and allow-list.
→ probe tree - 8Cross-clusteragent relay connects clusters; agent coverage writes the completion proof.
→ relay status, coverage proof - 9Report / rules / consolereport, export, rules generate and ui finish the engagement.
→ report, rule packs, console
Write-permission checks
| Gate | Refuses when | Signal |
|---|---|---|
| Consent | No record, expired window, out-of-scope asset. | exit 91 |
| Level | Template level above the record. | exit 91 |
| Backup | Write step without a backup target. | exit 91 |
| Scope | Target or namespace outside the session. | refused |
| Rollback | A step cannot be restored. | exit 3 |
Probe-first onboarding
Install, attach, deliver, run, report
Start from the console and attach the probe or foothold you already hold. The default foothold is a least-privilege Pod: non-root, no hostPath or privileged mode, no kubeconfig, outbound TCP only.
- python -m pip install -e .Install the controller (Python 3.10 – 3.13).
- python -m inkblade upStart the console, sign in and sign the authorization record.
- python -m inkblade probe listAttach an existing probe; the controller listens and the probe connects back.
- python -m inkblade session open --mode foothold ...First delivery from the shell, SA token or RCE you already hold.
- python -m inkblade agent run --probe <probe-id> ...Run detection through the probe channel, then report.
$ python -m inkblade up
$ python -m inkblade quickstart
$ python -m inkblade probe list
$ python -m inkblade channel listen
$ python -m inkblade session open --mode foothold --target <target> --credential-source pod-shell --namespace <namespace> --pod <pod>
$ python -m inkblade probe deploy --session <session-id> --via rce --binary ./inkblade-probe-linux-amd64 --probe-token-file ./probe.token --allow-write
$ inkblade-probe reverse --host <controller> --port <port>
$ python -m inkblade agent run --probe <probe-id> --objective read-only-recon --workspace ./work
$ python -m inkblade report --run <run-id> --lang bi
Child probes are delivered from the parent with probe upload + probe spawn and call back the same way. A stdio channel (channel start) is available when a local command transport exists. A kubeconfig is optional, only for a first batch bootstrap of several Pods. The documentation site is local: python -m inkblade docs serves docs/ on 127.0.0.1:8766 and opens the browser; --no-browser keeps it headless.
Quick start · Install · Usage
Command map
The surface you actually type
Commands that do not contact a cluster or an LLM run offline. Agent planning needs an LLM endpoint.
| Task | Command |
|---|---|
| Onboarding | inkblade up |
| Authorization | inkblade quickstart · inkblade roe |
| Session | inkblade session open|status|close|run |
| Probe | inkblade probe deploy|list|collect|exec|read-file|list-files|upload|download|spawn|cleanup |
| Channel | inkblade channel listen|start|status|stop |
| One template | inkblade session run --id |
| Chain | inkblade execute --chain |
| Agent | inkblade agent run|status|trace|resume|replay|stop |
| Cross-cluster | inkblade agent relay add|list|status · inkblade agent coverage status|proof |
| Report | inkblade report --run |
| Export | inkblade export --run |
| Rules | inkblade rules generate · inkblade rules validate |
| Console | inkblade ui |
| Docs site | inkblade docs --port 8766 --bind 127.0.0.1 |
| Templates | inkblade template list|get|plan|validate |
Wheel, container, Helm
One controller, any of three delivery paths
The controller is a Python package with no third-party dependency. The probe is a separate static binary.
python -m pip wheel . --no-deps -w dist/
python -m pip install --no-index --find-links dist/ inkblade
docker build -t inkblade:0.2.0 .
docker run --rm -v inkblade-data:/data inkblade:0.2.0 up
helm install inkblade deploy/helm/inkblade --namespace inkblade --create-namespace
uid 10001, read-only root, a PVC for evidence. Read verbs by default; writes need readOnly=false, rbac.allowWrite=true and a signed record. Uninstall keeps the PVC.
Security and authorization
Authorization is a prerequisite, not a feature toggle
InkBlade refuses to run without a signed record, and each stage has its own check.
- RoE recordTarget, scope, level, window and emergency contact. Hash-pinned and carried by every run.
- Read-only defaultCollection, probes, file reads and read-only templates need no extra flag.
- Five write-permission checksSession level, --allow-write, meta.writes, backup-write mode, backup receipt.
- Backup and rollbackSnapshot before the write, record both, restore one step at a time.
- Audit and evidenceEvery probe action and file access lands in the evidence store with a SHA-256 manifest.
- Kill switchinkblade abort stops the workspace; agent stop stops one run.
| Control | What it guarantees |
|---|---|
| Consent hash | Every run carries the hash of its signed authorization file. |
| Scope and level | Out-of-scope or above-level actions are refused before execution. |
| Backup receipt | No write without a restorable snapshot. |
| Evidence manifest | Every finding resolves to a task, step, artifact, probe or manifest hash. |
Authorized use only. Written authorization or nothing. Testing systems you do not own is a crime in most jurisdictions. The software refuses without a signed record.
Report security issues through the private channel in SECURITY.md. Do not open a public issue with exploit detail.
FAQ
Access, probe, detection, authorization, delivery
How does the probe get into the Pod?
From a foothold you already hold. The default is authorized RCE: base64 chunks of the binary go into the Pod and are written through memfd, or through /dev/shm or /tmp when memfd is unavailable, then chmod 700 and start. A ServiceAccount token, a shared volume and an EphemeralContainer manifest are the other roads: probe deploy --via sa-token builds a temporary kubeconfig and uses kubectl cp + exec, a shared volume carries the binary through a mounted volume, and probe deploy --via manifest generates the Pod, Job or EphemeralContainer manifest. kubectl is only needed for batch bootstrap. Once started, the probe calls back with inkblade-probe reverse --host
Is the probe a backdoor?
No. It does not persist, modify startup, patch images or call a fixed C2. It runs inside an authorized session, executes registered templates, defaults to read-only, checks writes and cleans up.
How are writes controlled?
Five checks: signed authorization covering target, level and window; --allow-write; meta.writes with a write step; backup-write mode; and a backup receipt. A write reads back the hash and rolls back on failure.
Can it run air-gapped?
Manual runs, templates, probes and reports run offline. Agent mode with LLM planning needs an LLM endpoint — a local model or an internal API; without one, use manual or rule-based execution.
Can I use it commercially?
Apache-2.0 permits commercial use and forks. Keep LICENSE and NOTICE, and do not use the InkBlade trademark for a fork.
More: FAQ.md
License
Apache-2.0, repository policies
Apache-2.0. Commercial use, forks and embedding are permitted; keep the notices.
| Item | Details |
|---|---|
| License | Apache-2.0. Keep LICENSE and NOTICE. |
| Trademark | Do not name a fork InkBlade. |
| Policies | SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md. |
Documentation index: DOC-INDEX.md