Security, privacy, and redaction
Public guide snapshot. View source. For exact flags in your installation, use olef commands <path> --json.
Olef reads real screens, logs, files, and network traffic from a real device. Everything below exists to keep that evidence from leaking secrets or personal data by accident — and to be explicit where redaction cannot help.
Redacting secrets and PII
Section titled “Redacting secrets and PII”Pass global --redact before or after any subcommand to filter JSON and text at
the shared output boundary:
olef --redact ui dumpolef log --last 2m --redactolef --redact collect --app com.example.app --redact-screenshotsolef net start --redactBuilt-ins cover password/secret/token/cookie fields, JWTs, bearer values,
emails, IPv4/IPv6 addresses, usernames/phone values, and common session,
device, transaction, and serial identifiers. JSON embedded in log or GraphQL
body strings is parsed and retains its structure. Each emitted record carries
the policy version and replacement count. Config can enable the policy for all
commands and add key names or Rust-regex patterns; user and project additions
are merged, with the nearest enabled value winning.
UI dumps also recognize values following English Birthdate/Date of Birth/DOB and Device ID/Android ID labels. Recognized date, Android ID and UUID values are removed from duplicate layout and summary text, and from explicitly requested pixel redaction. This does not cover arbitrary labels, every date locale, or text that Android does not expose; add project patterns for those.
The network boundary
Section titled “The network boundary”net start --redact applies the same policy to completed capture copies
before they reach the session log, including URL path/query values, hosts,
connection errors, WebSocket metadata, and TLS failures. A live daemon reports its capture-policy
fingerprint; requesting --redact refuses to reuse an unredacted or differently
configured daemon and asks for an explicit stop/start. Request/response bytes
forwarded to the app or upstream are never changed. The session log is written
0600 either way.
Pixels are different
Section titled “Pixels are different”ui screenshot reports raw pixels as potentially sensitive. Explicit
--redact-pixels (PNG only) blacks out matching accessibility bounds, but
still reports that Android may not expose every rendered glyph. collect
marks screenshots potentially sensitive unless --redact-screenshots
explicitly blacks out matching bounds. The device viewer’s annotation
overviews and crops are full-screen pixels too: they are captured with
--redact-pixels whenever the redaction policy is on (OLEF_REDACT
or redaction.enabled), and report pixels_redacted per screen.
Video is a stricter boundary: global --redact does not alter MP4 pixels.
Every video bundle is marked as containing sensitive, unencrypted data;
review its clips before sharing it. For video bundles, --redact filters
marker labels; device/session identity and recovery paths remain in the
protected manifest, so the JSON timeline is still marked potentially sensitive.
Screen recording is video-only — it does not capture device, app, or
microphone audio.
Secrets in commands
Section titled “Secrets in commands”ui pin enters a numeric PIN without echoing the digits back in action JSON,
and deliberately refuses --observe/--expect-* so a returned screen cannot
reveal an unmasked keypad. The PIN is still present in the local process
invocation, so use the host’s normal shell-history and process-visibility
protections. See agent-loop.md.
App state snapshots (app state snapshot) are written 0700/0600, record
SHA-256 hashes and a signing-identity digest, and are deliberately marked
contains_sensitive_data:true and unencrypted. cleanup overwrites before
deletion but cannot guarantee physical erasure on SSD/COW/journaled storage.
See device-state.md.
Config cannot inject shell
Section titled “Config cannot inject shell”Repository config cannot supply executable device-shell fragments: app
packages are validated at deserialization, permission/app-op tokens at their
command boundary, and accepted values are quoted before entering an Android
shell command. Values containing ;, newlines, $(), quotes, or whitespace
fail with a typed invalid_* error. See
configuration.md.
Trust boundaries of the on-device pieces
Section titled “Trust boundaries of the on-device pieces”- On first
connect, the CLI auto-installs a version-matched APK pair downloaded from the matching GitHub Release, SHA-256 verified, and cached under~/.olef/apks/<version>/. When working inside the Olef repository it prefers local Gradle build outputs. - The wire protocol is loopback HTTP/JSON over an adb forward; the supported
public interface for agents is the CLI surface and
olef commands --json. - The
netMITM proxy installs its CA into the device’s user trust store (net trust); apps that opt out of user CAs, pin certificates, or bypass the system store reject it, reported astls_error. Forwarded bytes are never modified unless you explicitly intercept, rule, or replay. - The runtime attaches only to apps the OS marks debuggable (it goes
through
run-as), never through an app dependency. Its channel is an abstract unix socket that accepts only adbd’s uid and requires a per-attach token;runtime detachrestores every hooked class. - On the host, the runtime and debug daemons take CLI requests over a
0600unix socket, or on Windows over a loopback port that answers only connections presenting the daemon’s secret, kept in an owner-only file under~/.olef.
The optional local usage log
Section titled “The optional local usage log”Opt in to a local usage log with olef usage enable. Schema
version 2 records only the command path, duration, CLI version, outcome, and
typed error code/stage/retry posture — never argument values — and never
uploads anything:
olef usage enableolef usage report --days 30 | jq \ '{verbs, error_codes, error_stages, versions, recommendations, feedback_loop}'Recommendations require repeated evidence: high error rates, slow p95s, or recurring error codes. The report suggests the next engineering action but does not edit code. Reproduce the evidence, add a regression, implement the change, then compare error rate and p95 by version.
Diagnostics stay passive
Section titled “Diagnostics stay passive”why is non-mutating: it reads the on-device server only if it is already
reachable and never installs, starts, or forwards anything to get a screen.
collect is passive with respect to device lifecycle: the selected device/AVD
must already be online, it only reads server-backed evidence through an
already-established session, and it never starts an AVD, server, or adb
forward. Its manifest records privacy status per artifact.
Recovery without exposing device serials
Section titled “Recovery without exposing device serials”With --redact, device-scoped recovery commands use local @sd-… handles
accepted by --device, or the selected project --target. Handle mappings
live under ~/.olef/device-refs (0600 files in a 0700 directory on
Unix). They work only on that host; deleting a mapping invalidates its handle.
They are not credentials. Device details and application session identifiers
remain redacted, and suggested follow-ups retain --redact.
Internal lifecycle identities such as avd:TV-default are never emitted as
ADB serial arguments.