From 3516e0b6fda2f45f90600d3800b4a643337e2e71 Mon Sep 17 00:00:00 2001 From: Didactyl User Date: Fri, 31 Jul 2026 06:59:31 -0400 Subject: [PATCH] security: gate provider payload logging behind DIDACTYL_CONTEXT_DEBUG The log_provider_payload_local() calls in perform_http_request() were unconditional, writing full LLM conversation transcripts (system prompts, user messages, tool calls, responses) to context.logs/ on every LLM call regardless of the DIDACTYL_CONTEXT_DEBUG setting. This caused 326 transcript files containing Nostr keys, relay URLs, and DM contents to be committed and pushed. Now the logging only runs when DIDACTYL_CONTEXT_DEBUG is set to 'init' or 'full' (matching the documented behavior in docs/CONTEXT.md). When unset or 'off', no transcripts are written to disk. --- src/llm.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/llm.c b/src/llm.c index f8d638e..fe690ad 100644 --- a/src/llm.c +++ b/src/llm.c @@ -65,6 +65,20 @@ static void log_provider_payload_local(const char* payload, fclose(out); } +/* + * Provider payload logging (context.logs/) is gated behind DIDACTYL_CONTEXT_DEBUG. + * Modes: "off" (or unset) = no logging, "init" or "full" = logging enabled. + * This prevents full LLM conversation transcripts (system prompts, user messages, + * tool calls, responses) from being written to disk in production. + */ +static int provider_log_enabled(void) { + const char* mode = getenv("DIDACTYL_CONTEXT_DEBUG"); + if (!mode || mode[0] == '\0') { + return 0; + } + return strcmp(mode, "off") != 0; +} + static int url_looks_like_websocket(const char* url) { if (!url) return 0; return (strncmp(url, "ws://", 5) == 0) || (strncmp(url, "wss://", 6) == 0); @@ -134,8 +148,9 @@ static char* perform_http_request(const char* url, const char* body, int is_post char provider_log_stamp[32] = {0}; unsigned long provider_log_seq = 0; int provider_log_has_pair = 0; + const int do_provider_log = provider_log_enabled(); - if (is_post && body && body[0] != '\0') { + if (do_provider_log && is_post && body && body[0] != '\0') { if (provider_log_next_stamp_seq_local(provider_log_stamp, sizeof(provider_log_stamp), &provider_log_seq) == 0) { @@ -151,7 +166,7 @@ static char* perform_http_request(const char* url, const char* body, int is_post return NULL; } - if (resp.body && resp.body_len > 0) { + if (do_provider_log && resp.body && resp.body_len > 0) { if (!provider_log_has_pair) { if (provider_log_next_stamp_seq_local(provider_log_stamp, sizeof(provider_log_stamp),