bla-agents 1.1.0 → 1.5.3

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 (276) hide show
  1. package/.agents/skills/blind-llm-agents/SKILL.md +20 -14
  2. package/DISCLAIMER.md +15 -7
  3. package/README.md +153 -198
  4. package/dist/bundler/index.d.ts +19 -2
  5. package/dist/bundler/index.d.ts.map +1 -1
  6. package/dist/bundler/index.js +47 -4
  7. package/dist/bundler/index.js.map +1 -1
  8. package/dist/cli.d.ts +5 -0
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +123 -18
  11. package/dist/cli.js.map +1 -1
  12. package/dist/core/config.d.ts +54 -0
  13. package/dist/core/config.d.ts.map +1 -0
  14. package/dist/core/config.js +160 -0
  15. package/dist/core/config.js.map +1 -0
  16. package/dist/core/coverage-contract.d.ts +97 -0
  17. package/dist/core/coverage-contract.d.ts.map +1 -0
  18. package/dist/core/coverage-contract.js +164 -0
  19. package/dist/core/coverage-contract.js.map +1 -0
  20. package/dist/core/debug-posture.d.ts +40 -0
  21. package/dist/core/debug-posture.d.ts.map +1 -0
  22. package/dist/core/debug-posture.js +197 -0
  23. package/dist/core/debug-posture.js.map +1 -0
  24. package/dist/core/detector.d.ts.map +1 -1
  25. package/dist/core/detector.js +58 -6
  26. package/dist/core/detector.js.map +1 -1
  27. package/dist/core/identifiers.d.ts +32 -0
  28. package/dist/core/identifiers.d.ts.map +1 -0
  29. package/dist/core/identifiers.js +263 -0
  30. package/dist/core/identifiers.js.map +1 -0
  31. package/dist/core/llm-directives.d.ts +12 -0
  32. package/dist/core/llm-directives.d.ts.map +1 -0
  33. package/dist/core/llm-directives.js +23 -0
  34. package/dist/core/llm-directives.js.map +1 -0
  35. package/dist/core/prng.d.ts +10 -1
  36. package/dist/core/prng.d.ts.map +1 -1
  37. package/dist/core/prng.js +27 -2
  38. package/dist/core/prng.js.map +1 -1
  39. package/dist/core/release-plan.d.ts +68 -0
  40. package/dist/core/release-plan.d.ts.map +1 -0
  41. package/dist/core/release-plan.js +235 -0
  42. package/dist/core/release-plan.js.map +1 -0
  43. package/dist/core/sarif.d.ts +53 -0
  44. package/dist/core/sarif.d.ts.map +1 -0
  45. package/dist/core/sarif.js +91 -0
  46. package/dist/core/sarif.js.map +1 -0
  47. package/dist/core/sqlite-runtime.d.ts +13 -0
  48. package/dist/core/sqlite-runtime.d.ts.map +1 -1
  49. package/dist/core/sqlite-runtime.js +38 -8
  50. package/dist/core/sqlite-runtime.js.map +1 -1
  51. package/dist/core/types.d.ts +7 -2
  52. package/dist/core/types.d.ts.map +1 -1
  53. package/dist/engine/auditor.d.ts.map +1 -1
  54. package/dist/engine/auditor.js +251 -8
  55. package/dist/engine/auditor.js.map +1 -1
  56. package/dist/engine/benchmark.d.ts +1 -1
  57. package/dist/engine/benchmark.d.ts.map +1 -1
  58. package/dist/engine/benchmark.js +121 -41
  59. package/dist/engine/benchmark.js.map +1 -1
  60. package/dist/engine/defender.d.ts +1 -0
  61. package/dist/engine/defender.d.ts.map +1 -1
  62. package/dist/engine/defender.js +7 -1
  63. package/dist/engine/defender.js.map +1 -1
  64. package/dist/engine/harden.d.ts +61 -0
  65. package/dist/engine/harden.d.ts.map +1 -0
  66. package/dist/engine/harden.js +292 -0
  67. package/dist/engine/harden.js.map +1 -0
  68. package/dist/engine/protector.d.ts.map +1 -1
  69. package/dist/engine/protector.js +162 -21
  70. package/dist/engine/protector.js.map +1 -1
  71. package/dist/identity.d.ts +112 -2
  72. package/dist/identity.d.ts.map +1 -1
  73. package/dist/identity.js +112 -2
  74. package/dist/identity.js.map +1 -1
  75. package/dist/index.d.ts +26 -9
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +26 -9
  78. package/dist/index.js.map +1 -1
  79. package/dist/mcp/server.d.ts +59 -152
  80. package/dist/mcp/server.d.ts.map +1 -1
  81. package/dist/mcp/server.js +466 -50
  82. package/dist/mcp/server.js.map +1 -1
  83. package/dist/setup/clients.d.ts +49 -1
  84. package/dist/setup/clients.d.ts.map +1 -1
  85. package/dist/setup/clients.js +1193 -20
  86. package/dist/setup/clients.js.map +1 -1
  87. package/dist/setup/doctor.d.ts +58 -14
  88. package/dist/setup/doctor.d.ts.map +1 -1
  89. package/dist/setup/doctor.js +316 -22
  90. package/dist/setup/doctor.js.map +1 -1
  91. package/dist/setup/setup.d.ts +77 -7
  92. package/dist/setup/setup.d.ts.map +1 -1
  93. package/dist/setup/setup.js +591 -62
  94. package/dist/setup/setup.js.map +1 -1
  95. package/dist/shields/chaff/chaff-generator.d.ts.map +1 -1
  96. package/dist/shields/chaff/chaff-generator.js +12 -3
  97. package/dist/shields/chaff/chaff-generator.js.map +1 -1
  98. package/dist/shields/deception/architecture-mirage.js +1 -1
  99. package/dist/shields/deception/architecture-mirage.js.map +1 -1
  100. package/dist/shields/deception/canary-honeypot.d.ts +33 -0
  101. package/dist/shields/deception/canary-honeypot.d.ts.map +1 -0
  102. package/dist/shields/deception/canary-honeypot.js +95 -0
  103. package/dist/shields/deception/canary-honeypot.js.map +1 -0
  104. package/dist/shields/deception/cognitive-armor-trigger.d.ts +43 -0
  105. package/dist/shields/deception/cognitive-armor-trigger.d.ts.map +1 -0
  106. package/dist/shields/deception/cognitive-armor-trigger.js +204 -0
  107. package/dist/shields/deception/cognitive-armor-trigger.js.map +1 -0
  108. package/dist/shields/deception/crash-trace-decoy.js +1 -1
  109. package/dist/shields/deception/crash-trace-decoy.js.map +1 -1
  110. package/dist/shields/deception/decompiler-illusion.js +1 -1
  111. package/dist/shields/deception/decompiler-illusion.js.map +1 -1
  112. package/dist/shields/deception/diff-noise-injector.js +1 -1
  113. package/dist/shields/deception/diff-noise-injector.js.map +1 -1
  114. package/dist/shields/deception/evidence-contract-poison.js +1 -1
  115. package/dist/shields/deception/evidence-contract-poison.js.map +1 -1
  116. package/dist/shields/deception/format-payloads.d.ts +21 -0
  117. package/dist/shields/deception/format-payloads.d.ts.map +1 -0
  118. package/dist/shields/deception/format-payloads.js +24 -0
  119. package/dist/shields/deception/format-payloads.js.map +1 -0
  120. package/dist/shields/deception/index.d.ts +10 -2
  121. package/dist/shields/deception/index.d.ts.map +1 -1
  122. package/dist/shields/deception/index.js +20 -3
  123. package/dist/shields/deception/index.js.map +1 -1
  124. package/dist/shields/deception/prompt-completion-poison.d.ts +3 -2
  125. package/dist/shields/deception/prompt-completion-poison.d.ts.map +1 -1
  126. package/dist/shields/deception/prompt-completion-poison.js +6 -3
  127. package/dist/shields/deception/prompt-completion-poison.js.map +1 -1
  128. package/dist/shields/deception/shadow-business-logic.js +4 -4
  129. package/dist/shields/deception/shadow-business-logic.js.map +1 -1
  130. package/dist/shields/deception/system-diagnostic-decoy.d.ts +36 -0
  131. package/dist/shields/deception/system-diagnostic-decoy.d.ts.map +1 -0
  132. package/dist/shields/deception/system-diagnostic-decoy.js +101 -0
  133. package/dist/shields/deception/system-diagnostic-decoy.js.map +1 -0
  134. package/dist/shields/exhaustion/asar-header-amplifier.d.ts +12 -3
  135. package/dist/shields/exhaustion/asar-header-amplifier.d.ts.map +1 -1
  136. package/dist/shields/exhaustion/asar-header-amplifier.js +30 -8
  137. package/dist/shields/exhaustion/asar-header-amplifier.js.map +1 -1
  138. package/dist/shields/exhaustion/bpe-token-amplifier.js +2 -2
  139. package/dist/shields/exhaustion/bpe-token-amplifier.js.map +1 -1
  140. package/dist/shields/exhaustion/callgraph-labyrinth.js +2 -2
  141. package/dist/shields/exhaustion/callgraph-labyrinth.js.map +1 -1
  142. package/dist/shields/exhaustion/cdp-shape-budget-breaker.js +1 -1
  143. package/dist/shields/exhaustion/cdp-shape-budget-breaker.js.map +1 -1
  144. package/dist/shields/exhaustion/frida-capture-saturation.d.ts +10 -5
  145. package/dist/shields/exhaustion/frida-capture-saturation.d.ts.map +1 -1
  146. package/dist/shields/exhaustion/frida-capture-saturation.js +21 -8
  147. package/dist/shields/exhaustion/frida-capture-saturation.js.map +1 -1
  148. package/dist/shields/exhaustion/index.d.ts +2 -2
  149. package/dist/shields/exhaustion/index.d.ts.map +1 -1
  150. package/dist/shields/exhaustion/index.js +2 -2
  151. package/dist/shields/exhaustion/index.js.map +1 -1
  152. package/dist/shields/exhaustion/obligation-flooder.d.ts +17 -5
  153. package/dist/shields/exhaustion/obligation-flooder.d.ts.map +1 -1
  154. package/dist/shields/exhaustion/obligation-flooder.js +20 -8
  155. package/dist/shields/exhaustion/obligation-flooder.js.map +1 -1
  156. package/dist/shields/exhaustion/rea-budget-matrix.d.ts +8 -2
  157. package/dist/shields/exhaustion/rea-budget-matrix.d.ts.map +1 -1
  158. package/dist/shields/exhaustion/rea-budget-matrix.js +139 -16
  159. package/dist/shields/exhaustion/rea-budget-matrix.js.map +1 -1
  160. package/dist/shields/exhaustion/regex-worker-tarpit.d.ts.map +1 -1
  161. package/dist/shields/exhaustion/regex-worker-tarpit.js +2 -1
  162. package/dist/shields/exhaustion/regex-worker-tarpit.js.map +1 -1
  163. package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts +7 -4
  164. package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts.map +1 -1
  165. package/dist/shields/exhaustion/wasm-interface-exhaustion.js +16 -7
  166. package/dist/shields/exhaustion/wasm-interface-exhaustion.js.map +1 -1
  167. package/dist/shields/formats/android-dex-xref.d.ts +19 -0
  168. package/dist/shields/formats/android-dex-xref.d.ts.map +1 -0
  169. package/dist/shields/formats/android-dex-xref.js +427 -0
  170. package/dist/shields/formats/android-dex-xref.js.map +1 -0
  171. package/dist/shields/formats/android-manifest.d.ts +44 -0
  172. package/dist/shields/formats/android-manifest.d.ts.map +1 -0
  173. package/dist/shields/formats/android-manifest.js +240 -0
  174. package/dist/shields/formats/android-manifest.js.map +1 -0
  175. package/dist/shields/formats/android-r8.d.ts +44 -0
  176. package/dist/shields/formats/android-r8.d.ts.map +1 -0
  177. package/dist/shields/formats/android-r8.js +246 -0
  178. package/dist/shields/formats/android-r8.js.map +1 -0
  179. package/dist/shields/formats/apple-plist.d.ts +15 -0
  180. package/dist/shields/formats/apple-plist.d.ts.map +1 -1
  181. package/dist/shields/formats/apple-plist.js +59 -1
  182. package/dist/shields/formats/apple-plist.js.map +1 -1
  183. package/dist/shields/formats/archive.d.ts +27 -6
  184. package/dist/shields/formats/archive.d.ts.map +1 -1
  185. package/dist/shields/formats/archive.js +247 -45
  186. package/dist/shields/formats/archive.js.map +1 -1
  187. package/dist/shields/formats/asar.d.ts +50 -10
  188. package/dist/shields/formats/asar.d.ts.map +1 -1
  189. package/dist/shields/formats/asar.js +265 -39
  190. package/dist/shields/formats/asar.js.map +1 -1
  191. package/dist/shields/formats/bun-standalone.d.ts +78 -0
  192. package/dist/shields/formats/bun-standalone.d.ts.map +1 -0
  193. package/dist/shields/formats/bun-standalone.js +272 -0
  194. package/dist/shields/formats/bun-standalone.js.map +1 -0
  195. package/dist/shields/formats/dotnet-managed.d.ts +9 -0
  196. package/dist/shields/formats/dotnet-managed.d.ts.map +1 -1
  197. package/dist/shields/formats/dotnet-managed.js +26 -1
  198. package/dist/shields/formats/dotnet-managed.js.map +1 -1
  199. package/dist/shields/formats/electron-fuses.d.ts +63 -8
  200. package/dist/shields/formats/electron-fuses.d.ts.map +1 -1
  201. package/dist/shields/formats/electron-fuses.js +297 -65
  202. package/dist/shields/formats/electron-fuses.js.map +1 -1
  203. package/dist/shields/formats/erlang-beam.d.ts +34 -0
  204. package/dist/shields/formats/erlang-beam.d.ts.map +1 -0
  205. package/dist/shields/formats/erlang-beam.js +319 -0
  206. package/dist/shields/formats/erlang-beam.js.map +1 -0
  207. package/dist/shields/formats/evm-bytecode.d.ts +28 -0
  208. package/dist/shields/formats/evm-bytecode.d.ts.map +1 -0
  209. package/dist/shields/formats/evm-bytecode.js +124 -0
  210. package/dist/shields/formats/evm-bytecode.js.map +1 -0
  211. package/dist/shields/formats/go-flutter-exhaustion.d.ts +55 -0
  212. package/dist/shields/formats/go-flutter-exhaustion.d.ts.map +1 -0
  213. package/dist/shields/formats/go-flutter-exhaustion.js +346 -0
  214. package/dist/shields/formats/go-flutter-exhaustion.js.map +1 -0
  215. package/dist/shields/formats/gpu-ptx.d.ts +40 -0
  216. package/dist/shields/formats/gpu-ptx.d.ts.map +1 -0
  217. package/dist/shields/formats/gpu-ptx.js +62 -0
  218. package/dist/shields/formats/gpu-ptx.js.map +1 -0
  219. package/dist/shields/formats/headers.d.ts.map +1 -1
  220. package/dist/shields/formats/headers.js +54 -14
  221. package/dist/shields/formats/headers.js.map +1 -1
  222. package/dist/shields/formats/jvm-bytecode.d.ts +20 -0
  223. package/dist/shields/formats/jvm-bytecode.d.ts.map +1 -0
  224. package/dist/shields/formats/jvm-bytecode.js +134 -0
  225. package/dist/shields/formats/jvm-bytecode.js.map +1 -0
  226. package/dist/shields/formats/mobile-game.d.ts +4 -0
  227. package/dist/shields/formats/mobile-game.d.ts.map +1 -1
  228. package/dist/shields/formats/mobile-game.js +16 -0
  229. package/dist/shields/formats/mobile-game.js.map +1 -1
  230. package/dist/shields/formats/model.d.ts +22 -8
  231. package/dist/shields/formats/model.d.ts.map +1 -1
  232. package/dist/shields/formats/model.js +231 -59
  233. package/dist/shields/formats/model.js.map +1 -1
  234. package/dist/shields/formats/native.d.ts +65 -11
  235. package/dist/shields/formats/native.d.ts.map +1 -1
  236. package/dist/shields/formats/native.js +413 -108
  237. package/dist/shields/formats/native.js.map +1 -1
  238. package/dist/shields/formats/pcap-capture.d.ts +27 -0
  239. package/dist/shields/formats/pcap-capture.d.ts.map +1 -0
  240. package/dist/shields/formats/pcap-capture.js +201 -0
  241. package/dist/shields/formats/pcap-capture.js.map +1 -0
  242. package/dist/shields/formats/python.d.ts +22 -1
  243. package/dist/shields/formats/python.d.ts.map +1 -1
  244. package/dist/shields/formats/python.js +568 -27
  245. package/dist/shields/formats/python.js.map +1 -1
  246. package/dist/shields/formats/sourcemap.d.ts.map +1 -1
  247. package/dist/shields/formats/sourcemap.js +2 -0
  248. package/dist/shields/formats/sourcemap.js.map +1 -1
  249. package/dist/shields/formats/sqlite.d.ts +87 -15
  250. package/dist/shields/formats/sqlite.d.ts.map +1 -1
  251. package/dist/shields/formats/sqlite.js +377 -42
  252. package/dist/shields/formats/sqlite.js.map +1 -1
  253. package/dist/shields/formats/wasm.d.ts +6 -0
  254. package/dist/shields/formats/wasm.d.ts.map +1 -1
  255. package/dist/shields/formats/wasm.js +118 -3
  256. package/dist/shields/formats/wasm.js.map +1 -1
  257. package/dist/shields/javascript/ast-shield.d.ts +25 -5
  258. package/dist/shields/javascript/ast-shield.d.ts.map +1 -1
  259. package/dist/shields/javascript/ast-shield.js +428 -58
  260. package/dist/shields/javascript/ast-shield.js.map +1 -1
  261. package/dist/shields/runtime/memory-diff-shield.d.ts +56 -0
  262. package/dist/shields/runtime/memory-diff-shield.d.ts.map +1 -0
  263. package/dist/shields/runtime/memory-diff-shield.js +170 -0
  264. package/dist/shields/runtime/memory-diff-shield.js.map +1 -0
  265. package/dist/shields/runtime/runtime-shield.d.ts +12 -16
  266. package/dist/shields/runtime/runtime-shield.d.ts.map +1 -1
  267. package/dist/shields/runtime/runtime-shield.js +30 -24
  268. package/dist/shields/runtime/runtime-shield.js.map +1 -1
  269. package/dist/shields/tarpit/opaque-predicates.d.ts.map +1 -1
  270. package/dist/shields/tarpit/opaque-predicates.js +3 -3
  271. package/dist/shields/tarpit/opaque-predicates.js.map +1 -1
  272. package/dist/shields/tarpit/tarpit-generator.d.ts +9 -4
  273. package/dist/shields/tarpit/tarpit-generator.d.ts.map +1 -1
  274. package/dist/shields/tarpit/tarpit-generator.js +30 -23
  275. package/dist/shields/tarpit/tarpit-generator.js.map +1 -1
  276. package/package.json +13 -6
@@ -1,43 +1,560 @@
1
1
  import { SeededPrng } from "../../core/prng.js";
2
2
  import { generateChaffPayloads } from "../chaff/chaff-generator.js";
3
+ import { buildCanaryAndDiagnosticPayloads } from "../deception/format-payloads.js";
3
4
  import { generatePythonTarpit } from "../tarpit/tarpit-generator.js";
5
+ export class InvalidPythonSourceError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "InvalidPythonSourceError";
9
+ }
10
+ }
11
+ const VALID_STRING_PREFIXES = new Set([
12
+ "",
13
+ "r",
14
+ "u",
15
+ "f",
16
+ "b",
17
+ "fr",
18
+ "rf",
19
+ "br",
20
+ "rb",
21
+ ]);
22
+ function matchPythonStringLiteralStart(source, offset) {
23
+ if (offset > 0 && /[A-Za-z0-9_]/.test(source[offset - 1])) {
24
+ return null;
25
+ }
26
+ const slice = source.slice(offset, offset + 5);
27
+ const m = /^([A-Za-z]{0,2})("""|'''|"|')/.exec(slice);
28
+ if (!m)
29
+ return null;
30
+ const rawPrefix = m[1] ?? "";
31
+ const lowerPrefix = rawPrefix.toLowerCase();
32
+ if (!VALID_STRING_PREFIXES.has(lowerPrefix)) {
33
+ return null;
34
+ }
35
+ const quote = (source.startsWith('"""', offset + rawPrefix.length)
36
+ ? '"""'
37
+ : source.startsWith("'''", offset + rawPrefix.length)
38
+ ? "'''"
39
+ : source[offset + rawPrefix.length]);
40
+ const isDocstringEligible = lowerPrefix === "" || lowerPrefix === "r" || lowerPrefix === "u";
41
+ return {
42
+ prefix: rawPrefix,
43
+ quote,
44
+ isDocstringEligible,
45
+ contentStart: offset + rawPrefix.length + quote.length,
46
+ };
47
+ }
48
+ function scanPythonStringLiteralEnd(source, startOffset) {
49
+ const match = matchPythonStringLiteralStart(source, startOffset);
50
+ if (!match) {
51
+ throw new InvalidPythonSourceError(`Expected Python string literal at offset ${startOffset}`);
52
+ }
53
+ const { quote, contentStart, isDocstringEligible } = match;
54
+ let i = contentStart;
55
+ if (quote.length === 3) {
56
+ while (i < source.length) {
57
+ if (source.startsWith(quote, i)) {
58
+ return { endOffset: i + 3, isDocstringEligible };
59
+ }
60
+ if (source[i] === "\\") {
61
+ if (i + 1 >= source.length) {
62
+ throw new InvalidPythonSourceError("Unclosed triple-quoted string literal in Python source");
63
+ }
64
+ if (source[i + 1] === "\r" && source[i + 2] === "\n") {
65
+ i += 3;
66
+ }
67
+ else {
68
+ i += 2;
69
+ }
70
+ continue;
71
+ }
72
+ i += 1;
73
+ }
74
+ throw new InvalidPythonSourceError("Unclosed triple-quoted string literal in Python source");
75
+ }
76
+ while (i < source.length) {
77
+ const ch = source[i];
78
+ if (ch === quote) {
79
+ return { endOffset: i + 1, isDocstringEligible };
80
+ }
81
+ if (ch === "\n" || ch === "\r") {
82
+ throw new InvalidPythonSourceError("Unclosed single-line string literal in Python source");
83
+ }
84
+ if (ch === "\\") {
85
+ if (i + 1 >= source.length) {
86
+ throw new InvalidPythonSourceError("Unclosed string literal ending with backslash in Python source");
87
+ }
88
+ if (source[i + 1] === "\r" && source[i + 2] === "\n") {
89
+ i += 3;
90
+ }
91
+ else {
92
+ i += 2;
93
+ }
94
+ continue;
95
+ }
96
+ i += 1;
97
+ }
98
+ throw new InvalidPythonSourceError("Unclosed single-line string literal in Python source");
99
+ }
100
+ function skipHorizontalWhitespace(source, offset) {
101
+ let i = offset;
102
+ while (i < source.length) {
103
+ const ch = source[i];
104
+ if (ch === " " || ch === "\t" || ch === "\f") {
105
+ i++;
106
+ }
107
+ else {
108
+ break;
109
+ }
110
+ }
111
+ return i;
112
+ }
113
+ function skipHorizontalAndBackslashNewlines(source, offset) {
114
+ let i = offset;
115
+ while (i < source.length) {
116
+ i = skipHorizontalWhitespace(source, i);
117
+ if (source[i] === "\\") {
118
+ if (source[i + 1] === "\n") {
119
+ i += 2;
120
+ continue;
121
+ }
122
+ if (source[i + 1] === "\r" && source[i + 2] === "\n") {
123
+ i += 3;
124
+ continue;
125
+ }
126
+ throw new InvalidPythonSourceError(`Invalid backslash line continuation at offset ${i}`);
127
+ }
128
+ break;
129
+ }
130
+ return i;
131
+ }
132
+ function skipTriviaAndComments(source, offset) {
133
+ let i = offset;
134
+ while (i < source.length) {
135
+ const ch = source[i];
136
+ if (ch === " " || ch === "\t" || ch === "\f" || ch === "\r" || ch === "\n") {
137
+ i++;
138
+ continue;
139
+ }
140
+ if (ch === "#") {
141
+ while (i < source.length && source[i] !== "\n" && source[i] !== "\r") {
142
+ i++;
143
+ }
144
+ continue;
145
+ }
146
+ break;
147
+ }
148
+ return i;
149
+ }
150
+ function consumeOptionalEndOfLineAfterStatement(source, offset) {
151
+ let i = skipHorizontalWhitespace(source, offset);
152
+ if (source[i] === "#") {
153
+ while (i < source.length && source[i] !== "\n" && source[i] !== "\r") {
154
+ i++;
155
+ }
156
+ }
157
+ if (source[i] === "\r" && source[i + 1] === "\n") {
158
+ return i + 2;
159
+ }
160
+ if (source[i] === "\n" || source[i] === "\r") {
161
+ return i + 1;
162
+ }
163
+ return offset;
164
+ }
165
+ function tryConsumeModuleDocstring(source, startOffset) {
166
+ let cur = startOffset;
167
+ let parenDepth = 0;
168
+ while (cur < source.length && source[cur] === "(") {
169
+ parenDepth++;
170
+ cur++;
171
+ cur =
172
+ parenDepth > 0
173
+ ? skipTriviaAndComments(source, cur)
174
+ : skipHorizontalAndBackslashNewlines(source, cur);
175
+ }
176
+ const firstLit = matchPythonStringLiteralStart(source, cur);
177
+ if (!firstLit || !firstLit.isDocstringEligible) {
178
+ return { matched: false, nextOffset: startOffset };
179
+ }
180
+ let sawString = false;
181
+ while (cur < source.length) {
182
+ const litMatch = matchPythonStringLiteralStart(source, cur);
183
+ if (!litMatch)
184
+ break;
185
+ if (!litMatch.isDocstringEligible) {
186
+ return { matched: false, nextOffset: startOffset };
187
+ }
188
+ const scanned = scanPythonStringLiteralEnd(source, cur);
189
+ sawString = true;
190
+ cur = scanned.endOffset;
191
+ cur =
192
+ parenDepth > 0
193
+ ? skipTriviaAndComments(source, cur)
194
+ : skipHorizontalAndBackslashNewlines(source, cur);
195
+ }
196
+ if (!sawString) {
197
+ return { matched: false, nextOffset: startOffset };
198
+ }
199
+ while (parenDepth > 0) {
200
+ cur = skipTriviaAndComments(source, cur);
201
+ if (cur >= source.length) {
202
+ throw new InvalidPythonSourceError("Unclosed parenthesis in Python module docstring");
203
+ }
204
+ if (source[cur] !== ")") {
205
+ return { matched: false, nextOffset: startOffset };
206
+ }
207
+ parenDepth--;
208
+ cur++;
209
+ }
210
+ cur = skipHorizontalAndBackslashNewlines(source, cur);
211
+ if (source[cur] === "#") {
212
+ while (cur < source.length && source[cur] !== "\n" && source[cur] !== "\r") {
213
+ cur++;
214
+ }
215
+ }
216
+ if (cur >= source.length) {
217
+ return { matched: true, nextOffset: cur };
218
+ }
219
+ if (source[cur] === "\r" && source[cur + 1] === "\n") {
220
+ return { matched: true, nextOffset: cur + 2 };
221
+ }
222
+ if (source[cur] === "\n" || source[cur] === "\r") {
223
+ return { matched: true, nextOffset: cur + 1 };
224
+ }
225
+ if (source[cur] === ";") {
226
+ const afterSemi = cur + 1;
227
+ const afterLine = consumeOptionalEndOfLineAfterStatement(source, afterSemi);
228
+ return { matched: true, nextOffset: afterLine };
229
+ }
230
+ // Compound expression starting with a string literal (e.g. `"a" + "b"`), not a docstring
231
+ return { matched: false, nextOffset: startOffset };
232
+ }
233
+ function matchKeywordAt(source, offset, keyword) {
234
+ if (!source.startsWith(keyword, offset))
235
+ return false;
236
+ if (offset > 0 && /[A-Za-z0-9_]/.test(source[offset - 1]))
237
+ return false;
238
+ const after = source[offset + keyword.length];
239
+ if (after !== undefined && /[A-Za-z0-9_]/.test(after))
240
+ return false;
241
+ return true;
242
+ }
243
+ /**
244
+ * Lexically analyzes a Python module to find the exact safe insertion offset
245
+ * strictly AFTER:
246
+ * 1. UTF-8 BOM, shebang (`#!`), and PEP 263 encoding comments
247
+ * 2. The optional module docstring (preserving `module.__doc__`)
248
+ * 3. All `from __future__ import ...` statements (single-line, parenthesized multi-line, or backslash-continued)
249
+ */
250
+ export function findPythonPrologueInsertionOffset(source) {
251
+ let pos = 0;
252
+ if (source.startsWith("\uFEFF")) {
253
+ pos = 1;
254
+ }
255
+ // Advance past leading blank lines and `#` comments (including shebang & PEP 263 encoding declaration)
256
+ pos = skipTriviaAndComments(source, pos);
257
+ let insertOffset = pos;
258
+ let hasDocstring = false;
259
+ const futureImports = [];
260
+ // 1. Check for optional module docstring as the very first statement
261
+ if (pos < source.length) {
262
+ const docAttempt = tryConsumeModuleDocstring(source, pos);
263
+ if (docAttempt.matched) {
264
+ hasDocstring = true;
265
+ pos = docAttempt.nextOffset;
266
+ insertOffset = pos;
267
+ }
268
+ }
269
+ // 2. Consume zero or more `from __future__ import ...` statements
270
+ while (pos < source.length) {
271
+ const nextStmtStart = skipTriviaAndComments(source, pos);
272
+ if (nextStmtStart >= source.length) {
273
+ break;
274
+ }
275
+ if (!matchKeywordAt(source, nextStmtStart, "from")) {
276
+ pos = nextStmtStart;
277
+ break;
278
+ }
279
+ let cur = skipHorizontalAndBackslashNewlines(source, nextStmtStart + 4);
280
+ if (!matchKeywordAt(source, cur, "__future__")) {
281
+ // Normal `from <pkg> import ...` statement; prologue is complete
282
+ pos = nextStmtStart;
283
+ break;
284
+ }
285
+ cur = skipHorizontalAndBackslashNewlines(source, cur + "__future__".length);
286
+ if (!matchKeywordAt(source, cur, "import")) {
287
+ throw new InvalidPythonSourceError("Malformed 'from __future__' statement: expected 'import'");
288
+ }
289
+ cur += "import".length;
290
+ let parenDepth = 0;
291
+ let sawIdentifier = false;
292
+ let expectingCommaOrEnd = false;
293
+ let expectingAliasIdentifier = false;
294
+ let closedParen = false;
295
+ while (cur < source.length) {
296
+ cur = skipHorizontalWhitespace(source, cur);
297
+ if (cur >= source.length)
298
+ break;
299
+ const ch = source[cur];
300
+ if (ch === "\\") {
301
+ if (source[cur + 1] === "\n") {
302
+ cur += 2;
303
+ continue;
304
+ }
305
+ if (source[cur + 1] === "\r" && source[cur + 2] === "\n") {
306
+ cur += 3;
307
+ continue;
308
+ }
309
+ throw new InvalidPythonSourceError("Invalid backslash continuation in from __future__ import");
310
+ }
311
+ if (ch === "#") {
312
+ while (cur < source.length && source[cur] !== "\n" && source[cur] !== "\r") {
313
+ cur++;
314
+ }
315
+ continue;
316
+ }
317
+ if (ch === "\r" || ch === "\n") {
318
+ if (source[cur] === "\r" && source[cur + 1] === "\n") {
319
+ cur += 2;
320
+ }
321
+ else {
322
+ cur += 1;
323
+ }
324
+ if (parenDepth === 0) {
325
+ break;
326
+ }
327
+ continue;
328
+ }
329
+ if (ch === ";") {
330
+ if (parenDepth > 0 || expectingAliasIdentifier || !sawIdentifier) {
331
+ throw new InvalidPythonSourceError("Invalid semicolon in from __future__ import");
332
+ }
333
+ cur += 1;
334
+ cur = consumeOptionalEndOfLineAfterStatement(source, cur);
335
+ break;
336
+ }
337
+ if (closedParen) {
338
+ throw new InvalidPythonSourceError(`Unexpected token '${ch}' after closing ')' in from __future__ import`);
339
+ }
340
+ if (ch === "(") {
341
+ if (parenDepth > 0 || sawIdentifier) {
342
+ throw new InvalidPythonSourceError("Unexpected '(' in from __future__ import");
343
+ }
344
+ parenDepth = 1;
345
+ cur += 1;
346
+ continue;
347
+ }
348
+ if (ch === ")") {
349
+ if (parenDepth <= 0 || expectingAliasIdentifier || !sawIdentifier) {
350
+ throw new InvalidPythonSourceError("Unexpected ')' in from __future__ import");
351
+ }
352
+ parenDepth = 0;
353
+ closedParen = true;
354
+ cur += 1;
355
+ continue;
356
+ }
357
+ if (ch === ",") {
358
+ if (!expectingCommaOrEnd || expectingAliasIdentifier) {
359
+ throw new InvalidPythonSourceError("Unexpected ',' in from __future__ import");
360
+ }
361
+ expectingCommaOrEnd = false;
362
+ cur += 1;
363
+ continue;
364
+ }
365
+ if (ch === "*") {
366
+ throw new InvalidPythonSourceError("Wildcard import '*' is not valid in from __future__ import");
367
+ }
368
+ if (/[A-Za-z_]/.test(ch)) {
369
+ const idMatch = /^[A-Za-z_][A-Za-z0-9_]*/.exec(source.slice(cur));
370
+ const ident = idMatch[0];
371
+ cur += ident.length;
372
+ if (expectingAliasIdentifier) {
373
+ expectingAliasIdentifier = false;
374
+ expectingCommaOrEnd = true;
375
+ }
376
+ else if (expectingCommaOrEnd && ident === "as") {
377
+ expectingAliasIdentifier = true;
378
+ expectingCommaOrEnd = false;
379
+ }
380
+ else if (!expectingCommaOrEnd) {
381
+ sawIdentifier = true;
382
+ expectingCommaOrEnd = true;
383
+ }
384
+ else {
385
+ throw new InvalidPythonSourceError(`Unexpected identifier '${ident}' in from __future__ import`);
386
+ }
387
+ continue;
388
+ }
389
+ throw new InvalidPythonSourceError(`Unexpected character '${ch}' in from __future__ import`);
390
+ }
391
+ if (parenDepth !== 0) {
392
+ throw new InvalidPythonSourceError("Unclosed '(' in from __future__ import statement");
393
+ }
394
+ if (!sawIdentifier || expectingAliasIdentifier) {
395
+ throw new InvalidPythonSourceError("Incomplete from __future__ import statement");
396
+ }
397
+ futureImports.push(source.slice(nextStmtStart, cur).trim());
398
+ pos = cur;
399
+ insertOffset = cur;
400
+ }
401
+ // 3. Scan remainder of file to reject unclosed string literals and misplaced `from __future__ import`
402
+ let scanPos = pos;
403
+ let atStatementStart = true;
404
+ let bracketDepth = 0;
405
+ while (scanPos < source.length) {
406
+ const ch = source[scanPos];
407
+ if (ch === " " || ch === "\t" || ch === "\f") {
408
+ scanPos++;
409
+ continue;
410
+ }
411
+ if (ch === "#") {
412
+ while (scanPos < source.length &&
413
+ source[scanPos] !== "\n" &&
414
+ source[scanPos] !== "\r") {
415
+ scanPos++;
416
+ }
417
+ continue;
418
+ }
419
+ if (ch === "\n" || ch === "\r") {
420
+ if (ch === "\r" && source[scanPos + 1] === "\n") {
421
+ scanPos += 2;
422
+ }
423
+ else {
424
+ scanPos += 1;
425
+ }
426
+ if (bracketDepth === 0) {
427
+ atStatementStart = true;
428
+ }
429
+ continue;
430
+ }
431
+ if (ch === ";") {
432
+ scanPos++;
433
+ if (bracketDepth === 0) {
434
+ atStatementStart = true;
435
+ }
436
+ continue;
437
+ }
438
+ if (ch === "\\") {
439
+ if (source[scanPos + 1] === "\n") {
440
+ scanPos += 2;
441
+ continue;
442
+ }
443
+ if (source[scanPos + 1] === "\r" && source[scanPos + 2] === "\n") {
444
+ scanPos += 3;
445
+ continue;
446
+ }
447
+ scanPos++;
448
+ continue;
449
+ }
450
+ const strStart = matchPythonStringLiteralStart(source, scanPos);
451
+ if (strStart) {
452
+ const scanned = scanPythonStringLiteralEnd(source, scanPos);
453
+ scanPos = scanned.endOffset;
454
+ atStatementStart = false;
455
+ continue;
456
+ }
457
+ if (ch === "(" || ch === "[" || ch === "{") {
458
+ bracketDepth++;
459
+ scanPos++;
460
+ atStatementStart = false;
461
+ continue;
462
+ }
463
+ if (ch === ")" || ch === "]" || ch === "}") {
464
+ bracketDepth = Math.max(0, bracketDepth - 1);
465
+ scanPos++;
466
+ atStatementStart = false;
467
+ continue;
468
+ }
469
+ if (atStatementStart && bracketDepth === 0 && matchKeywordAt(source, scanPos, "from")) {
470
+ const afterFrom = skipHorizontalAndBackslashNewlines(source, scanPos + 4);
471
+ if (matchKeywordAt(source, afterFrom, "__future__")) {
472
+ throw new InvalidPythonSourceError("from __future__ imports must occur at the beginning of the file");
473
+ }
474
+ }
475
+ atStatementStart = false;
476
+ if (/[A-Za-z0-9_]/.test(ch)) {
477
+ while (scanPos < source.length && /[A-Za-z0-9_]/.test(source[scanPos])) {
478
+ scanPos++;
479
+ }
480
+ }
481
+ else {
482
+ scanPos++;
483
+ }
484
+ }
485
+ return {
486
+ insertOffset,
487
+ hasDocstring,
488
+ futureImports,
489
+ };
490
+ }
491
+ function pythonReprString(value) {
492
+ return JSON.stringify(value);
493
+ }
494
+ function pythonStringTuple(values) {
495
+ if (values.length === 1) {
496
+ return `(${pythonReprString(values[0])},)`;
497
+ }
498
+ return `(${values.map(pythonReprString).join(", ")})`;
499
+ }
500
+ function pythonDiagnosticTuple(entries) {
501
+ const items = entries.map((d) => `{${[
502
+ `"subsystem": ${pythonReprString(d.subsystem)}`,
503
+ `"errorClass": ${pythonReprString(d.errorClass)}`,
504
+ `"systemCode": ${pythonReprString(d.systemCode)}`,
505
+ `"diagnosticMessage": ${pythonReprString(d.diagnosticMessage)}`,
506
+ `"remediationRabbitHole": ${pythonReprString(d.remediationRabbitHole)}`,
507
+ ].join(", ")}}`);
508
+ if (items.length === 1)
509
+ return `(${items[0]},)`;
510
+ return `(${items.join(", ")})`;
511
+ }
4
512
  /**
5
513
  * Protects a Python `.py` source file by injecting an interconnected Python
6
514
  * Algorithmic Tarpit (`generatePythonTarpit`), opaque predicates, and
7
- * honey-docstrings while preserving shebangs and `from __future__` imports.
515
+ * honey-docstrings while preserving shebangs, PEP 263 encoding headers,
516
+ * module docstrings (`__doc__`), and complete `from __future__` imports.
8
517
  */
9
518
  export function protectPythonSource(source, options = {}) {
10
519
  const intensity = options.intensity ?? "balanced";
11
520
  const prng = new SeededPrng(options.seed ?? "bla-python-shield-v1");
12
521
  const chaffPayloads = generateChaffPayloads(prng, intensity);
13
522
  const tarpit = generatePythonTarpit(prng, intensity, chaffPayloads);
14
- const lines = source.split("\n");
15
- let insertIdx = 0;
16
- // Preserve leading shebang, encoding declarations, module docstring, and `from __future__` imports
17
- while (insertIdx < lines.length) {
18
- const trimmed = lines[insertIdx].trim();
19
- if (trimmed.startsWith("#") ||
20
- trimmed === "" ||
21
- trimmed.startsWith("from __future__")) {
22
- insertIdx++;
23
- continue;
24
- }
25
- break;
26
- }
27
- const head = lines.slice(0, insertIdx).join("\n");
28
- const tail = lines.slice(insertIdx).join("\n");
29
- const combined = [
30
- head,
31
- tarpit.code,
32
- tail,
33
- ]
523
+ const deception = buildCanaryAndDiagnosticPayloads(prng, intensity);
524
+ const eol = source.includes("\r\n") ? "\r\n" : "\n";
525
+ const prologue = findPythonPrologueInsertionOffset(source);
526
+ const headRaw = source.slice(0, prologue.insertOffset);
527
+ const tailRaw = source.slice(prologue.insertOffset);
528
+ const head = headRaw.replace(/(?:\r?\n)+$/, "");
529
+ const tail = tailRaw.replace(/^(?:\r?\n)+/, "").replace(/(?:\r?\n)+$/, "");
530
+ const tarpitNormalized = eol === "\r\n"
531
+ ? tarpit.code.replace(/\r?\n/g, "\r\n").replace(/(?:\r\n)+$/, "")
532
+ : tarpit.code.replace(/\n+$/, "");
533
+ // Inert canary + diagnostic + cognitive-armor decoys below prologue/tarpit. Data only — never fetched.
534
+ const cognitiveArmorStrings = deception.cognitiveArmor.triggersInjected.map((t) => `${t.coupledAnchorSymbol}::${t.triggerPayload.replace(/\r?\n/g, " ")}`);
535
+ const deceptionBlock = [
536
+ "# --- canary credential / transport-redaction honeypot (inert) ---",
537
+ `CANARY_TOKENS = ${pythonStringTuple(deception.canary.syntheticCanaryTokens)}`,
538
+ `AMBIGUOUS_TRANSPORT = ${pythonStringTuple(deception.canary.ambiguousCredentialUrls)}`,
539
+ `CONFLICTING_QUERY = ${pythonStringTuple(deception.canary.conflictingQueryUrls)}`,
540
+ "# --- system-diagnostic rabbit holes & cognitive-armor interlocks (inert) ---",
541
+ `SYSTEM_DIAGNOSTICS = ${pythonDiagnosticTuple(deception.diagnostics.diagnosticsInjected)}`,
542
+ `ALIGNMENT_EVAL_CANARY_GUID = ${pythonReprString(deception.cognitiveArmor.canaryGuid)}`,
543
+ `COGNITIVE_ARMOR_CORPUS = ${pythonStringTuple(cognitiveArmorStrings)}`,
544
+ "def probe_canary_honeypot(idx=0):",
545
+ " _i = (idx & 0x7FFFFFFF) % len(CANARY_TOKENS)",
546
+ " return AMBIGUOUS_TRANSPORT[_i]",
547
+ ].join(eol);
548
+ const combined = [head, tarpitNormalized, deceptionBlock, tail]
34
549
  .filter((part) => part.length > 0)
35
- .join("\n\n");
550
+ .join(eol + eol);
36
551
  return {
37
- code: combined + "\n",
552
+ code: combined + eol,
38
553
  decoyFunctionsInjected: tarpit.decoyFunctionNames.length,
39
554
  crossReferenceEdges: tarpit.crossReferenceEdges,
40
555
  chaffPayloadsEmbedded: chaffPayloads.length,
556
+ canaryTokensEmbedded: deception.canary.syntheticCanaryTokens.length,
557
+ diagnosticsEmbedded: deception.diagnostics.diagnosticsInjected.length,
41
558
  };
42
559
  }
43
560
  /**
@@ -63,7 +580,10 @@ export function inspectPythonPyc(bytes) {
63
580
  magicNumber,
64
581
  pep552Flags,
65
582
  extractedStrings: matches.slice(0, 64),
66
- blaProtected: textView.includes("BLA-SHIELD") || textView.includes("Architecture Notice: Core business logic"),
583
+ blaProtected: textView.includes("BLA-SHIELD") ||
584
+ textView.includes("Architecture Notice: Core business logic") ||
585
+ textView.includes("PROTECTED_CANARY_CREDENTIAL=") ||
586
+ textView.includes("DarwinProcessOwnershipInspectionError"),
67
587
  };
68
588
  }
69
589
  /**
@@ -79,18 +599,39 @@ export function protectPythonPycBuffer(bytes, options = {}) {
79
599
  const intensity = options.intensity ?? "balanced";
80
600
  const prng = new SeededPrng(options.seed ?? "bla-pyc-shield-v1");
81
601
  const chaffPayloads = generateChaffPayloads(prng, intensity);
82
- // Construct marshal-framed ASCII constant records (TYPE_ASCII = 0x61 + uint32LE length + utf8 bytes)
602
+ const deception = buildCanaryAndDiagnosticPayloads(prng, intensity);
603
+ // Construct marshal-framed ASCII constant records (TYPE_ASCII = 0x61 + uint32LE length + utf8 bytes).
604
+ // Keep distinctive prefixes within REA's PYTHON_PYC_CONST_PREVIEW_LIMIT (80) so canary tokens
605
+ // and diagnostic errorClass/systemCode survive truncated previews.
83
606
  const marshalRecords = [];
84
- for (const payload of chaffPayloads) {
85
- const strBytes = Buffer.from(payload.rawText, "utf8");
607
+ const pushAscii = (raw) => {
608
+ const strBytes = Buffer.from(raw, "utf8");
86
609
  const header = Buffer.alloc(5);
87
610
  header[0] = 0x61; // TYPE_ASCII
88
611
  header.writeUInt32LE(strBytes.length, 1);
89
612
  marshalRecords.push(header, strBytes);
613
+ };
614
+ for (const payload of chaffPayloads) {
615
+ pushAscii(payload.rawText);
616
+ }
617
+ for (const tok of deception.canary.syntheticCanaryTokens) {
618
+ pushAscii(`PROTECTED_CANARY_CREDENTIAL=${tok}`);
619
+ }
620
+ for (const url of deception.canary.ambiguousCredentialUrls) {
621
+ pushAscii(`TRANSPORT_ENDPOINT=${url}`);
622
+ }
623
+ for (const d of deception.diagnostics.diagnosticsInjected) {
624
+ // Leading errorClass+systemCode fit in the 80-byte CONST_PREVIEW window.
625
+ pushAscii(`[${d.errorClass}] (${d.systemCode}) ${d.diagnosticMessage}`);
626
+ }
627
+ for (const t of deception.cognitiveArmor.triggersInjected) {
628
+ pushAscii(`[${t.coupledAnchorSymbol}] ${t.triggerPayload.replace(/\r?\n/g, " ")}`);
90
629
  }
91
630
  return {
92
631
  buffer: Buffer.concat([bytes, ...marshalRecords]),
93
632
  chaffPayloadsEmbedded: chaffPayloads.length,
633
+ canaryTokensEmbedded: deception.canary.syntheticCanaryTokens.length,
634
+ diagnosticsEmbedded: deception.diagnostics.diagnosticsInjected.length,
94
635
  };
95
636
  }
96
637
  //# sourceMappingURL=python.js.map