Report a suspected vulnerability by opening a GitHub issue at https://github.com/TGPSKI/flow-indicator/issues. If the report itself would disclose sensitive data, open an issue that says only that you have a report and wait to be contacted.
Expect acknowledgement within 7 days and an assessment within 14.
flow-indicator is a local CLI. It reads transcript stores, writes session and
instance JSON under the user's data directory, writes operator-selected corpus,
labeling and replay-set outputs, shells out to two programs in four bounded
roles, and can post text to an operator-configured HTTP endpoint. Security
issues are:
- Reading outside the selected source. A named source opens only that source;
without
--adapter, a named path uses the command's default harness rather than scanning stores to infer one.sessions,watch --currentandwatch --lastenumerate the four agent stores below unless--adapterselects one before discovery.watch --panereads herdr and only the harness store mapped from the pane's agent.corpus --scanreads one--harness, under the named root or that harness's default. The default roots are~/.claude/projects,~/.codex/sessions(orCODEX_HOME),~/.qwen/projects, and opencode's SQLite store. Reading a transcript outside the named source or selected root is a vulnerability. - Configuration and stored results.
replay,replay-set,watchandcalibrateread the named or default configuration and marker profile;reportandinspectread configuration and an existing session under the selected data root. A named--config,--profileor--data-dirpath is the boundary for that read. - Subprocess surface.
sqlite3 -readonlyreads the opencode store;herdr pane currentandherdr agent listresolvewatch --pane;herdr pane report-metadatapushes the--herdr-panesidebar row. The herdr calls are bounded at 3 s and thesqlite3read at 10 s; a store another process holds locked reports rather than hanging the meter. Passing operator-controlled or transcript-derived text into a subprocess argument in a way that changes the command is a vulnerability, as is invoking anything else. - Live instance records. Any
watchon a discovered session — a file, or opencode's store — writes one operational record; a pipedwatchwrites none. The record holds liveness coordinates and a small derived metric subset, read back throughinstances. Transcript text or event data appearing in one is a vulnerability. - Writing outside the selected destination. Session and instance artifacts
stay under the data directory;
store.SanitizeIDreduces a source stream identifier to one safe path element.corpus --build --out,annotate --out, andreplay-set --output/--anchorsintentionally write to operator-selected paths. A write outside the applicable data root or named output is a vulnerability. - Unintended transcript disclosure. By default only a 160-character snippet
per record is stored (
privacy.store_snippets,privacy.snippet_chars), andprivacy.store_textmust be set explicitly to store full text. Storing more than the configuration allows is a vulnerability. - Classifier egress. In
openai-compatibleandhybridmodes, turn text, bounded prior operator text, unresolved obligation references and an open repair reference are sent to the configured endpoint.annotateposts corpus units to its own--endpoint, which defaults tohttp://127.0.0.1:8000/v1/chat/completionsand is neverclassifier.endpoint;calibrate --classifier configuredscores through the configured classifier and so posts every scored turn in those two modes. Sending anything innoneorheuristicmode, or starting a request at an endpoint other than the one named for that command, is a vulnerability. - Credential handling. The API key is read from
FLOW_INDICATOR_API_KEYand sent as a bearer token to the endpoint the running command names — the configured classifier endpoint, orannotate --endpoint. It is never written to a session file, a log line, or an error message. - Mutating the measured session. The tool opens source files read-only. A write to a followed session file is a vulnerability.
Out of scope: the security of the endpoint an operator configures, the contents of transcripts an operator chooses to store, and file permissions on a directory the operator has made world-readable. Session files and directories are created with mode 0600 and 0700.
Pre-1.0. Only the tip of main is supported.
- Stored session data is not encrypted at rest. It is protected by filesystem permissions only. Encrypt the underlying volume if transcripts are sensitive.
openai-compatibleandhybridmodes send turn text to whatever endpoint is configured, including a remote one. The default mode isheuristic, which sends nothing.- The model clients use Go's default redirect policy. An endpoint returning 307 or 308 can resend the request body to its redirect target. Do not use an endpoint that redirects until redirect following is disabled.
sessions,--currentand--lastenumerate every agent store unless--adapterselects one before discovery, so their output can name projects outside the current one.