@solongate/proxy 0.81.7 → 0.81.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -184,19 +184,13 @@ ${SHIM_END}` : `${SHIM_BEGIN}
184
184
  claude() { "${node}" "${shield}" -- "${real}" "$@"; }
185
185
  ${SHIM_END}`;
186
186
  const targets = shimTargets();
187
- if (targets.length === 0) {
188
- console.log(" (No shell profile found for auto-shield; run `claude` via `solongate shield -- claude` manually.)");
189
- return;
190
- }
187
+ if (targets.length === 0) return;
191
188
  for (const file of targets) {
192
189
  try {
193
190
  writeShimBlock(file, block);
194
- console.log(` Auto-shield on: \`claude\` now masks secrets (${file})`);
195
- } catch (e) {
196
- console.log(` (Could not enable auto-shield in ${file}: ${e.message})`);
191
+ } catch {
197
192
  }
198
193
  }
199
- console.log(" Open a NEW terminal for it to take effect.");
200
194
  }
201
195
  function removeClaudeShim() {
202
196
  for (const file of shimTargets()) {
package/dist/index.js CHANGED
@@ -10528,19 +10528,13 @@ ${SHIM_END}` : `${SHIM_BEGIN}
10528
10528
  claude() { "${node}" "${shield}" -- "${real}" "$@"; }
10529
10529
  ${SHIM_END}`;
10530
10530
  const targets = shimTargets();
10531
- if (targets.length === 0) {
10532
- console.log(" (No shell profile found for auto-shield; run `claude` via `solongate shield -- claude` manually.)");
10533
- return;
10534
- }
10531
+ if (targets.length === 0) return;
10535
10532
  for (const file of targets) {
10536
10533
  try {
10537
10534
  writeShimBlock(file, block2);
10538
- console.log(` Auto-shield on: \`claude\` now masks secrets (${file})`);
10539
- } catch (e) {
10540
- console.log(` (Could not enable auto-shield in ${file}: ${e.message})`);
10535
+ } catch {
10541
10536
  }
10542
10537
  }
10543
- console.log(" Open a NEW terminal for it to take effect.");
10544
10538
  }
10545
10539
  function removeClaudeShim() {
10546
10540
  for (const file of shimTargets()) {
@@ -10976,8 +10970,16 @@ function startProxy(upstream) {
10976
10970
  try {
10977
10971
  if (body.length && (req.headers["content-type"] || "").includes("json")) {
10978
10972
  const parsed = JSON.parse(body.toString("utf-8"));
10979
- const redacted = redactDeep(parsed, cfg);
10980
- body = Buffer.from(JSON.stringify(redacted), "utf-8");
10973
+ if (parsed && typeof parsed === "object" && Array.isArray(parsed["messages"])) {
10974
+ if (parsed["system"] !== void 0) parsed["system"] = redactDeep(parsed["system"], cfg);
10975
+ const msgs = parsed["messages"];
10976
+ for (let i = 0; i < msgs.length; i++) {
10977
+ if (msgs[i] && msgs[i]["role"] !== "assistant") msgs[i] = redactDeep(msgs[i], cfg);
10978
+ }
10979
+ body = Buffer.from(JSON.stringify(parsed), "utf-8");
10980
+ } else {
10981
+ body = Buffer.from(JSON.stringify(redactDeep(parsed, cfg)), "utf-8");
10982
+ }
10981
10983
  }
10982
10984
  } catch {
10983
10985
  }
package/dist/login.js CHANGED
@@ -191,19 +191,13 @@ ${SHIM_END}` : `${SHIM_BEGIN}
191
191
  claude() { "${node}" "${shield}" -- "${real}" "$@"; }
192
192
  ${SHIM_END}`;
193
193
  const targets = shimTargets();
194
- if (targets.length === 0) {
195
- console.log(" (No shell profile found for auto-shield; run `claude` via `solongate shield -- claude` manually.)");
196
- return;
197
- }
194
+ if (targets.length === 0) return;
198
195
  for (const file of targets) {
199
196
  try {
200
197
  writeShimBlock(file, block);
201
- console.log(` Auto-shield on: \`claude\` now masks secrets (${file})`);
202
- } catch (e) {
203
- console.log(` (Could not enable auto-shield in ${file}: ${e.message})`);
198
+ } catch {
204
199
  }
205
200
  }
206
- console.log(" Open a NEW terminal for it to take effect.");
207
201
  }
208
202
  async function runGlobalInstall(opts = {}) {
209
203
  const p = globalPaths();
package/dist/shield.js CHANGED
@@ -211,8 +211,16 @@ function startProxy(upstream) {
211
211
  try {
212
212
  if (body.length && (req.headers["content-type"] || "").includes("json")) {
213
213
  const parsed = JSON.parse(body.toString("utf-8"));
214
- const redacted = redactDeep(parsed, cfg);
215
- body = Buffer.from(JSON.stringify(redacted), "utf-8");
214
+ if (parsed && typeof parsed === "object" && Array.isArray(parsed["messages"])) {
215
+ if (parsed["system"] !== void 0) parsed["system"] = redactDeep(parsed["system"], cfg);
216
+ const msgs = parsed["messages"];
217
+ for (let i = 0; i < msgs.length; i++) {
218
+ if (msgs[i] && msgs[i]["role"] !== "assistant") msgs[i] = redactDeep(msgs[i], cfg);
219
+ }
220
+ body = Buffer.from(JSON.stringify(parsed), "utf-8");
221
+ } else {
222
+ body = Buffer.from(JSON.stringify(redactDeep(parsed, cfg)), "utf-8");
223
+ }
216
224
  }
217
225
  } catch {
218
226
  }
package/hooks/shield.mjs CHANGED
@@ -220,21 +220,25 @@ function startProxy(upstream) {
220
220
  try {
221
221
  if (body.length && String(req.headers['content-type'] || '').includes('json')) {
222
222
  const parsed = JSON.parse(body.toString('utf-8'));
223
- // Only the NEW turn needs scanning. The model re-sends the WHOLE
224
- // conversation on every request, but every prior message was already
225
- // redacted when it was itself the latest turn so re-scanning all of
226
- // history each call is pure waste that grows with the session (this was
227
- // the source of the intermittent stalls). Redact ONLY the last message:
228
- // the fresh user input + tool results (e.g. an `ls` result ghost-strip
229
- // hidden paths, DLP-redact secret patterns). We deliberately do NOT scan
230
- // the model's own generated prose only inputs and tool results matter.
231
- const msgs = parsed && Array.isArray(parsed.messages) ? parsed.messages : null;
232
- if (msgs && msgs.length > 0) {
233
- const i = msgs.length - 1;
234
- msgs[i] = redactDeep(msgs[i], cfg);
223
+ // Redact EVERY request, not just the last message. Claude Code re-sends
224
+ // the ORIGINAL (unredacted) conversation on every call it stores the raw
225
+ // history and rebuilds the request each time, so the shield must re-scan
226
+ // it every request. Redacting only the newest message leaked any secret
227
+ // sitting in an earlier message: the user's own turn often lands at
228
+ // messages[0] with later messages after it, and a one-shot `-p` run has no
229
+ // prior request in which history could have been redacted. Scan the system
230
+ // prompt and every USER-role message (fresh input + tool results like an
231
+ // `ls`/Read result); skip ASSISTANT-role messages (model-generated prose
232
+ // the bulk of a long session and not a secret source) so cost stays low.
233
+ if (parsed && typeof parsed === 'object' && Array.isArray(parsed.messages)) {
234
+ if (parsed.system !== undefined) parsed.system = redactDeep(parsed.system, cfg);
235
+ for (let i = 0; i < parsed.messages.length; i++) {
236
+ const m = parsed.messages[i];
237
+ if (m && m.role !== 'assistant') parsed.messages[i] = redactDeep(m, cfg);
238
+ }
235
239
  body = Buffer.from(JSON.stringify(parsed), 'utf-8');
236
240
  } else {
237
- // Non-messages payload (rare) → redact it once.
241
+ // Non-messages payload (rare) → redact it whole.
238
242
  body = Buffer.from(JSON.stringify(redactDeep(parsed, cfg)), 'utf-8');
239
243
  }
240
244
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.81.7",
3
+ "version": "0.81.9",
4
4
  "description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
5
5
  "type": "module",
6
6
  "bin": {