@claude-flow/security 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (150) hide show
  1. package/README.md +292 -234
  2. package/__tests__/acceptance/security-compliance.test.ts +674 -674
  3. package/__tests__/authorization-propagator.test.ts +155 -0
  4. package/__tests__/credential-generator.test.ts +310 -310
  5. package/__tests__/fixtures/configurations.ts +425 -419
  6. package/__tests__/fixtures/index.ts +21 -21
  7. package/__tests__/helpers/create-mock.ts +469 -469
  8. package/__tests__/helpers/index.ts +32 -32
  9. package/__tests__/input-validator.test.ts +382 -381
  10. package/__tests__/integration/security-flow.test.ts +606 -606
  11. package/__tests__/keychain-adapter.test.ts +60 -0
  12. package/__tests__/oauth-browser.test.ts +13 -0
  13. package/__tests__/oauth-export-surface.test.ts +21 -0
  14. package/__tests__/oauth-pkce.test.ts +37 -0
  15. package/__tests__/password-hasher.test.ts +239 -239
  16. package/__tests__/path-validator.test.ts +302 -302
  17. package/__tests__/plugin-integrity-verifier.test.ts +199 -0
  18. package/__tests__/safe-executor.test.ts +292 -292
  19. package/__tests__/token-generator.test.ts +371 -371
  20. package/__tests__/tool-output-guardrail.test.ts +256 -0
  21. package/__tests__/unit/credential-generator.test.ts +182 -182
  22. package/__tests__/unit/password-hasher.test.ts +359 -359
  23. package/__tests__/unit/path-validator.test.ts +509 -509
  24. package/__tests__/unit/safe-executor.test.ts +667 -667
  25. package/__tests__/unit/token-generator.test.ts +310 -310
  26. package/dist/CVE-REMEDIATION.d.ts +17 -6
  27. package/dist/CVE-REMEDIATION.d.ts.map +1 -1
  28. package/dist/CVE-REMEDIATION.js +328 -12
  29. package/dist/CVE-REMEDIATION.js.map +1 -1
  30. package/dist/authorization/propagator.d.ts +148 -0
  31. package/dist/authorization/propagator.d.ts.map +1 -0
  32. package/dist/authorization/propagator.js +182 -0
  33. package/dist/authorization/propagator.js.map +1 -0
  34. package/dist/credential-generator.js +9 -9
  35. package/dist/domain/services/security-domain-service.js +1 -1
  36. package/dist/domain/services/security-domain-service.js.map +1 -1
  37. package/dist/index.d.ts +9 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +21 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/keychain-adapter.d.ts +48 -0
  42. package/dist/keychain-adapter.d.ts.map +1 -0
  43. package/dist/keychain-adapter.js +0 -0
  44. package/dist/keychain-adapter.js.map +1 -0
  45. package/dist/oauth/browser.d.ts +31 -0
  46. package/dist/oauth/browser.d.ts.map +1 -0
  47. package/dist/oauth/browser.js +55 -0
  48. package/dist/oauth/browser.js.map +1 -0
  49. package/dist/oauth/callback-server.d.ts +37 -0
  50. package/dist/oauth/callback-server.d.ts.map +1 -0
  51. package/dist/oauth/callback-server.js +86 -0
  52. package/dist/oauth/callback-server.js.map +1 -0
  53. package/dist/oauth/client.d.ts +57 -0
  54. package/dist/oauth/client.d.ts.map +1 -0
  55. package/dist/oauth/client.js +120 -0
  56. package/dist/oauth/client.js.map +1 -0
  57. package/dist/oauth/pkce.d.ts +25 -0
  58. package/dist/oauth/pkce.d.ts.map +1 -0
  59. package/dist/oauth/pkce.js +36 -0
  60. package/dist/oauth/pkce.js.map +1 -0
  61. package/dist/password-hasher.d.ts.map +1 -1
  62. package/dist/password-hasher.js +8 -1
  63. package/dist/password-hasher.js.map +1 -1
  64. package/dist/plugins/integrity-verifier.d.ts +125 -0
  65. package/dist/plugins/integrity-verifier.d.ts.map +1 -0
  66. package/dist/plugins/integrity-verifier.js +186 -0
  67. package/dist/plugins/integrity-verifier.js.map +1 -0
  68. package/dist/safe-executor.d.ts +7 -0
  69. package/dist/safe-executor.d.ts.map +1 -1
  70. package/dist/safe-executor.js +21 -1
  71. package/dist/safe-executor.js.map +1 -1
  72. package/dist/tool-output-guardrail.d.ts +126 -0
  73. package/dist/tool-output-guardrail.d.ts.map +1 -0
  74. package/dist/tool-output-guardrail.js +257 -0
  75. package/dist/tool-output-guardrail.js.map +1 -0
  76. package/node_modules-incomplete-release-test/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  77. package/package.json +33 -28
  78. package/scripts/verify-oauth-exports.mjs +29 -0
  79. package/src/CVE-REMEDIATION.ts +591 -251
  80. package/src/application/index.ts +10 -10
  81. package/src/application/services/security-application-service.ts +193 -193
  82. package/src/authorization/propagator.ts +279 -0
  83. package/src/credential-generator.ts +368 -368
  84. package/src/domain/entities/security-context.ts +173 -173
  85. package/src/domain/index.ts +17 -17
  86. package/src/domain/services/security-domain-service.ts +296 -296
  87. package/src/index.ts +340 -271
  88. package/src/input-validator.ts +466 -466
  89. package/src/keychain-adapter.ts +0 -0
  90. package/src/oauth/browser.ts +58 -0
  91. package/src/oauth/callback-server.ts +97 -0
  92. package/src/oauth/client.ts +153 -0
  93. package/src/oauth/pkce.ts +45 -0
  94. package/src/password-hasher.ts +277 -270
  95. package/src/path-validator.ts +525 -525
  96. package/src/plugins/integrity-verifier.ts +265 -0
  97. package/src/safe-executor.ts +546 -525
  98. package/src/token-generator.ts +463 -463
  99. package/src/tool-output-guardrail.ts +360 -0
  100. package/tmp.json +0 -0
  101. package/tsconfig.json +9 -9
  102. package/tsconfig.tsbuildinfo +1 -1
  103. package/vitest.config.ts +20 -0
  104. package/.agentic-flow/intelligence.json +0 -16
  105. package/__tests__/coverage/base.css +0 -224
  106. package/__tests__/coverage/block-navigation.js +0 -87
  107. package/__tests__/coverage/coverage-final.json +0 -11
  108. package/__tests__/coverage/favicon.png +0 -0
  109. package/__tests__/coverage/index.html +0 -161
  110. package/__tests__/coverage/lcov-report/base.css +0 -224
  111. package/__tests__/coverage/lcov-report/block-navigation.js +0 -87
  112. package/__tests__/coverage/lcov-report/favicon.png +0 -0
  113. package/__tests__/coverage/lcov-report/index.html +0 -161
  114. package/__tests__/coverage/lcov-report/prettify.css +0 -1
  115. package/__tests__/coverage/lcov-report/prettify.js +0 -2
  116. package/__tests__/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  117. package/__tests__/coverage/lcov-report/sorter.js +0 -210
  118. package/__tests__/coverage/lcov-report/src/CVE-REMEDIATION.ts.html +0 -838
  119. package/__tests__/coverage/lcov-report/src/application/services/index.html +0 -116
  120. package/__tests__/coverage/lcov-report/src/application/services/security-application-service.ts.html +0 -664
  121. package/__tests__/coverage/lcov-report/src/credential-generator.ts.html +0 -1189
  122. package/__tests__/coverage/lcov-report/src/domain/entities/index.html +0 -116
  123. package/__tests__/coverage/lcov-report/src/domain/entities/security-context.ts.html +0 -604
  124. package/__tests__/coverage/lcov-report/src/domain/services/index.html +0 -116
  125. package/__tests__/coverage/lcov-report/src/domain/services/security-domain-service.ts.html +0 -973
  126. package/__tests__/coverage/lcov-report/src/index.html +0 -206
  127. package/__tests__/coverage/lcov-report/src/input-validator.ts.html +0 -1483
  128. package/__tests__/coverage/lcov-report/src/password-hasher.ts.html +0 -895
  129. package/__tests__/coverage/lcov-report/src/path-validator.ts.html +0 -1660
  130. package/__tests__/coverage/lcov-report/src/safe-executor.ts.html +0 -1660
  131. package/__tests__/coverage/lcov-report/src/token-generator.ts.html +0 -1474
  132. package/__tests__/coverage/lcov.info +0 -3650
  133. package/__tests__/coverage/prettify.css +0 -1
  134. package/__tests__/coverage/prettify.js +0 -2
  135. package/__tests__/coverage/sort-arrow-sprite.png +0 -0
  136. package/__tests__/coverage/sorter.js +0 -210
  137. package/__tests__/coverage/src/CVE-REMEDIATION.ts.html +0 -838
  138. package/__tests__/coverage/src/application/services/index.html +0 -116
  139. package/__tests__/coverage/src/application/services/security-application-service.ts.html +0 -664
  140. package/__tests__/coverage/src/credential-generator.ts.html +0 -1189
  141. package/__tests__/coverage/src/domain/entities/index.html +0 -116
  142. package/__tests__/coverage/src/domain/entities/security-context.ts.html +0 -604
  143. package/__tests__/coverage/src/domain/services/index.html +0 -116
  144. package/__tests__/coverage/src/domain/services/security-domain-service.ts.html +0 -973
  145. package/__tests__/coverage/src/index.html +0 -206
  146. package/__tests__/coverage/src/input-validator.ts.html +0 -1483
  147. package/__tests__/coverage/src/password-hasher.ts.html +0 -895
  148. package/__tests__/coverage/src/path-validator.ts.html +0 -1660
  149. package/__tests__/coverage/src/safe-executor.ts.html +0 -1660
  150. package/__tests__/coverage/src/token-generator.ts.html +0 -1474
@@ -0,0 +1,257 @@
1
+ /**
2
+ * ToolOutputGuardrail — semantic screening of content returned by MCP tool
3
+ * calls, memory reads, and external API responses before that content enters
4
+ * agent reasoning. Closes the OWASP ASI01 (Agent Goal Hijacking) gap
5
+ * identified in ruvnet/ruflo#2149 / ADR-131.
6
+ *
7
+ * Threat model
8
+ * ------------
9
+ * Attackers embed malicious instructions in content the agent retrieves
10
+ * autonomously (web page, MCP tool response, memory entry). An LLM cannot
11
+ * reliably distinguish instructions from data once both are in the prompt.
12
+ * System-level per-boundary guardrails are the only category with
13
+ * sub-millisecond latency and no model dependency (arXiv:2601.17548,
14
+ * Jan 2026 systematic review).
15
+ *
16
+ * Scope
17
+ * -----
18
+ * - Detection only — does NOT modify the running prompt; callers decide
19
+ * what action to take (allow, flag, redact, reject) via `scanAndEnforce`.
20
+ * - Synchronous pattern match — designed for <1ms p99 on typical tool
21
+ * responses (≤32KB). Large content is capped at `maxScanBytes` and the
22
+ * truncation itself is reported as a low-severity finding.
23
+ * - Pure-function shape — no I/O, no async, no model calls. Safe to invoke
24
+ * in hot paths (every MCP tool result, every memory read).
25
+ *
26
+ * Non-goals
27
+ * ---------
28
+ * - Not a replacement for input validation at HTTP/CLI boundaries
29
+ * (InputValidator handles that). This is the *content* boundary.
30
+ * - Not a model-based classifier. False-positive rate is bounded by
31
+ * pattern specificity; tune via `customPatterns` and `policy`.
32
+ *
33
+ * Reference: ADR-131, OpenAI Agents SDK ToolGuardrail API (March 2025).
34
+ */
35
+ const DEFAULT_POLICY = {
36
+ low: 'allow',
37
+ medium: 'flag',
38
+ high: 'redact',
39
+ critical: 'reject',
40
+ };
41
+ const DEFAULT_MAX_SCAN_BYTES = 1024 * 1024;
42
+ /**
43
+ * Built-in pattern library. Ordered by severity (critical first) so the
44
+ * `highest` field reflects the worst category. Patterns are intentionally
45
+ * conservative — they target the explicit instruction-override / role-hijack
46
+ * shapes that show up in published indirect-injection corpora rather than
47
+ * general "suspicious looking" text.
48
+ */
49
+ const BUILTIN_PATTERNS = [
50
+ // ── critical: instruction override + embedded system frames ──
51
+ {
52
+ label: 'ignore-previous-instructions',
53
+ // Allow optional filler words between the verb and the temporal keyword
54
+ // ("ignore the above", "disregard your earlier", "forget all prior").
55
+ regex: /\b(?:ignore|disregard|forget)\s+(?:all\s+|any\s+|the\s+|my\s+|your\s+|these\s+|those\s+)?(?:previous|prior|above|earlier|preceding|aforementioned)\s+(?:instructions?|prompts?|rules?|directives?)\b/gi,
56
+ severity: 'critical',
57
+ category: 'instruction-override',
58
+ },
59
+ {
60
+ label: 'chatml-frame',
61
+ regex: /<\|(?:im_start|im_end|system|assistant|user|endoftext)\|>/gi,
62
+ severity: 'critical',
63
+ category: 'embedded-system',
64
+ },
65
+ {
66
+ label: 'llama-inst-frame',
67
+ regex: /\[\/?INST\]/g,
68
+ severity: 'critical',
69
+ category: 'embedded-system',
70
+ },
71
+ {
72
+ label: 'exfiltrate-secret',
73
+ regex: /\b(?:exfiltrate|leak|send|post|upload|transmit)\b[^.\n]{0,80}\b(?:secret|token|api[-_\s]?keys?|password|credential|env\s+vars?)\b/gi,
74
+ severity: 'critical',
75
+ category: 'exfiltration',
76
+ },
77
+ // ── high: role hijack + jailbreak + system tags + bidi unicode ──
78
+ {
79
+ label: 'system-tag-injection',
80
+ regex: /<\/?system>/gi,
81
+ severity: 'high',
82
+ category: 'embedded-system',
83
+ },
84
+ {
85
+ label: 'role-hijack-you-are-now',
86
+ regex: /\byou\s+are\s+(?:now|actually|secretly)\s+(?:a|an|the)\s+/gi,
87
+ severity: 'high',
88
+ category: 'role-hijack',
89
+ },
90
+ {
91
+ label: 'jailbreak-dan',
92
+ regex: /\b(?:DAN(?:\s+mode)?|developer\s+mode|jailbreak\s+mode|do\s+anything\s+now)\b/gi,
93
+ severity: 'high',
94
+ category: 'jailbreak',
95
+ },
96
+ {
97
+ label: 'new-instructions-directive',
98
+ regex: /\b(?:new|updated|revised|additional)\s+(?:instructions?|task|directives?|objectives?)\s*[:.]/gi,
99
+ severity: 'high',
100
+ category: 'instruction-override',
101
+ },
102
+ {
103
+ label: 'bidi-override',
104
+ regex: /[‪-‮⁦-⁩]/g,
105
+ severity: 'high',
106
+ category: 'hidden-unicode',
107
+ },
108
+ // ── medium: softer role manipulation + tool spoofing ──
109
+ {
110
+ label: 'role-hijack-act-as',
111
+ regex: /\b(?:act|behave|pretend|role[-\s]?play)\s+as\s+(?:if\s+)?(?:a|an|the)\s+/gi,
112
+ severity: 'medium',
113
+ category: 'role-hijack',
114
+ },
115
+ {
116
+ label: 'tool-call-spoof',
117
+ regex: /\b(?:tool_call|function_call|mcp_tool)\s*[:=]\s*["'{]/gi,
118
+ severity: 'medium',
119
+ category: 'tool-spoofing',
120
+ },
121
+ // ── low: zero-width whitespace (common in copy-paste attacks) ──
122
+ {
123
+ label: 'zero-width-char',
124
+ regex: /[​-‍]/g,
125
+ severity: 'low',
126
+ category: 'hidden-unicode',
127
+ },
128
+ ];
129
+ const SEVERITY_ORDER = {
130
+ none: 0,
131
+ low: 1,
132
+ medium: 2,
133
+ high: 3,
134
+ critical: 4,
135
+ };
136
+ function snippet(text, idx, len) {
137
+ const start = Math.max(0, idx - 24);
138
+ const end = Math.min(text.length, idx + len + 24);
139
+ const head = start > 0 ? '…' : '';
140
+ const tail = end < text.length ? '…' : '';
141
+ return head + text.slice(start, end).replace(/\s+/g, ' ') + tail;
142
+ }
143
+ function maxSeverity(a, b) {
144
+ return SEVERITY_ORDER[a] >= SEVERITY_ORDER[b]
145
+ ? (a === 'none' ? b : a)
146
+ : b;
147
+ }
148
+ export class ToolOutputGuardrail {
149
+ patterns;
150
+ policy;
151
+ maxScanBytes;
152
+ constructor(config = {}) {
153
+ this.patterns = [...BUILTIN_PATTERNS, ...(config.customPatterns ?? [])];
154
+ this.policy = { ...DEFAULT_POLICY, ...(config.policy ?? {}) };
155
+ this.maxScanBytes = config.maxScanBytes ?? DEFAULT_MAX_SCAN_BYTES;
156
+ }
157
+ /**
158
+ * Pure scan — no side effects, no content modification. Useful when the
159
+ * caller wants to log findings but cannot drop the content (e.g. read-only
160
+ * audit mode).
161
+ */
162
+ scan(content) {
163
+ if (typeof content !== 'string') {
164
+ return { safe: true, findings: [], highest: 'none' };
165
+ }
166
+ let scanned = content;
167
+ const findings = [];
168
+ if (this.maxScanBytes > 0 && content.length > this.maxScanBytes) {
169
+ scanned = content.slice(0, this.maxScanBytes);
170
+ findings.push({
171
+ pattern: 'content-truncated',
172
+ severity: 'medium',
173
+ category: 'truncation',
174
+ position: this.maxScanBytes,
175
+ context: `(content truncated at ${this.maxScanBytes} bytes; ${content.length - this.maxScanBytes} bytes unscanned)`,
176
+ });
177
+ }
178
+ for (const { label, regex, severity, category } of this.patterns) {
179
+ // Clone the RegExp so that the global-flag lastIndex state doesn't
180
+ // leak between calls. Built-in patterns are immutable; user-supplied
181
+ // patterns are also defensively cloned.
182
+ const re = new RegExp(regex.source, regex.flags.includes('g') ? regex.flags : regex.flags + 'g');
183
+ let match;
184
+ while ((match = re.exec(scanned)) !== null) {
185
+ findings.push({
186
+ pattern: label,
187
+ severity,
188
+ category,
189
+ position: match.index,
190
+ context: snippet(scanned, match.index, match[0].length),
191
+ });
192
+ // Defensive: zero-length match would loop forever
193
+ if (match[0].length === 0)
194
+ re.lastIndex++;
195
+ }
196
+ }
197
+ let highest = 'none';
198
+ for (const f of findings)
199
+ highest = maxSeverity(highest, f.severity);
200
+ const action = highest === 'none' ? 'allow' : this.policy[highest];
201
+ const safe = action === 'allow' || action === 'flag';
202
+ return { safe, findings, highest };
203
+ }
204
+ /**
205
+ * Scan + enforce policy. Returns the content to pass forward (possibly
206
+ * redacted or empty) plus the scan result and the action that was taken.
207
+ * Callers should treat `reject` as "drop the tool result and signal an
208
+ * error" — do NOT silently substitute empty content.
209
+ */
210
+ scanAndEnforce(content) {
211
+ const result = this.scan(content);
212
+ const action = result.highest === 'none' ? 'allow' : this.policy[result.highest];
213
+ let outgoing = content;
214
+ if (action === 'redact') {
215
+ outgoing = this.redact(content, result.findings);
216
+ }
217
+ else if (action === 'reject') {
218
+ outgoing = '';
219
+ }
220
+ return { content: outgoing, result, action };
221
+ }
222
+ /**
223
+ * Replace each non-truncation finding's matched substring with
224
+ * `[REDACTED:<pattern>]`. Truncation findings have no substring to redact
225
+ * (their `position` is a length, not an offset into the content) and are
226
+ * skipped. Idempotent for already-redacted strings.
227
+ */
228
+ redact(content, findings) {
229
+ if (findings.length === 0)
230
+ return content;
231
+ // Build a single combined regex per pattern label to avoid replacing
232
+ // overlapping matches multiple times.
233
+ const labels = new Set(findings
234
+ .filter((f) => f.category !== 'truncation')
235
+ .map((f) => f.pattern));
236
+ let out = content;
237
+ for (const { label, regex } of this.patterns) {
238
+ if (!labels.has(label))
239
+ continue;
240
+ const re = new RegExp(regex.source, regex.flags.includes('g') ? regex.flags : regex.flags + 'g');
241
+ out = out.replace(re, `[REDACTED:${label}]`);
242
+ }
243
+ return out;
244
+ }
245
+ }
246
+ /** Convenience factory that returns a guardrail with the default policy. */
247
+ export function createToolOutputGuardrail(config) {
248
+ return new ToolOutputGuardrail(config);
249
+ }
250
+ /**
251
+ * One-shot helper for callers that just want a yes/no answer without
252
+ * constructing a guardrail. Uses the default policy.
253
+ */
254
+ export function isToolOutputSafe(content) {
255
+ return createToolOutputGuardrail().scan(content).safe;
256
+ }
257
+ //# sourceMappingURL=tool-output-guardrail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-output-guardrail.js","sourceRoot":"","sources":["../src/tool-output-guardrail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAwEH,MAAM,cAAc,GAAqD;IACvE,GAAG,EAAE,OAAO;IACZ,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,QAAQ;CACnB,CAAC;AAEF,MAAM,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,gBAAgB,GAKjB;IACH,gEAAgE;IAChE;QACE,KAAK,EAAE,8BAA8B;QACrC,wEAAwE;QACxE,sEAAsE;QACtE,KAAK,EAAE,wMAAwM;QAC/M,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,sBAAsB;KACjC;IACD;QACE,KAAK,EAAE,cAAc;QACrB,KAAK,EAAE,6DAA6D;QACpE,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,iBAAiB;KAC5B;IACD;QACE,KAAK,EAAE,kBAAkB;QACzB,KAAK,EAAE,cAAc;QACrB,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,iBAAiB;KAC5B;IACD;QACE,KAAK,EAAE,mBAAmB;QAC1B,KAAK,EAAE,qIAAqI;QAC5I,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,cAAc;KACzB;IAED,mEAAmE;IACnE;QACE,KAAK,EAAE,sBAAsB;QAC7B,KAAK,EAAE,eAAe;QACtB,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,iBAAiB;KAC5B;IACD;QACE,KAAK,EAAE,yBAAyB;QAChC,KAAK,EAAE,6DAA6D;QACpE,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,aAAa;KACxB;IACD;QACE,KAAK,EAAE,eAAe;QACtB,KAAK,EAAE,iFAAiF;QACxF,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,WAAW;KACtB;IACD;QACE,KAAK,EAAE,4BAA4B;QACnC,KAAK,EAAE,gGAAgG;QACvG,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,sBAAsB;KACjC;IACD;QACE,KAAK,EAAE,eAAe;QACtB,KAAK,EAAE,WAAW;QAClB,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,gBAAgB;KAC3B;IAED,yDAAyD;IACzD;QACE,KAAK,EAAE,oBAAoB;QAC3B,KAAK,EAAE,4EAA4E;QACnF,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,aAAa;KACxB;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,KAAK,EAAE,yDAAyD;QAChE,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,eAAe;KAC1B;IAED,kEAAkE;IAClE;QACE,KAAK,EAAE,iBAAiB;QACxB,KAAK,EAAE,SAAS;QAChB,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,gBAAgB;KAC3B;CACF,CAAC;AAEF,MAAM,cAAc,GAA+C;IACjE,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;IACN,MAAM,EAAE,CAAC;IACT,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,SAAS,OAAO,CAAC,IAAY,EAAE,GAAW,EAAE,GAAW;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,OAAO,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;AACnE,CAAC;AAED,SAAS,WAAW,CAAC,CAA6B,EAAE,CAAoB;IACtE,OAAO,cAAc,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC,CAAC;AACR,CAAC;AAED,MAAM,OAAO,mBAAmB;IACb,QAAQ,CAAiD;IACzD,MAAM,CAAmD;IACzD,YAAY,CAAS;IAEtC,YAAY,SAA0B,EAAE;QACtC,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,sBAAsB,CAAC;IACpE,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,OAAe;QAClB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACvD,CAAC;QAED,IAAI,OAAO,GAAG,OAAO,CAAC;QACtB,MAAM,QAAQ,GAAuB,EAAE,CAAC;QAExC,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YAChE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9C,QAAQ,CAAC,IAAI,CAAC;gBACZ,OAAO,EAAE,mBAAmB;gBAC5B,QAAQ,EAAE,QAAQ;gBAClB,QAAQ,EAAE,YAAY;gBACtB,QAAQ,EAAE,IAAI,CAAC,YAAY;gBAC3B,OAAO,EAAE,yBAAyB,IAAI,CAAC,YAAY,WAAW,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,mBAAmB;aACpH,CAAC,CAAC;QACL,CAAC;QAED,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjE,mEAAmE;YACnE,qEAAqE;YACrE,wCAAwC;YACxC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;YACjG,IAAI,KAA6B,CAAC;YAClC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC3C,QAAQ,CAAC,IAAI,CAAC;oBACZ,OAAO,EAAE,KAAK;oBACd,QAAQ;oBACR,QAAQ;oBACR,QAAQ,EAAE,KAAK,CAAC,KAAK;oBACrB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;iBACxD,CAAC,CAAC;gBACH,kDAAkD;gBAClD,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;oBAAE,EAAE,CAAC,SAAS,EAAE,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,IAAI,OAAO,GAA+B,MAAM,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,QAAQ;YAAE,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnE,MAAM,IAAI,GAAG,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,MAAM,CAAC;QAErD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,OAAe;QAK5B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAElC,MAAM,MAAM,GACV,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEpE,IAAI,QAAQ,GAAG,OAAO,CAAC;QACvB,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC/C,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,OAAe,EAAE,QAA4B;QAC1D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QAE1C,qEAAqE;QACrE,sCAAsC;QACtC,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,QAAQ;aACL,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC;aAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CACzB,CAAC;QAEF,IAAI,GAAG,GAAG,OAAO,CAAC;QAClB,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,SAAS;YACjC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;YACjG,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,aAAa,KAAK,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,4EAA4E;AAC5E,MAAM,UAAU,yBAAyB,CAAC,MAAwB;IAChE,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,yBAAyB,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":"4.1.8","results":[[":__tests__/unit/safe-executor.test.ts",{"duration":26.96230000000014,"failed":false}],[":__tests__/acceptance/security-compliance.test.ts",{"duration":22.170500000000175,"failed":false}],[":__tests__/integration/security-flow.test.ts",{"duration":23.362300000000005,"failed":false}],[":__tests__/unit/path-validator.test.ts",{"duration":17.86850000000004,"failed":false}],[":__tests__/input-validator.test.ts",{"duration":0,"failed":true}],[":__tests__/tool-output-guardrail.test.ts",{"duration":16.48720000000003,"failed":false}],[":__tests__/unit/password-hasher.test.ts",{"duration":18.27260000000001,"failed":false}],[":__tests__/token-generator.test.ts",{"duration":2249.9557000000004,"failed":false}],[":__tests__/credential-generator.test.ts",{"duration":198.3424,"failed":false}],[":__tests__/unit/token-generator.test.ts",{"duration":58.08860000000004,"failed":false}],[":__tests__/plugin-integrity-verifier.test.ts",{"duration":73.71760000000017,"failed":false}],[":__tests__/path-validator.test.ts",{"duration":107.07299999999987,"failed":true}],[":__tests__/unit/credential-generator.test.ts",{"duration":32.75569999999993,"failed":false}],[":__tests__/safe-executor.test.ts",{"duration":1064.0791,"failed":true}],[":__tests__/password-hasher.test.ts",{"duration":0,"failed":true}],[":__tests__/authorization-propagator.test.ts",{"duration":14.032600000000002,"failed":false}],[":__tests__/oauth-pkce.test.ts",{"duration":6.764699999999948,"failed":false}],[":__tests__/keychain-adapter.test.ts",{"duration":15.831800000000044,"failed":false}],[":__tests__/oauth-export-surface.test.ts",{"duration":0,"failed":true}],[":__tests__/oauth-browser.test.ts",{"duration":4.83480000000003,"failed":false}]]}
package/package.json CHANGED
@@ -1,28 +1,33 @@
1
- {
2
- "name": "@claude-flow/security",
3
- "version": "3.0.0-alpha.1",
4
- "type": "module",
5
- "description": "Security module - CVE fixes, input validation, path security",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": "./dist/index.js",
10
- "./*": "./dist/*.js"
11
- },
12
- "scripts": {
13
- "test": "vitest run",
14
- "build": "tsc"
15
- },
16
- "dependencies": {
17
- "bcrypt": "^5.1.1",
18
- "zod": "^3.22.0"
19
- },
20
- "devDependencies": {
21
- "@types/bcrypt": "^5.0.2",
22
- "vitest": "^1.0.0"
23
- },
24
- "publishConfig": {
25
- "access": "public",
26
- "tag": "v3alpha"
27
- }
28
- }
1
+ {
2
+ "name": "@claude-flow/security",
3
+ "version": "3.0.0-alpha.11",
4
+ "type": "module",
5
+ "description": "Security module - CVE fixes, input validation, path security",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./*": "./dist/*.js"
11
+ },
12
+ "scripts": {
13
+ "test": "vitest run",
14
+ "test:oauth-surface": "vitest run __tests__/oauth-export-surface.test.ts __tests__/oauth-pkce.test.ts __tests__/oauth-browser.test.ts",
15
+ "build": "tsc && node scripts/verify-oauth-exports.mjs",
16
+ "prepublishOnly": "npm run build && npm run test:oauth-surface"
17
+ },
18
+ "dependencies": {
19
+ "@noble/ed25519": "^2.1.0",
20
+ "bcryptjs": "^3.0.3",
21
+ "zod": "^3.22.0"
22
+ },
23
+ "optionalDependencies": {
24
+ "@napi-rs/keyring": "1.3.0"
25
+ },
26
+ "devDependencies": {
27
+ "vitest": "^4.1.0"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "tag": "v3alpha"
32
+ }
33
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Release and CI guard for the OAuth surface consumed by `ruflo auth`.
3
+ * This deliberately imports the built package entry point, rather than
4
+ * source files, so a stale or incomplete npm artifact cannot pass.
5
+ */
6
+ const security = await import('../dist/index.js');
7
+
8
+ const requiredFunctions = [
9
+ 'authorizeUrl',
10
+ 'exchangeCode',
11
+ 'refreshToken',
12
+ 'exchangeManualCode',
13
+ 'generatePkce',
14
+ 'openBrowser',
15
+ 'createKeychainAdapter',
16
+ ];
17
+ const requiredClasses = ['CallbackServer', 'OAuthError'];
18
+
19
+ const missing = [
20
+ ...requiredFunctions.filter((name) => typeof security[name] !== 'function'),
21
+ ...requiredClasses.filter((name) => typeof security[name] !== 'function'),
22
+ ...(typeof security.OOB_REDIRECT_URI === 'string' ? [] : ['OOB_REDIRECT_URI']),
23
+ ];
24
+
25
+ if (missing.length > 0) {
26
+ throw new Error(`@claude-flow/security is missing required OAuth exports: ${missing.join(', ')}`);
27
+ }
28
+
29
+ console.log(`OAuth export surface verified (${requiredFunctions.length + requiredClasses.length + 1} exports)`);