[object Object]

← back to Fleet Rag

fleet-rag: redact secret shapes at ingest + untrack vectors.jsonl build artifact

114cc098803822112d5595ce729f1acb8f0f5de3 · 2026-06-24 08:52:22 -0700 · Steve

Files touched

Diff

commit 114cc098803822112d5595ce729f1acb8f0f5de3
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jun 24 08:52:22 2026 -0700

    fleet-rag: redact secret shapes at ingest + untrack vectors.jsonl build artifact
---
 .gitignore    |  3 +++
 lib/index.js  |  2 ++
 lib/redact.js | 26 ++++++++++++++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/.gitignore b/.gitignore
index 19e99af..75f37ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,6 @@ build/
 *~
 .swp
 .swo
+
+# RAG build artifact — regenerable via POST /index, NEVER commit (holds spilled secrets)
+data/vectors.jsonl
diff --git a/lib/index.js b/lib/index.js
index a7a6ff3..c5e5de9 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -4,6 +4,7 @@ const fs   = require('fs');
 const path = require('path');
 const { execSync } = require('child_process');
 const { embed } = require('./embed');
+const { redact } = require('./redact');
 
 const VECTORS_PATH = path.join(__dirname, '../data/vectors.jsonl');
 const CHUNK_SIZE   = 512;
@@ -162,6 +163,7 @@ async function buildIndex(onProgress) {
 
   for (let i = 0; i < all.length; i++) {
     const doc = all[i];
+    doc.chunk_text = redact(doc.chunk_text);   // strip known secret shapes before embed/persist
     try {
       const embedding = await embed(doc.chunk_text);
       const record = { id: i, ...doc, embedding };
diff --git a/lib/redact.js b/lib/redact.js
new file mode 100644
index 0000000..fec7896
--- /dev/null
+++ b/lib/redact.js
@@ -0,0 +1,26 @@
+'use strict';
+// Redact known fleet-secret shapes from any chunk before it is embedded/persisted.
+// Added 2026-06-24 (fleet-rag-secret-spillage remediation): the ingestion pipeline
+// slurped server.js heads + memory files verbatim, capturing plaintext secrets into
+// data/vectors.jsonl. This filter neutralizes known secret shapes at ingest time so a
+// rebuilt index carries no live credential even when a source file still holds one.
+const PATTERNS = [
+  [/AIza[A-Za-z0-9_\-]{35}/g,                                  '[REDACTED_GEMINI_KEY]'],
+  [/shpat_[a-f0-9]{32}/g,                                       '[REDACTED_SHOPIFY_TOKEN]'],
+  [/shpss_[a-f0-9]{32}/g,                                       '[REDACTED_SHOPIFY_SECRET]'],
+  [/shpca_[a-f0-9]{32}/g,                                       '[REDACTED_SHOPIFY_SECRET]'],
+  [/https?:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9\/]+/g,   '[REDACTED_SLACK_WEBHOOK]'],
+  [/postgres(?:ql)?:\/\/[^:\/\s]+:[^@\s]+@[^\s"'`]+/g,          '[REDACTED_PG_DSN]'],
+  [/DW2024SecurePass!?/g,                                       '[REDACTED_PW]'],
+  [/DWSecure2024!?/g,                                           '[REDACTED_PW]'],
+  [/[A-Za-z0-9]*access911[A-Za-z0-9]*/g,                        '[REDACTED_VENDOR_PW]'],
+  [/sk-[A-Za-z0-9]{20,}/g,                                      '[REDACTED_OPENAI_KEY]'],
+  [/(?:r8_|ghp_|gho_|xoxb-|xoxp-)[A-Za-z0-9\-]{20,}/g,          '[REDACTED_TOKEN]'],
+];
+function redact(text) {
+  if (!text) return text;
+  let out = String(text);
+  for (const [re, repl] of PATTERNS) out = out.replace(re, repl);
+  return out;
+}
+module.exports = { redact };

← 854e00f gitignore: cover backup/scratch/editor artifacts  ·  back to Fleet Rag  ·  untrack vectors.jsonl build artifact (held spilled secrets) b21a822 →