@hasna/logs 0.3.30 → 0.3.32

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.
package/dist/cli/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  runJob,
9
9
  structuredLogToEntry,
10
10
  validateStructuredLogReferences
11
- } from "../index-k9w7zfsv.js";
11
+ } from "../index-a0gz0zzc.js";
12
12
  import {
13
13
  PACKAGE_VERSION,
14
14
  createPage,
@@ -30,7 +30,7 @@ import {
30
30
  searchTestReports,
31
31
  summarizeLogs,
32
32
  validateUniversalEventInput
33
- } from "../index-mx0f61s2.js";
33
+ } from "../index-he072p17.js";
34
34
  import {
35
35
  getStorageStatus,
36
36
  storagePull,
@@ -8,7 +8,7 @@ import {
8
8
  redactValue,
9
9
  saveSnapshot,
10
10
  touchPage
11
- } from "./index-mx0f61s2.js";
11
+ } from "./index-he072p17.js";
12
12
  import {
13
13
  getEventStoreDataDir
14
14
  } from "./index-t3x838zw.js";
@@ -658,6 +658,12 @@ function redactString(input, path = "$") {
658
658
  if (matched)
659
659
  fields.push(`${path}:${label}`);
660
660
  }
661
+ const cookieResult = redactCookieHeaderText(output);
662
+ if (cookieResult.replacements > 0) {
663
+ output = cookieResult.value;
664
+ fields.push(`${path}:cookie_header`);
665
+ replacements += cookieResult.replacements;
666
+ }
661
667
  return {
662
668
  value: output,
663
669
  report: { applied: replacements > 0, fields, replacements }
@@ -726,6 +732,191 @@ function redactionMetadata(report) {
726
732
  function emptyReport() {
727
733
  return { applied: false, fields: [], replacements: 0 };
728
734
  }
735
+ function redactCookieHeaderText(input) {
736
+ const ranges = [];
737
+ const keyPattern = /set-cookie|cookie/gi;
738
+ let match = keyPattern.exec(input);
739
+ while (match) {
740
+ const keyStart = match.index;
741
+ const keyEnd = keyStart + match[0].length;
742
+ if (hasCookieKeyBoundary(input, keyStart, keyEnd)) {
743
+ const quotedKey = parseQuotedKeyContext(input, keyStart, keyEnd);
744
+ if (quotedKey) {
745
+ const afterKey = skipHorizontalWhitespace(input, quotedKey.afterKey);
746
+ if (input[afterKey] === ":") {
747
+ collectCookieMapValueRanges(input, afterKey + 1, ranges);
748
+ match = keyPattern.exec(input);
749
+ continue;
750
+ }
751
+ if (input[afterKey] === ",") {
752
+ const value = parseQuotedString(input, skipHorizontalWhitespace(input, afterKey + 1));
753
+ if (value)
754
+ ranges.push(quotedStringRange(value));
755
+ match = keyPattern.exec(input);
756
+ continue;
757
+ }
758
+ }
759
+ collectPlainCookieHeaderRange(input, keyEnd, ranges);
760
+ }
761
+ match = keyPattern.exec(input);
762
+ }
763
+ return applyReplacementRanges(input, ranges);
764
+ }
765
+ function hasCookieKeyBoundary(input, start, end) {
766
+ return !isCookieKeyCharacter(input[start - 1]) && !isCookieKeyCharacter(input[end]);
767
+ }
768
+ function isCookieKeyCharacter(value) {
769
+ return value !== undefined && /[A-Za-z0-9_-]/.test(value);
770
+ }
771
+ function parseQuotedKeyContext(input, start, end) {
772
+ const before = readQuoteBefore(input, start);
773
+ const after = readQuoteAt(input, end);
774
+ if (!before || !after)
775
+ return null;
776
+ if (before.quote !== after.quote || before.escaped !== after.escaped) {
777
+ return null;
778
+ }
779
+ return { afterKey: end + after.length };
780
+ }
781
+ function collectCookieMapValueRanges(input, start, ranges) {
782
+ const valueStart = skipHorizontalWhitespace(input, start);
783
+ if (input[valueStart] === "[") {
784
+ collectQuotedArrayValueRanges(input, valueStart, ranges);
785
+ return;
786
+ }
787
+ const value = parseQuotedString(input, valueStart);
788
+ if (value)
789
+ ranges.push(quotedStringRange(value));
790
+ }
791
+ function collectQuotedArrayValueRanges(input, start, ranges) {
792
+ let index = start + 1;
793
+ while (index < input.length) {
794
+ index = skipHorizontalWhitespace(input, index);
795
+ if (input[index] === "]" || isLineBreak(input[index]))
796
+ return;
797
+ const value = parseQuotedString(input, index);
798
+ if (value) {
799
+ ranges.push(quotedStringRange(value));
800
+ index = value.end;
801
+ continue;
802
+ }
803
+ index += 1;
804
+ }
805
+ }
806
+ function collectPlainCookieHeaderRange(input, start, ranges) {
807
+ let index = skipHorizontalWhitespace(input, start);
808
+ if (input[index] !== ":" && input[index] !== "=")
809
+ return;
810
+ index = skipHorizontalWhitespace(input, index + 1);
811
+ const end = findLineEnd(input, index);
812
+ if (end > index)
813
+ ranges.push({ start: index, end });
814
+ }
815
+ function parseQuotedString(input, start) {
816
+ const open = readQuoteAt(input, start);
817
+ if (!open)
818
+ return null;
819
+ const contentStart = start + open.length;
820
+ const closeStart = findClosingQuote(input, contentStart, open);
821
+ if (closeStart === null)
822
+ return null;
823
+ return {
824
+ contentStart,
825
+ contentEnd: closeStart,
826
+ end: closeStart + open.length
827
+ };
828
+ }
829
+ function quotedStringRange(value) {
830
+ return { start: value.contentStart, end: value.contentEnd };
831
+ }
832
+ function findClosingQuote(input, start, token) {
833
+ let index = start;
834
+ while (index < input.length) {
835
+ if (isLineBreak(input[index]))
836
+ return null;
837
+ if (token.escaped) {
838
+ if (input[index] === "\\" && input[index + 1] === token.quote) {
839
+ const slashCount = countContiguousBackslashesEndingAt(input, index);
840
+ if (slashCount === 1)
841
+ return index;
842
+ index += 2;
843
+ continue;
844
+ }
845
+ index += 1;
846
+ continue;
847
+ }
848
+ if (input[index] === "\\") {
849
+ index += 2;
850
+ continue;
851
+ }
852
+ if (input[index] === token.quote)
853
+ return index;
854
+ index += 1;
855
+ }
856
+ return null;
857
+ }
858
+ function readQuoteBefore(input, index) {
859
+ const escapedQuote = input.slice(index - 2, index);
860
+ if (escapedQuote === "\\\"" || escapedQuote === "\\'") {
861
+ return { quote: escapedQuote[1], escaped: true, length: 2 };
862
+ }
863
+ const quote = input[index - 1];
864
+ return quote === '"' || quote === "'" ? { quote, escaped: false, length: 1 } : null;
865
+ }
866
+ function readQuoteAt(input, index) {
867
+ const escapedQuote = input.slice(index, index + 2);
868
+ if (escapedQuote === "\\\"" || escapedQuote === "\\'") {
869
+ return { quote: escapedQuote[1], escaped: true, length: 2 };
870
+ }
871
+ const quote = input[index];
872
+ return quote === '"' || quote === "'" ? { quote, escaped: false, length: 1 } : null;
873
+ }
874
+ function skipHorizontalWhitespace(input, start) {
875
+ let index = start;
876
+ while (input[index] === " " || input[index] === "\t")
877
+ index += 1;
878
+ return index;
879
+ }
880
+ function findLineEnd(input, start) {
881
+ let index = start;
882
+ while (index < input.length && !isLineBreak(input[index]))
883
+ index += 1;
884
+ return index;
885
+ }
886
+ function isLineBreak(value) {
887
+ return value === `
888
+ ` || value === "\r";
889
+ }
890
+ function countContiguousBackslashesEndingAt(input, index) {
891
+ let count = 0;
892
+ let cursor = index;
893
+ while (cursor >= 0 && input[cursor] === "\\") {
894
+ count += 1;
895
+ cursor -= 1;
896
+ }
897
+ return count;
898
+ }
899
+ function applyReplacementRanges(input, ranges) {
900
+ const sorted = ranges.filter((range) => range.end > range.start).sort((a, b) => a.start - b.start);
901
+ const deduped = [];
902
+ let lastEnd = -1;
903
+ for (const range of sorted) {
904
+ if (range.start < lastEnd)
905
+ continue;
906
+ deduped.push(range);
907
+ lastEnd = range.end;
908
+ }
909
+ let value = input;
910
+ let replacements = 0;
911
+ for (let index = deduped.length - 1;index >= 0; index -= 1) {
912
+ const range = deduped[index];
913
+ if (value.slice(range.start, range.end) === REDACTED)
914
+ continue;
915
+ value = `${value.slice(0, range.start)}${REDACTED}${value.slice(range.end)}`;
916
+ replacements += 1;
917
+ }
918
+ return { value, replacements };
919
+ }
729
920
  function isSensitiveFlag(value) {
730
921
  const normalized = value.trim().replace(/^-+/, "");
731
922
  if (!normalized || normalized.includes("="))
package/dist/mcp/index.js CHANGED
@@ -93,7 +93,7 @@ import {
93
93
  searchTestReports,
94
94
  summarizeLogs,
95
95
  validateUniversalEventInput
96
- } from "../index-mx0f61s2.js";
96
+ } from "../index-he072p17.js";
97
97
  import {
98
98
  getStoragePg,
99
99
  getStorageStatus,
@@ -8,7 +8,7 @@ import {
8
8
  startScheduler,
9
9
  structuredLogPayloadToEntries,
10
10
  validateStructuredLogReferences
11
- } from "../index-k9w7zfsv.js";
11
+ } from "../index-a0gz0zzc.js";
12
12
  import {
13
13
  countLogs
14
14
  } from "../index-gcd14q2f.js";
@@ -50,7 +50,7 @@ import {
50
50
  updateAlertRule,
51
51
  updateProject,
52
52
  validateUniversalEventInput
53
- } from "../index-mx0f61s2.js";
53
+ } from "../index-he072p17.js";
54
54
  import {
55
55
  getDb,
56
56
  getIssue,
@@ -2148,12 +2148,12 @@ function isLocalOpenModeEnabled() {
2148
2148
  }
2149
2149
  function isTrustedLocalRequest(c) {
2150
2150
  const url = new URL(c.req.url);
2151
- const host = forwardedHost(c.req.header("x-forwarded-host")) ?? hostWithoutPort(c.req.header("host")) ?? url.hostname;
2152
- return isLocalHost(host) && isLocalOrigin(c.req.header("origin"));
2153
- }
2154
- function forwardedHost(value) {
2155
- const first = value?.split(",")[0]?.trim();
2156
- return first ? hostWithoutPort(first) : null;
2151
+ const hosts = [
2152
+ hostWithoutPort(c.req.header("host")),
2153
+ url.hostname,
2154
+ ...forwardedHosts(c.req.header("x-forwarded-host"))
2155
+ ].filter((host) => Boolean(host));
2156
+ return hosts.length > 0 && hosts.every((host) => isLocalHost(host)) && isLocalOrigin(c.req.header("origin"));
2157
2157
  }
2158
2158
  function hostWithoutPort(value) {
2159
2159
  if (!value)
@@ -2162,6 +2162,9 @@ function hostWithoutPort(value) {
2162
2162
  return value.slice(1, value.indexOf("]"));
2163
2163
  return value.split(":")[0] || null;
2164
2164
  }
2165
+ function forwardedHosts(value) {
2166
+ return value?.split(",").map((host) => hostWithoutPort(host.trim())).filter((host) => Boolean(host)) ?? [];
2167
+ }
2165
2168
  function isLocalOrigin(origin) {
2166
2169
  if (!origin)
2167
2170
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/logs",
3
- "version": "0.3.30",
3
+ "version": "0.3.32",
4
4
  "description": "Log aggregation + browser script + headless page scanner + performance monitoring for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",