@octocodeai/octocode-engine 16.5.0

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 (95) hide show
  1. package/README.md +558 -0
  2. package/dist/lsp/client.d.ts +28 -0
  3. package/dist/lsp/client.js +98 -0
  4. package/dist/lsp/config.d.ts +3 -0
  5. package/dist/lsp/config.js +7 -0
  6. package/dist/lsp/evidence.d.ts +4 -0
  7. package/dist/lsp/evidence.js +28 -0
  8. package/dist/lsp/index.d.ts +7 -0
  9. package/dist/lsp/index.js +6 -0
  10. package/dist/lsp/initConstants.d.ts +4 -0
  11. package/dist/lsp/initConstants.js +27 -0
  12. package/dist/lsp/lspClientPool.d.ts +27 -0
  13. package/dist/lsp/lspClientPool.js +87 -0
  14. package/dist/lsp/lspErrorCodes.d.ts +12 -0
  15. package/dist/lsp/lspErrorCodes.js +12 -0
  16. package/dist/lsp/manager.d.ts +23 -0
  17. package/dist/lsp/manager.js +94 -0
  18. package/dist/lsp/native.d.ts +35 -0
  19. package/dist/lsp/native.js +3 -0
  20. package/dist/lsp/resolver.d.ts +26 -0
  21. package/dist/lsp/resolver.js +73 -0
  22. package/dist/lsp/schemas.d.ts +9 -0
  23. package/dist/lsp/schemas.js +30 -0
  24. package/dist/lsp/types.d.ts +85 -0
  25. package/dist/lsp/types.js +1 -0
  26. package/dist/lsp/uri.d.ts +15 -0
  27. package/dist/lsp/uri.js +24 -0
  28. package/dist/lsp/validation.d.ts +6 -0
  29. package/dist/lsp/validation.js +23 -0
  30. package/dist/lsp/workspaceRoot.d.ts +2 -0
  31. package/dist/lsp/workspaceRoot.js +7 -0
  32. package/dist/security/commandUtils.d.ts +1 -0
  33. package/dist/security/commandUtils.js +7 -0
  34. package/dist/security/commandValidator.d.ts +7 -0
  35. package/dist/security/commandValidator.js +472 -0
  36. package/dist/security/contentSanitizer.d.ts +2 -0
  37. package/dist/security/contentSanitizer.js +181 -0
  38. package/dist/security/filePatterns.d.ts +1 -0
  39. package/dist/security/filePatterns.js +209 -0
  40. package/dist/security/ignoredPathFilter.d.ts +3 -0
  41. package/dist/security/ignoredPathFilter.js +72 -0
  42. package/dist/security/index.d.ts +16 -0
  43. package/dist/security/index.js +13 -0
  44. package/dist/security/mask.d.ts +1 -0
  45. package/dist/security/mask.js +49 -0
  46. package/dist/security/maskUtils.d.ts +1 -0
  47. package/dist/security/maskUtils.js +7 -0
  48. package/dist/security/native.d.ts +9 -0
  49. package/dist/security/native.js +161 -0
  50. package/dist/security/paramExtractors.d.ts +7 -0
  51. package/dist/security/paramExtractors.js +75 -0
  52. package/dist/security/pathPatterns.d.ts +1 -0
  53. package/dist/security/pathPatterns.js +26 -0
  54. package/dist/security/pathUtils.d.ts +1 -0
  55. package/dist/security/pathUtils.js +37 -0
  56. package/dist/security/pathValidator.d.ts +22 -0
  57. package/dist/security/pathValidator.js +229 -0
  58. package/dist/security/regexes/ai-providers.d.ts +2 -0
  59. package/dist/security/regexes/ai-providers.js +177 -0
  60. package/dist/security/regexes/analytics.d.ts +2 -0
  61. package/dist/security/regexes/analytics.js +50 -0
  62. package/dist/security/regexes/auth-crypto.d.ts +6 -0
  63. package/dist/security/regexes/auth-crypto.js +255 -0
  64. package/dist/security/regexes/aws.d.ts +2 -0
  65. package/dist/security/regexes/aws.js +68 -0
  66. package/dist/security/regexes/cloudProviders.d.ts +2 -0
  67. package/dist/security/regexes/cloudProviders.js +328 -0
  68. package/dist/security/regexes/communications.d.ts +4 -0
  69. package/dist/security/regexes/communications.js +260 -0
  70. package/dist/security/regexes/databases.d.ts +2 -0
  71. package/dist/security/regexes/databases.js +135 -0
  72. package/dist/security/regexes/devTools.d.ts +2 -0
  73. package/dist/security/regexes/devTools.js +236 -0
  74. package/dist/security/regexes/index.d.ts +3 -0
  75. package/dist/security/regexes/index.js +31 -0
  76. package/dist/security/regexes/monitoring.d.ts +2 -0
  77. package/dist/security/regexes/monitoring.js +92 -0
  78. package/dist/security/regexes/payments-commerce.d.ts +3 -0
  79. package/dist/security/regexes/payments-commerce.js +197 -0
  80. package/dist/security/regexes/types.d.ts +2 -0
  81. package/dist/security/regexes/types.js +1 -0
  82. package/dist/security/regexes/vcs.d.ts +2 -0
  83. package/dist/security/regexes/vcs.js +105 -0
  84. package/dist/security/registry.d.ts +48 -0
  85. package/dist/security/registry.js +156 -0
  86. package/dist/security/securityConstants.d.ts +3 -0
  87. package/dist/security/securityConstants.js +12 -0
  88. package/dist/security/types.d.ts +35 -0
  89. package/dist/security/types.js +1 -0
  90. package/dist/security/withSecurityValidation.d.ts +21 -0
  91. package/dist/security/withSecurityValidation.js +107 -0
  92. package/index.cjs +97 -0
  93. package/index.d.ts +934 -0
  94. package/index.js +652 -0
  95. package/package.json +311 -0
@@ -0,0 +1,197 @@
1
+ export const paymentProviderPatterns = [
2
+ {
3
+ name: 'stripeSecretKey',
4
+ description: 'Stripe secret key - live and test (sk_*, rk_*)',
5
+ regex: /\b[rs]k_(?:live|test)_[a-zA-Z0-9]{20,247}\b/g,
6
+ matchAccuracy: 'high',
7
+ },
8
+ {
9
+ name: 'stripeWebhookSecret',
10
+ description: 'Stripe webhook signing secret',
11
+ regex: /\bwhsec_[a-zA-Z0-9]{32,}\b/g,
12
+ matchAccuracy: 'high',
13
+ },
14
+ {
15
+ name: 'stripePublishableKey',
16
+ description: 'Stripe publishable key (can indicate key pair presence)',
17
+ regex: /\bpk_(?:live|test)_[a-zA-Z0-9]{20,247}\b/g,
18
+ matchAccuracy: 'medium',
19
+ },
20
+ {
21
+ name: 'paypalAccessToken',
22
+ description: 'PayPal access token',
23
+ regex: /\bA21AA[a-zA-Z0-9_-]{50,}\b/g,
24
+ matchAccuracy: 'high',
25
+ },
26
+ {
27
+ name: 'paypalBraintreeAccessToken',
28
+ description: 'PayPal Braintree access token',
29
+ regex: /\baccess_token\$(?:production|sandbox)\$[0-9a-z]{16}\$[0-9a-f]{32}\b/g,
30
+ matchAccuracy: 'high',
31
+ },
32
+ {
33
+ name: 'squareAccessToken',
34
+ description: 'Square access token (all formats)',
35
+ regex: /\b(?:EAAAE[A-Za-z0-9_-]{94,}|sq0[a-z]?atp-[0-9A-Za-z\-_]{22,26})\b/g,
36
+ matchAccuracy: 'high',
37
+ },
38
+ {
39
+ name: 'squareOauthSecret',
40
+ description: 'Square OAuth secret',
41
+ regex: /\bsq0csp-[0-9A-Za-z\-_]{43}\b/g,
42
+ matchAccuracy: 'high',
43
+ },
44
+ {
45
+ name: 'squareApplicationId',
46
+ description: 'Square application ID',
47
+ regex: /\bsq0ids-[a-zA-Z0-9_-]{43}\b/g,
48
+ matchAccuracy: 'high',
49
+ },
50
+ {
51
+ name: 'shopifyPrivateAppPassword',
52
+ description: 'Shopify private app password',
53
+ regex: /\bshppa_[a-fA-F0-9]{32}\b/g,
54
+ matchAccuracy: 'high',
55
+ },
56
+ {
57
+ name: 'shopifyAccessToken',
58
+ description: 'Shopify access token',
59
+ regex: /\bshpat_[a-fA-F0-9]{32}\b/g,
60
+ matchAccuracy: 'high',
61
+ },
62
+ {
63
+ name: 'shopifyWebhookToken',
64
+ description: 'Shopify webhook token',
65
+ regex: /\bshpwh_[a-fA-F0-9]{32}\b/g,
66
+ matchAccuracy: 'high',
67
+ },
68
+ {
69
+ name: 'adyenApiKey',
70
+ description: 'Adyen API key',
71
+ regex: /\bAQE[a-zA-Z0-9]{70,}\b/g,
72
+ matchAccuracy: 'high',
73
+ },
74
+ {
75
+ name: 'razorpayApiKey',
76
+ description: 'Razorpay API key',
77
+ regex: /\brzp_(?:test|live)_[a-zA-Z0-9]{14}\b/g,
78
+ matchAccuracy: 'high',
79
+ },
80
+ {
81
+ name: 'flutterwaveKeys',
82
+ description: 'Flutterwave API keys',
83
+ regex: /\bFLW(?:PUBK|SECK)_(?:TEST|LIVE)-[a-h0-9]{32}-X\b/g,
84
+ matchAccuracy: 'high',
85
+ },
86
+ {
87
+ name: 'coinbaseAccessToken',
88
+ description: 'Coinbase access token',
89
+ regex: /\b['"]?(?:coinbase)(?:[\s\w.-]{0,20})['"]?\s*(?::|=>|=)\s*['"]?[a-z0-9_-]{64}['"]?\b/gi,
90
+ matchAccuracy: 'medium',
91
+ },
92
+ {
93
+ name: 'krakenAccessToken',
94
+ description: 'Kraken access token',
95
+ regex: /\b['"]?(?:kraken)(?:[\s\w.-]{0,20})['"]?\s*(?::|=>|=)\s*['"]?[a-z0-9/=_+-]{80,90}['"]?\b/gi,
96
+ matchAccuracy: 'medium',
97
+ },
98
+ {
99
+ name: 'kucoinAccessToken',
100
+ description: 'Kucoin access token',
101
+ regex: /\b['"]?(?:kucoin)(?:[\s\w.-]{0,20})['"]?\s*(?::|=>|=)\s*['"]?[a-f0-9]{24}['"]?\b/gi,
102
+ matchAccuracy: 'medium',
103
+ },
104
+ {
105
+ name: 'kucoinSecretKey',
106
+ description: 'Kucoin secret key',
107
+ regex: /\b['"]?(?:kucoin)(?:[\s\w.-]{0,20})['"]?\s*(?::|=>|=)\s*['"]?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}['"]?\b/gi,
108
+ matchAccuracy: 'medium',
109
+ },
110
+ {
111
+ name: 'bittrexAccessKey',
112
+ description: 'Bittrex access key',
113
+ regex: /\b['"]?(?:bittrex)(?:[\s\w.-]{0,20})['"]?\s*(?::|=>|=)\s*['"]?[a-z0-9]{32}['"]?\b/gi,
114
+ matchAccuracy: 'medium',
115
+ },
116
+ {
117
+ name: 'binanceApiKey',
118
+ description: 'Binance API key',
119
+ regex: /\b['"]?(?:binance)(?:[\s\w.-]{0,20})['"]?\s*(?::|=>|=)\s*['"]?[A-Za-z0-9]{64}['"]?\b/gi,
120
+ matchAccuracy: 'medium',
121
+ },
122
+ {
123
+ name: 'bybitApiKey',
124
+ description: 'Bybit API key',
125
+ regex: /\b['"]?(?:bybit)(?:[\s\w.-]{0,20})['"]?\s*(?::|=>|=)\s*['"]?[A-Za-z0-9]{18,24}['"]?\b/gi,
126
+ matchAccuracy: 'medium',
127
+ },
128
+ {
129
+ name: 'gocardlessApiToken',
130
+ description: 'GoCardless API token',
131
+ regex: /\blive_[a-z0-9\-_=]{40}\b/gi,
132
+ matchAccuracy: 'high',
133
+ },
134
+ {
135
+ name: 'plaidApiToken',
136
+ description: 'Plaid API token',
137
+ regex: /\baccess-(?:sandbox|development|production)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g,
138
+ matchAccuracy: 'high',
139
+ },
140
+ {
141
+ name: 'plaidClientId',
142
+ description: 'Plaid client ID',
143
+ regex: /\b['"]?(?:PLAID|plaid)_?(?:CLIENT|client)_?(?:ID|id)['"]?\s*(?::|=>|=)\s*['"]?[a-f0-9]{24}['"]?\b/gi,
144
+ matchAccuracy: 'medium',
145
+ },
146
+ {
147
+ name: 'lemonSqueezyApiKey',
148
+ description: 'Lemon Squeezy API key',
149
+ regex: /\b['"]?(?:LEMONSQUEEZY|LEMON_SQUEEZY|lemonsqueezy)_?(?:API|api)?_?(?:KEY|key)['"]?\s*(?::|=>|=)\s*['"]?eyJ[a-zA-Z0-9_-]{100,}['"]?\b/gi,
150
+ matchAccuracy: 'medium',
151
+ },
152
+ {
153
+ name: 'paddleApiKey',
154
+ description: 'Paddle API key',
155
+ regex: /\b['"]?(?:PADDLE|paddle)_?(?:API|api)?_?(?:KEY|key)['"]?\s*(?::|=>|=)\s*['"]?pdl_(?:live|sdbx)_[a-zA-Z0-9]{40,}['"]?\b/gi,
156
+ matchAccuracy: 'high',
157
+ },
158
+ {
159
+ name: 'mollieApiKey',
160
+ description: 'Mollie API key',
161
+ regex: /\b(?:live|test)_[a-zA-Z0-9]{30,}\b/g,
162
+ matchAccuracy: 'medium',
163
+ fileContext: /mollie/i,
164
+ },
165
+ ];
166
+ export const ecommerceContentPatterns = [
167
+ {
168
+ name: 'shopifyStorefrontAccessToken',
169
+ description: 'Shopify storefront API access token',
170
+ regex: /\bshpatf_[0-9a-f]{32}\b/g,
171
+ matchAccuracy: 'high',
172
+ },
173
+ {
174
+ name: 'woocommerceConsumerKey',
175
+ description: 'WooCommerce consumer key',
176
+ regex: /\bck_[a-f0-9]{40}\b/g,
177
+ matchAccuracy: 'high',
178
+ },
179
+ {
180
+ name: 'woocommerceConsumerSecret',
181
+ description: 'WooCommerce consumer secret',
182
+ regex: /\bcs_[a-f0-9]{40}\b/g,
183
+ matchAccuracy: 'high',
184
+ },
185
+ {
186
+ name: 'contentfulAccessToken',
187
+ description: 'Contentful access token',
188
+ regex: /\bCFPAT-[0-9a-zA-Z]{20}\b/g,
189
+ matchAccuracy: 'high',
190
+ },
191
+ {
192
+ name: 'mailchimpEcommerceApiKey',
193
+ description: 'MailChimp E-commerce API key',
194
+ regex: /\b[0-9a-f]{32}-[a-z]{2,3}[0-9]{1,2}\b/g,
195
+ matchAccuracy: 'high',
196
+ },
197
+ ];
@@ -0,0 +1,2 @@
1
+ import type { SensitiveDataPattern } from '../types.js';
2
+ export type { SensitiveDataPattern };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { SensitiveDataPattern } from './types.js';
2
+ export declare const versionControlPatterns: SensitiveDataPattern[];
@@ -0,0 +1,105 @@
1
+ export const versionControlPatterns = [
2
+ {
3
+ name: 'gitlabPersonalAccessToken',
4
+ description: 'GitLab personal access token',
5
+ regex: /\bglpat-[A-Za-z0-9_-]{20,}\b/g,
6
+ matchAccuracy: 'high',
7
+ },
8
+ {
9
+ name: 'gitlabDeployToken',
10
+ description: 'GitLab deploy token',
11
+ regex: /\bgldt-[A-Za-z0-9_-]{20}\b/g,
12
+ matchAccuracy: 'high',
13
+ },
14
+ {
15
+ name: 'gitlabRunnerToken',
16
+ description: 'GitLab runner registration token',
17
+ regex: /\bglrt-[A-Za-z0-9_-]{20}\b/g,
18
+ matchAccuracy: 'high',
19
+ },
20
+ {
21
+ name: 'gitlabCiJobToken',
22
+ description: 'GitLab CI/CD job token',
23
+ regex: /\bglcbt-[0-9a-zA-Z]{1,5}_[0-9a-zA-Z_-]{20}\b/g,
24
+ matchAccuracy: 'high',
25
+ },
26
+ {
27
+ name: 'gitlabPipelineTriggerToken',
28
+ description: 'GitLab pipeline trigger token',
29
+ regex: /\bglptt-[0-9a-f]{40}\b/g,
30
+ matchAccuracy: 'high',
31
+ },
32
+ {
33
+ name: 'bitbucketAppPassword',
34
+ description: 'Bitbucket app password',
35
+ regex: /\bATBB[a-zA-Z0-9]{24}\b/g,
36
+ matchAccuracy: 'high',
37
+ },
38
+ {
39
+ name: 'githubTokens',
40
+ description: 'GitHub personal access token (classic)',
41
+ regex: /\b((?:ghp|gho|ghu|ghs|ghr|github_pat)_[a-zA-Z0-9_]{36,255})\b/g,
42
+ matchAccuracy: 'high',
43
+ },
44
+ {
45
+ name: 'githubFineGrainedToken',
46
+ description: 'GitHub fine-grained personal access token',
47
+ regex: /\bgithub_pat_[A-Za-z0-9_]{82}\b/g,
48
+ matchAccuracy: 'high',
49
+ fileContext: /(?:\.env|config|settings|secrets)/i,
50
+ },
51
+ {
52
+ name: 'githubAppInstallationToken',
53
+ description: 'GitHub App installation token',
54
+ regex: /\bghs_[0-9a-zA-Z]{37}\b/g,
55
+ matchAccuracy: 'high',
56
+ },
57
+ {
58
+ name: 'gitlabScimToken',
59
+ description: 'GitLab SCIM token',
60
+ regex: /\bglsoat-[0-9a-zA-Z_-]{20}\b/g,
61
+ matchAccuracy: 'high',
62
+ },
63
+ {
64
+ name: 'gitlabFeatureFlagToken',
65
+ description: 'GitLab feature flag client token',
66
+ regex: /\bglffct-[0-9a-zA-Z_-]{20}\b/g,
67
+ matchAccuracy: 'high',
68
+ },
69
+ {
70
+ name: 'gitlabFeedToken',
71
+ description: 'GitLab feed token',
72
+ regex: /\bglft-[0-9a-zA-Z_-]{20}\b/g,
73
+ matchAccuracy: 'high',
74
+ },
75
+ {
76
+ name: 'gitlabIncomingMailToken',
77
+ description: 'GitLab incoming mail token',
78
+ regex: /\bglimt-[0-9a-zA-Z_-]{25}\b/g,
79
+ matchAccuracy: 'high',
80
+ },
81
+ {
82
+ name: 'gitlabK8sAgentToken',
83
+ description: 'GitLab Kubernetes agent token',
84
+ regex: /\bglagent-[0-9a-zA-Z_-]{50}\b/g,
85
+ matchAccuracy: 'high',
86
+ },
87
+ {
88
+ name: 'gitlabOAuthAppSecret',
89
+ description: 'GitLab OAuth application secret',
90
+ regex: /\bgloas-[0-9a-zA-Z_-]{64}\b/g,
91
+ matchAccuracy: 'high',
92
+ },
93
+ {
94
+ name: 'gitlabSessionCookie',
95
+ description: 'GitLab session cookie',
96
+ regex: /_gitlab_session=[0-9a-z]{32}/g,
97
+ matchAccuracy: 'high',
98
+ },
99
+ {
100
+ name: 'bitbucketRepoToken',
101
+ description: 'Bitbucket repository access token',
102
+ regex: /\bATCTT3[a-zA-Z0-9]{24}\b/g,
103
+ matchAccuracy: 'high',
104
+ },
105
+ ];
@@ -0,0 +1,48 @@
1
+ import type { SensitiveDataPattern } from './types.js';
2
+ export interface ISecurityRegistry {
3
+ readonly extraSecretPatterns: readonly SensitiveDataPattern[];
4
+ readonly extraAllowedCommands: readonly string[];
5
+ readonly extraAllowedRoots: readonly string[];
6
+ readonly extraIgnoredPathPatterns: readonly RegExp[];
7
+ readonly extraIgnoredFilePatterns: readonly RegExp[];
8
+ readonly version: number;
9
+ readonly frozen: boolean;
10
+ addSecretPatterns(patterns: SensitiveDataPattern[]): void;
11
+ addAllowedCommands(commands: string[]): void;
12
+ addAllowedRoots(roots: string[]): void;
13
+ addIgnoredPathPatterns(patterns: RegExp[]): void;
14
+ addIgnoredFilePatterns(patterns: RegExp[]): void;
15
+ freeze(): void;
16
+ reset(): void;
17
+ }
18
+ export declare class SecurityRegistry implements ISecurityRegistry {
19
+ private _extraSecretPatterns;
20
+ private _extraAllowedCommands;
21
+ private _extraAllowedRoots;
22
+ private _extraIgnoredPathPatterns;
23
+ private _extraIgnoredFilePatterns;
24
+ private _version;
25
+ private _frozen;
26
+ private _frozenSecretPatterns;
27
+ private _frozenAllowedCommands;
28
+ private _frozenAllowedRoots;
29
+ private _frozenIgnoredPathPatterns;
30
+ private _frozenIgnoredFilePatterns;
31
+ get frozen(): boolean;
32
+ private _assertMutable;
33
+ private _invalidateFrozenCaches;
34
+ get version(): number;
35
+ get extraSecretPatterns(): readonly SensitiveDataPattern[];
36
+ get extraAllowedCommands(): readonly string[];
37
+ get extraAllowedRoots(): readonly string[];
38
+ get extraIgnoredPathPatterns(): readonly RegExp[];
39
+ get extraIgnoredFilePatterns(): readonly RegExp[];
40
+ addSecretPatterns(patterns: SensitiveDataPattern[]): void;
41
+ addAllowedCommands(commands: string[]): void;
42
+ addAllowedRoots(roots: string[]): void;
43
+ addIgnoredPathPatterns(patterns: RegExp[]): void;
44
+ addIgnoredFilePatterns(patterns: RegExp[]): void;
45
+ freeze(): void;
46
+ reset(): void;
47
+ }
48
+ export declare const securityRegistry: SecurityRegistry;
@@ -0,0 +1,156 @@
1
+ import { normalizeCommandName } from './commandUtils.js';
2
+ const REDOS_TIMEOUT_MS = 50;
3
+ const REDOS_TEST_INPUT = 'a'.repeat(100);
4
+ function isReDoSSafe(regex) {
5
+ const start = performance.now();
6
+ try {
7
+ regex.test(REDOS_TEST_INPUT);
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ return performance.now() - start < REDOS_TIMEOUT_MS;
13
+ }
14
+ export class SecurityRegistry {
15
+ _extraSecretPatterns = [];
16
+ _extraAllowedCommands = [];
17
+ _extraAllowedRoots = [];
18
+ _extraIgnoredPathPatterns = [];
19
+ _extraIgnoredFilePatterns = [];
20
+ _version = 0;
21
+ _frozen = false;
22
+ _frozenSecretPatterns = null;
23
+ _frozenAllowedCommands = null;
24
+ _frozenAllowedRoots = null;
25
+ _frozenIgnoredPathPatterns = null;
26
+ _frozenIgnoredFilePatterns = null;
27
+ get frozen() {
28
+ return this._frozen;
29
+ }
30
+ _assertMutable() {
31
+ if (this._frozen) {
32
+ throw new Error('SecurityRegistry is frozen — call reset() to unfreeze before mutating');
33
+ }
34
+ }
35
+ _invalidateFrozenCaches() {
36
+ this._frozenSecretPatterns = null;
37
+ this._frozenAllowedCommands = null;
38
+ this._frozenAllowedRoots = null;
39
+ this._frozenIgnoredPathPatterns = null;
40
+ this._frozenIgnoredFilePatterns = null;
41
+ }
42
+ get version() {
43
+ return this._version;
44
+ }
45
+ get extraSecretPatterns() {
46
+ return (this._frozenSecretPatterns ??= Object.freeze([
47
+ ...this._extraSecretPatterns,
48
+ ]));
49
+ }
50
+ get extraAllowedCommands() {
51
+ return (this._frozenAllowedCommands ??= Object.freeze([
52
+ ...this._extraAllowedCommands,
53
+ ]));
54
+ }
55
+ get extraAllowedRoots() {
56
+ return (this._frozenAllowedRoots ??= Object.freeze([
57
+ ...this._extraAllowedRoots,
58
+ ]));
59
+ }
60
+ get extraIgnoredPathPatterns() {
61
+ return (this._frozenIgnoredPathPatterns ??= Object.freeze([
62
+ ...this._extraIgnoredPathPatterns,
63
+ ]));
64
+ }
65
+ get extraIgnoredFilePatterns() {
66
+ return (this._frozenIgnoredFilePatterns ??= Object.freeze([
67
+ ...this._extraIgnoredFilePatterns,
68
+ ]));
69
+ }
70
+ addSecretPatterns(patterns) {
71
+ this._assertMutable();
72
+ for (const p of patterns) {
73
+ if (!p.name || !p.regex) {
74
+ throw new Error('Each pattern must have a name and regex');
75
+ }
76
+ if (!isReDoSSafe(p.regex)) {
77
+ throw new Error(`Pattern '${p.name}' failed ReDoS safety check — regex may cause catastrophic backtracking`);
78
+ }
79
+ if (!this._extraSecretPatterns.some(e => e.name === p.name)) {
80
+ this._extraSecretPatterns.push(p);
81
+ }
82
+ }
83
+ this._invalidateFrozenCaches();
84
+ this._version++;
85
+ }
86
+ addAllowedCommands(commands) {
87
+ this._assertMutable();
88
+ for (const cmd of commands) {
89
+ if (typeof cmd !== 'string' || cmd.trim() === '') {
90
+ throw new Error('Each command must be a non-empty string');
91
+ }
92
+ const normalized = normalizeCommandName(cmd);
93
+ if (!this._extraAllowedCommands.includes(normalized)) {
94
+ this._extraAllowedCommands.push(normalized);
95
+ }
96
+ }
97
+ this._invalidateFrozenCaches();
98
+ this._version++;
99
+ }
100
+ addAllowedRoots(roots) {
101
+ this._assertMutable();
102
+ for (const root of roots) {
103
+ if (typeof root !== 'string' || root.trim() === '') {
104
+ throw new Error('Each root must be a non-empty string');
105
+ }
106
+ if (!this._extraAllowedRoots.includes(root)) {
107
+ this._extraAllowedRoots.push(root);
108
+ }
109
+ }
110
+ this._invalidateFrozenCaches();
111
+ this._version++;
112
+ }
113
+ addIgnoredPathPatterns(patterns) {
114
+ this._assertMutable();
115
+ for (const p of patterns) {
116
+ if (!isReDoSSafe(p)) {
117
+ throw new Error(`Path pattern /${p.source}/ failed ReDoS safety check`);
118
+ }
119
+ if (!this._extraIgnoredPathPatterns.some(e => e.source === p.source)) {
120
+ this._extraIgnoredPathPatterns.push(p);
121
+ }
122
+ }
123
+ this._invalidateFrozenCaches();
124
+ this._version++;
125
+ }
126
+ addIgnoredFilePatterns(patterns) {
127
+ this._assertMutable();
128
+ for (const p of patterns) {
129
+ if (!isReDoSSafe(p)) {
130
+ throw new Error(`File pattern /${p.source}/ failed ReDoS safety check`);
131
+ }
132
+ if (!this._extraIgnoredFilePatterns.some(e => e.source === p.source)) {
133
+ this._extraIgnoredFilePatterns.push(p);
134
+ }
135
+ }
136
+ this._invalidateFrozenCaches();
137
+ this._version++;
138
+ }
139
+ freeze() {
140
+ this._frozen = true;
141
+ }
142
+ reset() {
143
+ this._frozen = false;
144
+ this._extraSecretPatterns = [];
145
+ this._extraAllowedCommands = [];
146
+ this._extraAllowedRoots = [];
147
+ this._extraIgnoredPathPatterns = [];
148
+ this._extraIgnoredFilePatterns = [];
149
+ this._invalidateFrozenCaches();
150
+ this._version++;
151
+ }
152
+ }
153
+ const GLOBAL_KEY = '__octocode_security_registry__';
154
+ export const securityRegistry = globalThis[GLOBAL_KEY] ??
155
+ (globalThis[GLOBAL_KEY] =
156
+ new SecurityRegistry());
@@ -0,0 +1,3 @@
1
+ export declare const ALLOWED_COMMANDS: readonly ["rg", "ls", "find", "grep", "git"];
2
+ export declare const DANGEROUS_PATTERNS: readonly [RegExp, RegExp, RegExp];
3
+ export declare const PATTERN_DANGEROUS_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp];
@@ -0,0 +1,12 @@
1
+ export const ALLOWED_COMMANDS = ['rg', 'ls', 'find', 'grep', 'git'];
2
+ export const DANGEROUS_PATTERNS = [
3
+ /[;&|`$(){}[\]<>]/, // Shell metacharacters
4
+ /\${/,
5
+ /\$\(/,
6
+ ];
7
+ export const PATTERN_DANGEROUS_PATTERNS = [
8
+ /\${/,
9
+ /\$\(/,
10
+ /`/, // Backtick substitution
11
+ /;/,
12
+ ];
@@ -0,0 +1,35 @@
1
+ export interface SensitiveDataPattern {
2
+ name: string;
3
+ description: string;
4
+ regex: RegExp;
5
+ fileContext?: RegExp;
6
+ matchAccuracy?: 'high' | 'medium';
7
+ }
8
+ export interface SanitizationResult {
9
+ content: string;
10
+ hasSecrets: boolean;
11
+ secretsDetected: string[];
12
+ warnings: string[];
13
+ }
14
+ export interface ValidationResult {
15
+ sanitizedParams: Record<string, unknown>;
16
+ isValid: boolean;
17
+ hasSecrets: boolean;
18
+ warnings: string[];
19
+ }
20
+ export interface PathValidationResult {
21
+ isValid: boolean;
22
+ error?: string;
23
+ sanitizedPath?: string;
24
+ }
25
+ export interface ToolResult {
26
+ content: Array<{
27
+ type: string;
28
+ text?: string;
29
+ }>;
30
+ isError?: boolean;
31
+ }
32
+ export interface ISanitizer {
33
+ sanitizeContent(content: string, filePath?: string): SanitizationResult;
34
+ validateInputParameters(params: Record<string, unknown>): ValidationResult;
35
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { ISanitizer, ToolResult } from './types.js';
2
+ export interface SecurityDepsConfig {
3
+ sanitizer?: ISanitizer;
4
+ defaultTimeoutMs?: number;
5
+ logToolCall?: (toolName: string, repos: string[], goal?: string, rGoal?: string, reasoning?: string) => Promise<void>;
6
+ logSessionError?: (toolName: string, errorCode: string) => Promise<void>;
7
+ isLoggingEnabled?: () => boolean;
8
+ }
9
+ export declare function configureSecurity(deps: SecurityDepsConfig): void;
10
+ export declare function withSecurityValidation<T extends Record<string, unknown>, TAuth = unknown>(toolName: string, toolHandler: (sanitizedArgs: T, authInfo?: TAuth, sessionId?: string) => Promise<ToolResult>, options?: {
11
+ timeoutMs?: number;
12
+ }): (args: unknown, extra: {
13
+ authInfo?: TAuth;
14
+ sessionId?: string;
15
+ signal?: AbortSignal;
16
+ }) => Promise<ToolResult>;
17
+ export declare function withBasicSecurityValidation<T extends object>(toolHandler: (sanitizedArgs: T) => Promise<ToolResult>, toolName?: string, options?: {
18
+ timeoutMs?: number;
19
+ }): (args: unknown, extra?: {
20
+ signal?: AbortSignal;
21
+ }) => Promise<ToolResult>;