opencode-secrets-obfuscation 0.1.6 → 0.1.7

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/plugin.mjs +11 -52
package/README.md CHANGED
@@ -10,7 +10,7 @@ This plugin keeps configured dotenv values private and substitutes opaque secret
10
10
 
11
11
  ## Installation
12
12
 
13
- Install with: opencode plugin add opencode-secrets-obfuscation@0.1.6
13
+ Install with: opencode plugin add opencode-secrets-obfuscation@0.1.7
14
14
 
15
15
  Configure the published package in opencode.jsonc with the options documented at https://github.com/jfomhhover/opencode-secrets-obfuscation/blob/main/INSTALL.md.
16
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-secrets-obfuscation",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Transparent OpenCode V2 secret substitution plugin",
5
5
  "license": "MIT",
6
6
  "repository": {
package/plugin.mjs CHANGED
@@ -3359,7 +3359,6 @@ function verifyCeilingBytes(patterns) {
3359
3359
  var WITHHELD = "SANITIZATION_UNAVAILABLE";
3360
3360
  var encoder2 = new TextEncoder();
3361
3361
  var decoder = new TextDecoder();
3362
- var AUTH_CHANNEL = /* @__PURE__ */ new Set(["authorization", "api-key", "x-api-key", "proxy-authorization"]);
3363
3362
  var NULL_BODY_STATUS = /* @__PURE__ */ new Set([101, 204, 205, 304]);
3364
3363
  var hasSecrets = (state) => state.patterns.length > 0;
3365
3364
  function redactNode(current, depth, state, counters) {
@@ -3419,30 +3418,6 @@ function containsSecret(value, state) {
3419
3418
  if (!hasSecrets(state)) return false;
3420
3419
  return scanForSecrets(value, state.patterns, state.budget) !== "clean";
3421
3420
  }
3422
- function redactHeaders(headers, state, options2) {
3423
- if (!hasSecrets(state)) return;
3424
- for (const name of Object.keys(headers)) {
3425
- if (options2.skipAuth && AUTH_CHANNEL.has(name.toLowerCase())) continue;
3426
- const value = headers[name];
3427
- if (typeof value !== "string") {
3428
- if (options2.strict) return "withheld";
3429
- delete headers[name];
3430
- continue;
3431
- }
3432
- const safeValue = redactString(value, state);
3433
- const safeName = redactString(name, state);
3434
- if (safeValue === null || safeName === null) {
3435
- if (options2.strict) return "withheld";
3436
- delete headers[name];
3437
- continue;
3438
- }
3439
- if (safeValue !== value) headers[name] = safeValue;
3440
- if (safeName !== name) {
3441
- delete headers[name];
3442
- headers[safeName] = safeValue;
3443
- }
3444
- }
3445
- }
3446
3421
  function redactBody(text, state) {
3447
3422
  if (!hasSecrets(state)) return text;
3448
3423
  if (scanForSecrets(text, state.patterns, state.budget) === "clean") return text;
@@ -3511,12 +3486,6 @@ async function redactRequest(request, state) {
3511
3486
  const verifyCeiling = verifyCeilingBytes(state.patterns);
3512
3487
  const declared = Number(request.headers.get("content-length") ?? Number.NaN);
3513
3488
  if (Number.isFinite(declared) && declared > verifyCeiling) return "withheld";
3514
- const record = {};
3515
- request.headers.forEach((value, name) => {
3516
- record[name] = value;
3517
- });
3518
- const originalHeaders = { ...record };
3519
- if (redactHeaders(record, state, { skipAuth: true, strict: true }) === "withheld") return "withheld";
3520
3489
  let body;
3521
3490
  if (request.body !== null) {
3522
3491
  const read = await readBoundedBody(request.clone().body, verifyCeiling);
@@ -3529,34 +3498,25 @@ async function redactRequest(request, state) {
3529
3498
  if (safe !== read.text) body = safe;
3530
3499
  }
3531
3500
  }
3532
- const headersChanged = Object.keys(record).length !== Object.keys(originalHeaders).length || Object.keys(record).some((name) => record[name] !== originalHeaders[name]);
3533
- if (body === void 0 && !headersChanged) return request;
3534
- if (body !== void 0) {
3535
- delete record["content-length"];
3536
- record["content-length"] = String(encoder2.encode(body).byteLength);
3537
- }
3501
+ if (body === void 0) return request;
3538
3502
  try {
3539
- return new Request(request, {
3540
- headers: record,
3541
- ...body === void 0 ? {} : { body },
3542
- signal: request.signal
3503
+ const headers = {};
3504
+ request.headers.forEach((value, name) => {
3505
+ headers[name] = value;
3543
3506
  });
3507
+ headers["content-length"] = String(encoder2.encode(body).byteLength);
3508
+ return new Request(request, { headers, body, signal: request.signal });
3544
3509
  } catch {
3545
3510
  return "withheld";
3546
3511
  }
3547
3512
  }
3548
3513
  async function redactResponse(response2, state) {
3549
3514
  if (!hasSecrets(state)) return response2;
3550
- const headers = {};
3551
- response2.headers.forEach((value, name) => {
3552
- headers[name] = value;
3553
- });
3554
- redactHeaders(headers, state, { skipAuth: false, strict: false });
3555
3515
  const status = response2.status;
3556
3516
  const nullBody = NULL_BODY_STATUS.has(status);
3557
3517
  if (nullBody) {
3558
3518
  try {
3559
- return new Response(null, { status, headers });
3519
+ return new Response(null, { status, headers: response2.headers });
3560
3520
  } catch {
3561
3521
  return new Response(null, { status: 502 });
3562
3522
  }
@@ -3565,7 +3525,7 @@ async function redactResponse(response2, state) {
3565
3525
  const declared = Number(response2.headers.get("content-length") ?? Number.NaN);
3566
3526
  if (Number.isFinite(declared) && declared > verifyCeiling) {
3567
3527
  try {
3568
- return new Response(null, { status, headers });
3528
+ return new Response(null, { status, headers: response2.headers });
3569
3529
  } catch {
3570
3530
  return new Response(null, { status: 502 });
3571
3531
  }
@@ -3573,7 +3533,7 @@ async function redactResponse(response2, state) {
3573
3533
  const read = await readBoundedBody(response2.clone().body, verifyCeiling);
3574
3534
  if (read === null) {
3575
3535
  try {
3576
- return new Response(null, { status, headers });
3536
+ return new Response(null, { status, headers: response2.headers });
3577
3537
  } catch {
3578
3538
  return new Response(null, { status: 502 });
3579
3539
  }
@@ -3581,14 +3541,14 @@ async function redactResponse(response2, state) {
3581
3541
  let body;
3582
3542
  if (read.bytes > state.maxInputBytes) {
3583
3543
  body = scanForSecrets(read.text, state.patterns, state.budget) === "clean" ? read.text : "";
3584
- } else if ((headers["content-type"] ?? "").toLowerCase().includes("text/event-stream")) {
3544
+ } else if ((response2.headers.get("content-type") ?? "").toLowerCase().includes("text/event-stream")) {
3585
3545
  body = redactEventStream(read.text, state) ?? "";
3586
3546
  } else {
3587
3547
  const safe = redactBody(read.text, state);
3588
3548
  body = safe === null ? "" : safe;
3589
3549
  }
3590
3550
  try {
3591
- return new Response(body, { status, headers });
3551
+ return new Response(body, { status, headers: response2.headers });
3592
3552
  } catch {
3593
3553
  return new Response(null, { status: 502 });
3594
3554
  }
@@ -3771,7 +3731,6 @@ var realRuntimeFactory = (options2, location) => {
3771
3731
  }),
3772
3732
  modelRequest: (event) => Effect4.gen(function* () {
3773
3733
  if (!hasSecrets(filter)) return;
3774
- if (redactHeaders(event.headers, filter, { skipAuth: true, strict: true }) === "withheld") yield* Effect4.die(new Error(WITHHELD));
3775
3734
  if (event.baseURL !== void 0) event.baseURL = redactString(event.baseURL, filter) ?? WITHHELD;
3776
3735
  }),
3777
3736
  httpRequest: (event) => Effect4.promise(async () => {