Skip to content

Commit 756045e

Browse files
RoyLinRoyLin
authored andcommitted
release: v0.5.0 — SSL/TLS content capture (#7), KVM-validated
Opt-in OpenSSL uprobe content capture validated in a non-prod KVM VM: a marker sent inside a local TLS session surfaced as SslContent plaintext (the GET / HTTP/1.1 request line + marker header captured pre-encryption). README + CHANGELOG reflect the now-real content extension. 0.4.0 -> 0.5.0.
1 parent db5e355 commit 756045e

7 files changed

Lines changed: 21 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
All notable changes to a3s-observer will be documented in this file.
44

5-
## [Unreleased]
5+
## [0.5.0] — SSL/TLS content capture (opt-in)
66

77
### Added
88

99
- **SSL/TLS content capture (#7)** — the long-deferred opt-in OpenSSL uprobe extension.
1010
`A3S_OBSERVER_SSL=1` attaches uprobes to `SSL_write` / `SSL_read` and emits `SslContent`
11-
events with the request (prompt) / response (completion) **plaintext**. This is deliberately
12-
outside the universal core (Rule 2): a uprobe binds to a library symbol, so it is **not**
11+
events with the request (prompt) / response (completion) **plaintext**. Deliberately outside
12+
the universal core (Rule 2): a uprobe binds to a library symbol, so it is **not**
1313
language-agnostic (OpenSSL only — Python `requests`/`httpx`, Node, curl …, not Go
14-
`crypto/tls`), and it captures real content, so it is **off by default**. Build-validated;
15-
runtime validation pending a non-prod VM (content capture is gated off the shared prod node).
14+
`crypto/tls`), and it captures real content, so it is **off by default**.
15+
- **Validated end-to-end in a throwaway KVM VM**: a marker sent *inside* a local TLS session
16+
surfaced as `SslContent` plaintext (the `GET / HTTP/1.1` request line and the marker header
17+
were captured pre-encryption), confirming the uprobe reads cleartext the wire never sees.
1618

1719
## [0.4.0] — file-access intervention
1820

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
edition = "2021"
55
license = "MIT"
66
description = "General-purpose, language-agnostic eBPF observability for AI agents (LLM calls, tools, files, network egress)."

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ provider + bytes/latency/TTFT), where (peer IP / hostname).
5454
| `dns` | `sendto` / `sendmsg` / `sendmmsg` to :53 | resolved hostnames |
5555
| LLM metrics | per-socket `read` / `recv` + `close` | req/resp wire bytes, latency, TTFT |
5656
| `file` | `sys_enter_openat` (write opens) | files written — **opt-in** (`A3S_OBSERVER_FILES=1`; high-volume) |
57+
| `ssl` content | uprobes on OpenSSL `SSL_write` / `SSL_read` | request/response **plaintext** (prompt/completion) — **opt-in** (`A3S_OBSERVER_SSL=1`; OpenSSL-only, not language-agnostic) |
5758

5859
Userspace enriches each event with **identity** (k8s cgroup→pod, `/proc` comm+ppid, or an
5960
in-kernel `comm` fallback for short-lived processes) and a `(pid,fd)→peer` **correlation**,
@@ -79,9 +80,11 @@ turns observed events into a deny-list. See [`docs/enforcement.md`](docs/enforce
7980
- **Zero-instrumentation, language-agnostic** — observe or guard any agent
8081
(Python/Node/Go/Rust) without touching its code, including its tool subprocesses.
8182
- **Sees what the app won't report** — real execs, file I/O, network egress.
82-
- **Kernel hooks only, no uprobes.** The deliberate trade-off: **no LLM prompt / model name /
83-
token / completion content** — that needs an opt-in per-TLS-library uprobe extension, kept
84-
out of the universal core. (ECH will eventually hide SNI → fall back to IP/DNS.)
83+
- **Kernel hooks only in the always-on core, no uprobes.** The deliberate trade-off: the core
84+
gives **no LLM prompt / completion content**. That content *is* available via an **opt-in**
85+
OpenSSL uprobe extension (`A3S_OBSERVER_SSL=1`) that captures `SSL_write`/`SSL_read`
86+
plaintext — kept out of the core because a uprobe binds to a library symbol, so it's OpenSSL
87+
only, not language-agnostic. (ECH will eventually hide SNI → fall back to IP/DNS.)
8588
- **a3s-box:** a box is a separate guest kernel, so host-side eBPF sees box **egress** (it
8689
flows through the host net path) but not in-guest exec/file — those need an in-guest
8790
collector (phase 2).

a3s-observer-collector/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer-collector"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
edition = "2021"
55
license = "MIT"
66
description = "a3s-observer collector: loads the eBPF probes and exports enriched events."

a3s-observer-common/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer-common"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
edition = "2021"
55
license = "MIT"
66
description = "Shared no_std types crossing the eBPF <-> userspace boundary for a3s-observer."

a3s-observer-ebpf/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer-ebpf"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
edition = "2021"
55
license = "MIT"
66
publish = false

0 commit comments

Comments
 (0)