beddel 0.1.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.
- package/README.md +297 -0
- package/dist/agents/agentRegistry.d.ts +68 -0
- package/dist/agents/agentRegistry.d.ts.map +1 -0
- package/dist/agents/agentRegistry.js +222 -0
- package/dist/agents/agentRegistry.js.map +1 -0
- package/dist/agents/formatter-agent.d.ts +10 -0
- package/dist/agents/formatter-agent.d.ts.map +1 -0
- package/dist/agents/formatter-agent.js +49 -0
- package/dist/agents/formatter-agent.js.map +1 -0
- package/dist/agents/genkit-agent.d.ts +12 -0
- package/dist/agents/genkit-agent.d.ts.map +1 -0
- package/dist/agents/genkit-agent.js +119 -0
- package/dist/agents/genkit-agent.js.map +1 -0
- package/dist/agents/i18n-messages.d.ts +17 -0
- package/dist/agents/i18n-messages.d.ts.map +1 -0
- package/dist/agents/i18n-messages.js +92 -0
- package/dist/agents/i18n-messages.js.map +1 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +26 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/pipeline.d.ts +15 -0
- package/dist/agents/pipeline.d.ts.map +1 -0
- package/dist/agents/pipeline.js +45 -0
- package/dist/agents/pipeline.js.map +1 -0
- package/dist/agents/schema-factory.d.ts +40 -0
- package/dist/agents/schema-factory.d.ts.map +1 -0
- package/dist/agents/schema-factory.js +121 -0
- package/dist/agents/schema-factory.js.map +1 -0
- package/dist/agents/translation-validators.d.ts +26 -0
- package/dist/agents/translation-validators.d.ts.map +1 -0
- package/dist/agents/translation-validators.js +77 -0
- package/dist/agents/translation-validators.js.map +1 -0
- package/dist/agents/translator-agents.d.ts +184 -0
- package/dist/agents/translator-agents.d.ts.map +1 -0
- package/dist/agents/translator-agents.js +613 -0
- package/dist/agents/translator-agents.js.map +1 -0
- package/dist/agents/types/translation.types.d.ts +100 -0
- package/dist/agents/types/translation.types.d.ts.map +1 -0
- package/dist/agents/types/translation.types.js +3 -0
- package/dist/agents/types/translation.types.js.map +1 -0
- package/dist/agents/validator-agent.d.ts +42 -0
- package/dist/agents/validator-agent.d.ts.map +1 -0
- package/dist/agents/validator-agent.js +122 -0
- package/dist/agents/validator-agent.js.map +1 -0
- package/dist/audit/auditTrail.d.ts +55 -0
- package/dist/audit/auditTrail.d.ts.map +1 -0
- package/dist/audit/auditTrail.js +93 -0
- package/dist/audit/auditTrail.js.map +1 -0
- package/dist/compliance/gdprEngine.d.ts +44 -0
- package/dist/compliance/gdprEngine.d.ts.map +1 -0
- package/dist/compliance/gdprEngine.js +178 -0
- package/dist/compliance/gdprEngine.js.map +1 -0
- package/dist/compliance/lgpdEngine.d.ts +51 -0
- package/dist/compliance/lgpdEngine.d.ts.map +1 -0
- package/dist/compliance/lgpdEngine.js +221 -0
- package/dist/compliance/lgpdEngine.js.map +1 -0
- package/dist/config.d.ts +78 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/firebase/tenantManager.d.ts +84 -0
- package/dist/firebase/tenantManager.d.ts.map +1 -0
- package/dist/firebase/tenantManager.js +378 -0
- package/dist/firebase/tenantManager.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/secure-yaml-runtime.d.ts +68 -0
- package/dist/integration/secure-yaml-runtime.d.ts.map +1 -0
- package/dist/integration/secure-yaml-runtime.js +245 -0
- package/dist/integration/secure-yaml-runtime.js.map +1 -0
- package/dist/parser/secure-yaml-parser.d.ts +62 -0
- package/dist/parser/secure-yaml-parser.d.ts.map +1 -0
- package/dist/parser/secure-yaml-parser.js +234 -0
- package/dist/parser/secure-yaml-parser.js.map +1 -0
- package/dist/performance/autoscaling.d.ts +100 -0
- package/dist/performance/autoscaling.d.ts.map +1 -0
- package/dist/performance/autoscaling.js +339 -0
- package/dist/performance/autoscaling.js.map +1 -0
- package/dist/performance/benchmark.d.ts +104 -0
- package/dist/performance/benchmark.d.ts.map +1 -0
- package/dist/performance/benchmark.js +514 -0
- package/dist/performance/benchmark.js.map +1 -0
- package/dist/performance/index.d.ts +14 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +35 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/monitor.d.ts +126 -0
- package/dist/performance/monitor.d.ts.map +1 -0
- package/dist/performance/monitor.js +324 -0
- package/dist/performance/monitor.js.map +1 -0
- package/dist/performance/streaming.d.ts +82 -0
- package/dist/performance/streaming.d.ts.map +1 -0
- package/dist/performance/streaming.js +287 -0
- package/dist/performance/streaming.js.map +1 -0
- package/dist/runtime/audit.d.ts +240 -0
- package/dist/runtime/audit.d.ts.map +1 -0
- package/dist/runtime/audit.js +641 -0
- package/dist/runtime/audit.js.map +1 -0
- package/dist/runtime/declarativeAgentRuntime.d.ts +123 -0
- package/dist/runtime/declarativeAgentRuntime.d.ts.map +1 -0
- package/dist/runtime/declarativeAgentRuntime.js +576 -0
- package/dist/runtime/declarativeAgentRuntime.js.map +1 -0
- package/dist/runtime/isolatedRuntime.d.ts +119 -0
- package/dist/runtime/isolatedRuntime.d.ts.map +1 -0
- package/dist/runtime/isolatedRuntime.js +425 -0
- package/dist/runtime/isolatedRuntime.js.map +1 -0
- package/dist/runtime/schemaCompiler.d.ts +35 -0
- package/dist/runtime/schemaCompiler.d.ts.map +1 -0
- package/dist/runtime/schemaCompiler.js +151 -0
- package/dist/runtime/schemaCompiler.js.map +1 -0
- package/dist/runtime/simpleRuntime.d.ts +57 -0
- package/dist/runtime/simpleRuntime.d.ts.map +1 -0
- package/dist/runtime/simpleRuntime.js +187 -0
- package/dist/runtime/simpleRuntime.js.map +1 -0
- package/dist/security/dashboard.d.ts +89 -0
- package/dist/security/dashboard.d.ts.map +1 -0
- package/dist/security/dashboard.js +300 -0
- package/dist/security/dashboard.js.map +1 -0
- package/dist/security/hardening.d.ts +130 -0
- package/dist/security/hardening.d.ts.map +1 -0
- package/dist/security/hardening.js +414 -0
- package/dist/security/hardening.js.map +1 -0
- package/dist/security/index.d.ts +128 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +353 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/monitor.d.ts +88 -0
- package/dist/security/monitor.d.ts.map +1 -0
- package/dist/security/monitor.js +356 -0
- package/dist/security/monitor.js.map +1 -0
- package/dist/security/scanner.d.ts +104 -0
- package/dist/security/scanner.d.ts.map +1 -0
- package/dist/security/scanner.js +298 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/security/score.d.ts +150 -0
- package/dist/security/score.d.ts.map +1 -0
- package/dist/security/score.js +983 -0
- package/dist/security/score.js.map +1 -0
- package/dist/security/test-security.d.ts +22 -0
- package/dist/security/test-security.d.ts.map +1 -0
- package/dist/security/test-security.js +154 -0
- package/dist/security/test-security.js.map +1 -0
- package/dist/security/threatDetector.d.ts +39 -0
- package/dist/security/threatDetector.d.ts.map +1 -0
- package/dist/security/threatDetector.js +354 -0
- package/dist/security/threatDetector.js.map +1 -0
- package/dist/security/validation.d.ts +69 -0
- package/dist/security/validation.d.ts.map +1 -0
- package/dist/security/validation.js +286 -0
- package/dist/security/validation.js.map +1 -0
- package/dist/server/api/clientsRoute.d.ts +9 -0
- package/dist/server/api/clientsRoute.d.ts.map +1 -0
- package/dist/server/api/clientsRoute.js +71 -0
- package/dist/server/api/clientsRoute.js.map +1 -0
- package/dist/server/api/endpointsRoute.d.ts +8 -0
- package/dist/server/api/endpointsRoute.d.ts.map +1 -0
- package/dist/server/api/endpointsRoute.js +76 -0
- package/dist/server/api/endpointsRoute.js.map +1 -0
- package/dist/server/api/graphql.d.ts +9 -0
- package/dist/server/api/graphql.d.ts.map +1 -0
- package/dist/server/api/graphql.js +180 -0
- package/dist/server/api/graphql.js.map +1 -0
- package/dist/server/errors.d.ts +19 -0
- package/dist/server/errors.d.ts.map +1 -0
- package/dist/server/errors.js +42 -0
- package/dist/server/errors.js.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +24 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/kvStore.d.ts +27 -0
- package/dist/server/kvStore.d.ts.map +1 -0
- package/dist/server/kvStore.js +128 -0
- package/dist/server/kvStore.js.map +1 -0
- package/dist/server/runtimeSecurity.d.ts +28 -0
- package/dist/server/runtimeSecurity.d.ts.map +1 -0
- package/dist/server/runtimeSecurity.js +85 -0
- package/dist/server/runtimeSecurity.js.map +1 -0
- package/dist/server/types.d.ts +53 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +8 -0
- package/dist/server/types.js.map +1 -0
- package/dist/types/executionContext.d.ts +16 -0
- package/dist/types/executionContext.d.ts.map +1 -0
- package/dist/types/executionContext.js +3 -0
- package/dist/types/executionContext.js.map +1 -0
- package/package.json +77 -0
- package/src/agents/agentRegistry.ts +272 -0
- package/src/agents/image-agent.yaml +86 -0
- package/src/agents/joker-agent.yaml +47 -0
- package/src/agents/translator-agent.yaml +80 -0
- package/src/audit/auditTrail.ts +134 -0
- package/src/compliance/gdprEngine.ts +209 -0
- package/src/compliance/lgpdEngine.ts +268 -0
- package/src/config.ts +179 -0
- package/src/errors.ts +35 -0
- package/src/firebase/tenantManager.ts +443 -0
- package/src/index.ts +125 -0
- package/src/integration/secure-yaml-runtime.ts +341 -0
- package/src/parser/secure-yaml-parser.ts +273 -0
- package/src/performance/autoscaling.ts +495 -0
- package/src/performance/benchmark.ts +644 -0
- package/src/performance/index.ts +34 -0
- package/src/performance/monitor.ts +469 -0
- package/src/performance/streaming.ts +317 -0
- package/src/runtime/audit.ts +907 -0
- package/src/runtime/declarativeAgentRuntime.ts +836 -0
- package/src/runtime/isolatedRuntime.ts +572 -0
- package/src/runtime/schemaCompiler.ts +228 -0
- package/src/runtime/simpleRuntime.ts +201 -0
- package/src/security/dashboard.ts +462 -0
- package/src/security/hardening.ts +560 -0
- package/src/security/index.ts +439 -0
- package/src/security/monitor.ts +490 -0
- package/src/security/scanner.ts +368 -0
- package/src/security/score.ts +1138 -0
- package/src/security/threatDetector.ts +481 -0
- package/src/security/validation.ts +365 -0
- package/src/server/api/clientsRoute.ts +92 -0
- package/src/server/api/endpointsRoute.ts +97 -0
- package/src/server/api/graphql.ts +249 -0
- package/src/server/errors.ts +38 -0
- package/src/server/index.ts +6 -0
- package/src/server/kvStore.ts +152 -0
- package/src/server/runtimeSecurity.ts +102 -0
- package/src/server/types.ts +60 -0
- package/src/types/executionContext.ts +16 -0
- package/tools/seed.ts +365 -0
- package/tools/test-endpoints.ts +174 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security hardening utilities for YAML parsing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface SecurityHardeningOptions {
|
|
6
|
+
maxCircularReferences: number;
|
|
7
|
+
validateStructureIntegrity: boolean;
|
|
8
|
+
enableContentInspection: boolean;
|
|
9
|
+
logSecurityEvents: boolean;
|
|
10
|
+
maxNestingDepth: number;
|
|
11
|
+
enableCircularReferenceDetection: boolean;
|
|
12
|
+
detectAndBlock: boolean;
|
|
13
|
+
sanitizeOnFailure: boolean;
|
|
14
|
+
validationPolicy: 'strict' | 'moderate' | 'lenient';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SecurityEvent {
|
|
18
|
+
timestamp: number;
|
|
19
|
+
type: SecurityEventType;
|
|
20
|
+
path: string;
|
|
21
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
22
|
+
message: string;
|
|
23
|
+
details?: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type SecurityEventType =
|
|
27
|
+
| 'circular_reference'
|
|
28
|
+
| 'deep_nesting'
|
|
29
|
+
| 'oversized_object'
|
|
30
|
+
| 'potential_injection'
|
|
31
|
+
| 'invalid_structure'
|
|
32
|
+
| 'content_inspection_warning'
|
|
33
|
+
| 'schema_violation';
|
|
34
|
+
|
|
35
|
+
export interface StructureStats {
|
|
36
|
+
maxDepth: number;
|
|
37
|
+
totalKeys: number;
|
|
38
|
+
circularReferences: number;
|
|
39
|
+
uniqueObjects: number;
|
|
40
|
+
totalSize: number;
|
|
41
|
+
deepestPath: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ContentIssue {
|
|
45
|
+
path: string;
|
|
46
|
+
type: string;
|
|
47
|
+
severity: 'low' | 'medium' | 'high';
|
|
48
|
+
description: string;
|
|
49
|
+
pattern: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface SecurityHardeningStats {
|
|
53
|
+
totalEvents: number;
|
|
54
|
+
recentEvents: number;
|
|
55
|
+
passes: number;
|
|
56
|
+
fails: number;
|
|
57
|
+
warnings: number;
|
|
58
|
+
securityScore: number;
|
|
59
|
+
eventsByType: Record<string, number>;
|
|
60
|
+
recentAlerts: SecurityEvent[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const DEFAULT_HARDENING_OPTIONS: SecurityHardeningOptions = {
|
|
64
|
+
maxCircularReferences: 0,
|
|
65
|
+
validateStructureIntegrity: true,
|
|
66
|
+
enableContentInspection: true,
|
|
67
|
+
logSecurityEvents: true,
|
|
68
|
+
maxNestingDepth: 1000,
|
|
69
|
+
enableCircularReferenceDetection: true,
|
|
70
|
+
detectAndBlock: true,
|
|
71
|
+
sanitizeOnFailure: true,
|
|
72
|
+
validationPolicy: 'moderate'
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export class SecurityHardening {
|
|
76
|
+
private readonly options: SecurityHardeningOptions;
|
|
77
|
+
private events: SecurityEvent[] = [];
|
|
78
|
+
private passes = 0;
|
|
79
|
+
private fails = 0;
|
|
80
|
+
private warnings = 0;
|
|
81
|
+
|
|
82
|
+
constructor(options: Partial<SecurityHardeningOptions> = {}) {
|
|
83
|
+
this.options = { ...DEFAULT_HARDENING_OPTIONS, ...options };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Executa hardening completo em um objeto
|
|
88
|
+
*/
|
|
89
|
+
public harden(obj: any): {
|
|
90
|
+
result: any;
|
|
91
|
+
secure: boolean;
|
|
92
|
+
stats: SecurityHardeningStats;
|
|
93
|
+
} {
|
|
94
|
+
this.resetStatistics();
|
|
95
|
+
|
|
96
|
+
let result = obj;
|
|
97
|
+
let secure = true;
|
|
98
|
+
|
|
99
|
+
// 1. Detecção de referências circulares
|
|
100
|
+
if (this.options.enableCircularReferenceDetection) {
|
|
101
|
+
try {
|
|
102
|
+
this.detectCircularReferences(result);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
105
|
+
if (this.options.detectAndBlock) {
|
|
106
|
+
throw new Error(`Referência circular detectada: ${errorMessage}`);
|
|
107
|
+
}
|
|
108
|
+
this.fails++;
|
|
109
|
+
secure = false;
|
|
110
|
+
if (this.options.logSecurityEvents) {
|
|
111
|
+
this.addSecurityEvent(
|
|
112
|
+
'circular_reference',
|
|
113
|
+
'root',
|
|
114
|
+
'high',
|
|
115
|
+
errorMessage
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
if (this.options.sanitizeOnFailure) {
|
|
119
|
+
result = this.sanitizeObject(result);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 2. Validação de integridade estrutural
|
|
125
|
+
if (this.options.validateStructureIntegrity) {
|
|
126
|
+
try {
|
|
127
|
+
this.validateObjectStructure(result);
|
|
128
|
+
this.passes++;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
this.fails++;
|
|
131
|
+
secure = false;
|
|
132
|
+
if (this.options.logSecurityEvents) {
|
|
133
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
134
|
+
this.addSecurityEvent(
|
|
135
|
+
'invalid_structure',
|
|
136
|
+
'root',
|
|
137
|
+
'medium',
|
|
138
|
+
errorMessage
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 3. Inspeção de conteúdo
|
|
145
|
+
if (this.options.enableContentInspection) {
|
|
146
|
+
const contentResult = this.inspectContent(result);
|
|
147
|
+
if (contentResult.warnings > 0) {
|
|
148
|
+
this.warnings += contentResult.warnings;
|
|
149
|
+
if (this.options.logSecurityEvents) {
|
|
150
|
+
contentResult.issues.forEach((issue: ContentIssue) => {
|
|
151
|
+
this.addSecurityEvent(
|
|
152
|
+
'content_inspection_warning',
|
|
153
|
+
issue.path,
|
|
154
|
+
this.mapSeverity(issue.severity),
|
|
155
|
+
`${issue.type} detectado`
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
result,
|
|
164
|
+
secure,
|
|
165
|
+
stats: this.getStatistics()
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Detecta referências circulares no objeto
|
|
171
|
+
*/
|
|
172
|
+
public detectCircularReferences(obj: any, visited = new WeakSet(), path = 'root'): void {
|
|
173
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (visited.has(obj)) {
|
|
178
|
+
throw new Error(`Referência circular detectada em ${path}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Verifica limite de profundidade
|
|
182
|
+
const depth = path.split('.').length;
|
|
183
|
+
if (depth > this.options.maxNestingDepth) {
|
|
184
|
+
this.addSecurityEvent(
|
|
185
|
+
'deep_nesting',
|
|
186
|
+
path,
|
|
187
|
+
'medium',
|
|
188
|
+
`Profundidade máxima de ${this.options.maxNestingDepth} excedida`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
visited.add(obj);
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
196
|
+
if (typeof value === 'object' && value !== null) {
|
|
197
|
+
// Simplificar para evitar problemas com WeakSet
|
|
198
|
+
this.detectCircularReferences(value, new WeakSet(), `${path}.${key}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
} finally {
|
|
202
|
+
visited.delete(obj);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Valida a integridade estrutural do objeto
|
|
208
|
+
*/
|
|
209
|
+
public validateObjectStructure(obj: any): boolean {
|
|
210
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return this.isValidStructure(obj, '', 0);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private isValidStructure(obj: any, path: string, depth: number): boolean {
|
|
218
|
+
// Verifica limite de profundidade
|
|
219
|
+
if (depth > this.options.maxNestingDepth) {
|
|
220
|
+
this.addSecurityEvent(
|
|
221
|
+
'deep_nesting',
|
|
222
|
+
path,
|
|
223
|
+
'medium',
|
|
224
|
+
`Profundidade máxima de ${this.options.maxNestingDepth} atingida`
|
|
225
|
+
);
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Verifica tipos válidos
|
|
230
|
+
if (!this.isAllowedType(obj)) {
|
|
231
|
+
this.addSecurityEvent(
|
|
232
|
+
'invalid_structure',
|
|
233
|
+
path,
|
|
234
|
+
'medium',
|
|
235
|
+
`Tipo inválido ${typeof obj} detectado no caminho ${path}`
|
|
236
|
+
);
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Valida objetos aninhados
|
|
241
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
242
|
+
if (Array.isArray(obj)) {
|
|
243
|
+
for (let i = 0; i < obj.length; i++) {
|
|
244
|
+
if (!this.isValidStructure(obj[i], `${path}[${i}]`, depth + 1)) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
250
|
+
const keyPath = path ? `${path}.${key}` : key;
|
|
251
|
+
if (!this.isValidStructure(value, keyPath, depth + 1)) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Verifica se um tipo é permitido
|
|
263
|
+
*/
|
|
264
|
+
private isAllowedType(obj: any): boolean {
|
|
265
|
+
const type = typeof obj;
|
|
266
|
+
|
|
267
|
+
if (obj === null) return true;
|
|
268
|
+
if (type === 'boolean') return true;
|
|
269
|
+
if (type === 'number') return true;
|
|
270
|
+
if (type === 'string') return true;
|
|
271
|
+
if (Array.isArray(obj)) return true;
|
|
272
|
+
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Inspeciona o conteúdo para padrões perigosos
|
|
278
|
+
*/
|
|
279
|
+
public inspectContent(obj: any): {
|
|
280
|
+
issues: ContentIssue[];
|
|
281
|
+
warnings: number;
|
|
282
|
+
} {
|
|
283
|
+
const issues: ContentIssue[] = [];
|
|
284
|
+
let warnings = 0;
|
|
285
|
+
|
|
286
|
+
const deepInspect = (current: any, path: string = 'root') => {
|
|
287
|
+
if (typeof current === 'string') {
|
|
288
|
+
// Padrões de vulnerabilidade
|
|
289
|
+
const vulnerabilityPatterns = [
|
|
290
|
+
{
|
|
291
|
+
pattern: /<script[^>]*>/i,
|
|
292
|
+
type: 'XSS',
|
|
293
|
+
severity: 'high' as const,
|
|
294
|
+
description: 'Possível tentativa de XSS via script tag'
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
pattern: /javascript:/i,
|
|
298
|
+
type: 'URL_INJECTION',
|
|
299
|
+
severity: 'high' as const,
|
|
300
|
+
description: 'Possível inject javascript: URL'
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
pattern: /\$\{.*\}/,
|
|
304
|
+
type: 'TEMPLATE_INJECTION',
|
|
305
|
+
severity: 'medium' as const,
|
|
306
|
+
description: 'Possível template string injection'
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
pattern: /on\w+\s*=/i,
|
|
310
|
+
type: 'EVENT_HANDLER',
|
|
311
|
+
severity: 'medium' as const,
|
|
312
|
+
description: 'Possível event handler injection'
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
pattern: /eval\s*\(/i,
|
|
316
|
+
type: 'CODE_EXECUTION',
|
|
317
|
+
severity: 'high' as const,
|
|
318
|
+
description: 'Possível code execution via eval'
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
pattern: /(password|api_key|secret|token)\s*[:=]\s*["']?[\w\-]+["']?/i,
|
|
322
|
+
type: 'CREDENTIAL_LEAK',
|
|
323
|
+
severity: 'medium' as const,
|
|
324
|
+
description: 'Possível exposição de credenciais'
|
|
325
|
+
}
|
|
326
|
+
];
|
|
327
|
+
|
|
328
|
+
for (const rule of vulnerabilityPatterns) {
|
|
329
|
+
if (rule.pattern.test(current)) {
|
|
330
|
+
issues.push({
|
|
331
|
+
path,
|
|
332
|
+
type: rule.type,
|
|
333
|
+
severity: rule.severity,
|
|
334
|
+
description: rule.description,
|
|
335
|
+
pattern: rule.pattern.source
|
|
336
|
+
});
|
|
337
|
+
warnings++;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Recursivamente inspeciona objetos aninhados
|
|
343
|
+
if (typeof current === 'object' && current !== null) {
|
|
344
|
+
if (Array.isArray(current)) {
|
|
345
|
+
current.forEach((item, index) => {
|
|
346
|
+
deepInspect(item, `${path}[${index}]`);
|
|
347
|
+
});
|
|
348
|
+
} else {
|
|
349
|
+
for (const [key, value] of Object.entries(current)) {
|
|
350
|
+
deepInspect(value, `${path}.${key}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
deepInspect(obj);
|
|
357
|
+
return { issues, warnings };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Sanitiza um objeto remover conteúdo potencialmente perigoso
|
|
362
|
+
*/
|
|
363
|
+
public sanitizeObject(obj: any): any {
|
|
364
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
365
|
+
return obj;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const visited = new WeakSet();
|
|
369
|
+
|
|
370
|
+
const sanitize = (current: any): any => {
|
|
371
|
+
if (typeof current !== 'object' || current === null) {
|
|
372
|
+
return this.sanitizeString(typeof current === 'string' ? current : '');
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (visited.has(current)) {
|
|
376
|
+
throw new Error('Referência circular detectada durante a sanitização');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
visited.add(current);
|
|
380
|
+
|
|
381
|
+
// Sanitização baseada em tipo
|
|
382
|
+
if (Array.isArray(current)) {
|
|
383
|
+
const sanitized: any[] = [];
|
|
384
|
+
for (const item of current) {
|
|
385
|
+
const sanitizedItem = sanitize(item);
|
|
386
|
+
if (sanitizedItem !== undefined) {
|
|
387
|
+
sanitized.push(sanitizedItem);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
visited.delete(current);
|
|
391
|
+
return sanitized;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const sanitized: Record<string, any> = {};
|
|
395
|
+
for (const [key, value] of Object.entries(current)) {
|
|
396
|
+
const sanitizedKey = this.sanitizeString(key);
|
|
397
|
+
const sanitizedValue = sanitize(value);
|
|
398
|
+
|
|
399
|
+
if (sanitizedValue !== undefined) {
|
|
400
|
+
sanitized[sanitizedKey] = sanitizedValue;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
visited.delete(current);
|
|
405
|
+
return sanitized;
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
return sanitize(obj);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Sanitiza strings removendo conteúdo perigoso
|
|
413
|
+
*/
|
|
414
|
+
private sanitizeString(str: string): string {
|
|
415
|
+
if (!str || typeof str !== 'string') {
|
|
416
|
+
return '';
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Remove scripts e conteúdo HTML/JavaScript
|
|
420
|
+
let sanitized = str
|
|
421
|
+
.replace(/<script[^>]*>.*?<\/script>/gi, '')
|
|
422
|
+
.replace(/javascript:/gi, '')
|
|
423
|
+
.replace(/on\w+\s*=/gi, '')
|
|
424
|
+
.replace(/eval\s*\(/gi, '')
|
|
425
|
+
.replace(/expression\s*\(/gi, '');
|
|
426
|
+
|
|
427
|
+
// Limita tamanho da string
|
|
428
|
+
return sanitized.length > 100000 ? sanitized.substring(0, 100000) + '[truncated]' : sanitized;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Adiciona um evento de segurança
|
|
433
|
+
*/
|
|
434
|
+
private addSecurityEvent(
|
|
435
|
+
type: SecurityEventType,
|
|
436
|
+
path: string,
|
|
437
|
+
severity: 'low' | 'medium' | 'high' | 'critical',
|
|
438
|
+
message: string,
|
|
439
|
+
details?: any
|
|
440
|
+
): void {
|
|
441
|
+
this.events.push({
|
|
442
|
+
timestamp: Date.now(),
|
|
443
|
+
type,
|
|
444
|
+
path,
|
|
445
|
+
severity,
|
|
446
|
+
message,
|
|
447
|
+
details
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Limita número de eventos para evitar vazamento de memória
|
|
451
|
+
if (this.events.length > 1000) {
|
|
452
|
+
this.events = this.events.slice(-500);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Obtém estatísticas do hardening
|
|
458
|
+
*/
|
|
459
|
+
public getStatistics(): SecurityHardeningStats {
|
|
460
|
+
const now = Date.now();
|
|
461
|
+
const recentEvents = this.events.filter(e => now - e.timestamp < 30000); // Últimos 30 segundos
|
|
462
|
+
|
|
463
|
+
return {
|
|
464
|
+
totalEvents: this.events.length,
|
|
465
|
+
recentEvents: recentEvents.length,
|
|
466
|
+
passes: this.passes,
|
|
467
|
+
fails: this.fails,
|
|
468
|
+
warnings: this.warnings,
|
|
469
|
+
securityScore: this.calculateSecurityScore(),
|
|
470
|
+
eventsByType: this.groupEventsByType(),
|
|
471
|
+
recentAlerts: this.getRecentAlerts()
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Calcula o score de segurança (0-100)
|
|
477
|
+
*/
|
|
478
|
+
private calculateSecurityScore(): number {
|
|
479
|
+
if (this.events.length === 0) {
|
|
480
|
+
return 100;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const total = this.passes + this.fails;
|
|
484
|
+
if (total === 0) {
|
|
485
|
+
return 50; // Nenhum teste executado
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const successRate = this.passes / total;
|
|
489
|
+
const penalty = this.warnings * 0.5; // Penaliza por warnings
|
|
490
|
+
|
|
491
|
+
return Math.max(0, Math.min(100, (successRate * 100) - penalty));
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Agrupa eventos por tipo
|
|
496
|
+
*/
|
|
497
|
+
private groupEventsByType(): Record<string, number> {
|
|
498
|
+
const counts: Record<string, number> = {};
|
|
499
|
+
this.events.forEach(event => {
|
|
500
|
+
counts[event.type] = (counts[event.type] || 0) + 1;
|
|
501
|
+
});
|
|
502
|
+
return counts;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Obtém alertas recentes
|
|
507
|
+
*/
|
|
508
|
+
private getRecentAlerts(): SecurityEvent[] {
|
|
509
|
+
const now = Date.now();
|
|
510
|
+
return this.events
|
|
511
|
+
.filter(e =>
|
|
512
|
+
now - e.timestamp < 60000 && // Último minuto
|
|
513
|
+
(e.severity === 'high' || e.severity === 'critical')
|
|
514
|
+
)
|
|
515
|
+
.slice(-10); // Últimos 10 alertas
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Mapeia severidade para uso de eventos
|
|
520
|
+
*/
|
|
521
|
+
private mapSeverity(severity: string): 'low' | 'medium' | 'high' {
|
|
522
|
+
if (severity === 'high' || severity === 'critical') return 'high';
|
|
523
|
+
if (severity === 'medium') return 'medium';
|
|
524
|
+
return 'low';
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Reinicia as estatísticas
|
|
529
|
+
*/
|
|
530
|
+
private resetStatistics(): void {
|
|
531
|
+
this.passes = 0;
|
|
532
|
+
this.fails = 0;
|
|
533
|
+
this.warnings = 0;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Executa limpeza e validação final
|
|
538
|
+
*/
|
|
539
|
+
public cleanup(): void {
|
|
540
|
+
// Remove eventos antigos (máx 24 horas)
|
|
541
|
+
const cutoff = Date.now() - (24 * 60 * 60 * 1000);
|
|
542
|
+
this.events = this.events.filter(e => e.timestamp > cutoff);
|
|
543
|
+
|
|
544
|
+
// Limita número de eventos
|
|
545
|
+
if (this.events.length > 10000) {
|
|
546
|
+
this.events = this.events.slice(-5000);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Função auxiliar para criar instância de hardening
|
|
553
|
+
*/
|
|
554
|
+
function createSecurityHardening(
|
|
555
|
+
options: Partial<SecurityHardeningOptions> = {}
|
|
556
|
+
): SecurityHardening {
|
|
557
|
+
return new SecurityHardening(options);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
export { createSecurityHardening };
|