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.
This commit is contained in:
Didactyl User
2026-07-31 06:59:31 -04:00
parent e14514b396
commit 3516e0b6fd
+17 -2
View File
@@ -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),