aura-security 0.4.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/LICENSE +21 -0
- package/README.md +446 -0
- package/deploy/AWS-DEPLOYMENT.md +358 -0
- package/deploy/terraform/main.tf +362 -0
- package/deploy/terraform/terraform.tfvars.example +6 -0
- package/dist/agents/base.d.ts +44 -0
- package/dist/agents/base.js +96 -0
- package/dist/agents/index.d.ts +14 -0
- package/dist/agents/index.js +17 -0
- package/dist/agents/policy/evaluator.d.ts +15 -0
- package/dist/agents/policy/evaluator.js +183 -0
- package/dist/agents/policy/index.d.ts +12 -0
- package/dist/agents/policy/index.js +15 -0
- package/dist/agents/policy/validator.d.ts +15 -0
- package/dist/agents/policy/validator.js +182 -0
- package/dist/agents/scanners/gitleaks.d.ts +14 -0
- package/dist/agents/scanners/gitleaks.js +155 -0
- package/dist/agents/scanners/grype.d.ts +14 -0
- package/dist/agents/scanners/grype.js +109 -0
- package/dist/agents/scanners/index.d.ts +15 -0
- package/dist/agents/scanners/index.js +27 -0
- package/dist/agents/scanners/npm-audit.d.ts +13 -0
- package/dist/agents/scanners/npm-audit.js +129 -0
- package/dist/agents/scanners/semgrep.d.ts +14 -0
- package/dist/agents/scanners/semgrep.js +131 -0
- package/dist/agents/scanners/trivy.d.ts +14 -0
- package/dist/agents/scanners/trivy.js +122 -0
- package/dist/agents/types.d.ts +137 -0
- package/dist/agents/types.js +91 -0
- package/dist/auditor/index.d.ts +3 -0
- package/dist/auditor/index.js +2 -0
- package/dist/auditor/pipeline.d.ts +19 -0
- package/dist/auditor/pipeline.js +240 -0
- package/dist/auditor/validator.d.ts +17 -0
- package/dist/auditor/validator.js +58 -0
- package/dist/aura/client.d.ts +29 -0
- package/dist/aura/client.js +125 -0
- package/dist/aura/index.d.ts +4 -0
- package/dist/aura/index.js +2 -0
- package/dist/aura/server.d.ts +45 -0
- package/dist/aura/server.js +343 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +1433 -0
- package/dist/client/index.d.ts +41 -0
- package/dist/client/index.js +170 -0
- package/dist/compliance/index.d.ts +40 -0
- package/dist/compliance/index.js +292 -0
- package/dist/database/index.d.ts +77 -0
- package/dist/database/index.js +395 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +762 -0
- package/dist/integrations/aura-scanner.d.ts +69 -0
- package/dist/integrations/aura-scanner.js +155 -0
- package/dist/integrations/aws-scanner.d.ts +63 -0
- package/dist/integrations/aws-scanner.js +624 -0
- package/dist/integrations/config.d.ts +69 -0
- package/dist/integrations/config.js +212 -0
- package/dist/integrations/github.d.ts +45 -0
- package/dist/integrations/github.js +201 -0
- package/dist/integrations/gitlab.d.ts +36 -0
- package/dist/integrations/gitlab.js +110 -0
- package/dist/integrations/index.d.ts +11 -0
- package/dist/integrations/index.js +11 -0
- package/dist/integrations/local-scanner.d.ts +146 -0
- package/dist/integrations/local-scanner.js +1654 -0
- package/dist/integrations/notifications.d.ts +99 -0
- package/dist/integrations/notifications.js +305 -0
- package/dist/integrations/scanners.d.ts +57 -0
- package/dist/integrations/scanners.js +217 -0
- package/dist/integrations/slop-scanner.d.ts +69 -0
- package/dist/integrations/slop-scanner.js +155 -0
- package/dist/integrations/webhook.d.ts +37 -0
- package/dist/integrations/webhook.js +256 -0
- package/dist/orchestrator/index.d.ts +72 -0
- package/dist/orchestrator/index.js +187 -0
- package/dist/output/index.d.ts +152 -0
- package/dist/output/index.js +399 -0
- package/dist/pipeline/index.d.ts +72 -0
- package/dist/pipeline/index.js +313 -0
- package/dist/sbom/index.d.ts +94 -0
- package/dist/sbom/index.js +298 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/input.schema.d.ts +87 -0
- package/dist/schemas/input.schema.js +44 -0
- package/dist/schemas/output.schema.d.ts +115 -0
- package/dist/schemas/output.schema.js +64 -0
- package/dist/serve-visualizer.d.ts +2 -0
- package/dist/serve-visualizer.js +78 -0
- package/dist/slop/client.d.ts +29 -0
- package/dist/slop/client.js +125 -0
- package/dist/slop/index.d.ts +4 -0
- package/dist/slop/index.js +2 -0
- package/dist/slop/server.d.ts +45 -0
- package/dist/slop/server.js +343 -0
- package/dist/types/events.d.ts +62 -0
- package/dist/types/events.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/visualizer/index.d.ts +4 -0
- package/dist/visualizer/index.js +181 -0
- package/dist/websocket/index.d.ts +88 -0
- package/dist/websocket/index.js +195 -0
- package/dist/zones/index.d.ts +7 -0
- package/dist/zones/index.js +7 -0
- package/dist/zones/manager.d.ts +101 -0
- package/dist/zones/manager.js +304 -0
- package/dist/zones/types.d.ts +78 -0
- package/dist/zones/types.js +33 -0
- package/package.json +84 -0
- package/visualizer/app.js +0 -0
- package/visualizer/index-minimal.html +1771 -0
- package/visualizer/index.html +2933 -0
- package/visualizer/landing.html +1328 -0
- package/visualizer/styles.css +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Base Agent
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class for all agents.
|
|
5
|
+
*/
|
|
6
|
+
import { Agent, AgentConfig, AgentCapabilities, AgentStatus, AgentResult } from './types.js';
|
|
7
|
+
import { ZoneContext, ZoneFinding } from '../zones/types.js';
|
|
8
|
+
export declare abstract class BaseAgent implements Agent {
|
|
9
|
+
readonly config: AgentConfig;
|
|
10
|
+
readonly capabilities: AgentCapabilities;
|
|
11
|
+
protected status: AgentStatus;
|
|
12
|
+
constructor(config: AgentConfig, capabilities: AgentCapabilities);
|
|
13
|
+
/**
|
|
14
|
+
* Check if external tool is installed
|
|
15
|
+
*/
|
|
16
|
+
protected checkToolAvailable(toolName: string): Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Execute a command and return output
|
|
19
|
+
*/
|
|
20
|
+
protected executeCommand(command: string, args: string[], options?: {
|
|
21
|
+
cwd?: string;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
stdout: string;
|
|
25
|
+
stderr: string;
|
|
26
|
+
exitCode: number;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Check if agent is available
|
|
30
|
+
*/
|
|
31
|
+
isAvailable(): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Get current status
|
|
34
|
+
*/
|
|
35
|
+
getStatus(): AgentStatus;
|
|
36
|
+
/**
|
|
37
|
+
* Execute the agent
|
|
38
|
+
*/
|
|
39
|
+
abstract execute(context: ZoneContext): Promise<AgentResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Helper to create a finding
|
|
42
|
+
*/
|
|
43
|
+
protected createFinding(agentId: string, partial: Omit<ZoneFinding, 'id' | 'agentId' | 'timestamp'>): ZoneFinding;
|
|
44
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Base Agent
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class for all agents.
|
|
5
|
+
*/
|
|
6
|
+
import { execSync, spawn } from 'child_process';
|
|
7
|
+
export class BaseAgent {
|
|
8
|
+
config;
|
|
9
|
+
capabilities;
|
|
10
|
+
status = 'idle';
|
|
11
|
+
constructor(config, capabilities) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.capabilities = capabilities;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if external tool is installed
|
|
17
|
+
*/
|
|
18
|
+
async checkToolAvailable(toolName) {
|
|
19
|
+
try {
|
|
20
|
+
execSync(`which ${toolName}`, { stdio: 'ignore' });
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Try Windows-style check
|
|
25
|
+
try {
|
|
26
|
+
execSync(`where ${toolName}`, { stdio: 'ignore' });
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Execute a command and return output
|
|
36
|
+
*/
|
|
37
|
+
async executeCommand(command, args, options = {}) {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
const proc = spawn(command, args, {
|
|
40
|
+
cwd: options.cwd,
|
|
41
|
+
shell: true,
|
|
42
|
+
timeout: options.timeout || 300000, // 5 minute default
|
|
43
|
+
});
|
|
44
|
+
let stdout = '';
|
|
45
|
+
let stderr = '';
|
|
46
|
+
proc.stdout?.on('data', (data) => {
|
|
47
|
+
stdout += data.toString();
|
|
48
|
+
});
|
|
49
|
+
proc.stderr?.on('data', (data) => {
|
|
50
|
+
stderr += data.toString();
|
|
51
|
+
});
|
|
52
|
+
proc.on('close', (code) => {
|
|
53
|
+
resolve({
|
|
54
|
+
stdout,
|
|
55
|
+
stderr,
|
|
56
|
+
exitCode: code || 0,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
proc.on('error', (err) => {
|
|
60
|
+
resolve({
|
|
61
|
+
stdout,
|
|
62
|
+
stderr: err.message,
|
|
63
|
+
exitCode: 1,
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if agent is available
|
|
70
|
+
*/
|
|
71
|
+
async isAvailable() {
|
|
72
|
+
if (!this.config.enabled)
|
|
73
|
+
return false;
|
|
74
|
+
if (this.config.externalTool) {
|
|
75
|
+
return this.checkToolAvailable(this.config.externalTool);
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get current status
|
|
81
|
+
*/
|
|
82
|
+
getStatus() {
|
|
83
|
+
return this.status;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Helper to create a finding
|
|
87
|
+
*/
|
|
88
|
+
createFinding(agentId, partial) {
|
|
89
|
+
return {
|
|
90
|
+
...partial,
|
|
91
|
+
id: `${agentId}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
92
|
+
agentId,
|
|
93
|
+
timestamp: Date.now(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Agents
|
|
3
|
+
*
|
|
4
|
+
* Export all agents and agent utilities.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export * from './base.js';
|
|
8
|
+
export * from './scanners/index.js';
|
|
9
|
+
export * from './policy/index.js';
|
|
10
|
+
import { Agent } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create all default agents
|
|
13
|
+
*/
|
|
14
|
+
export declare function createAllAgents(): Agent[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Agents
|
|
3
|
+
*
|
|
4
|
+
* Export all agents and agent utilities.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export * from './base.js';
|
|
8
|
+
export * from './scanners/index.js';
|
|
9
|
+
export * from './policy/index.js';
|
|
10
|
+
import { createScannerAgents } from './scanners/index.js';
|
|
11
|
+
import { createPolicyAgents } from './policy/index.js';
|
|
12
|
+
/**
|
|
13
|
+
* Create all default agents
|
|
14
|
+
*/
|
|
15
|
+
export function createAllAgents() {
|
|
16
|
+
return [...createScannerAgents(), ...createPolicyAgents()];
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Policy Evaluator Agent
|
|
3
|
+
*
|
|
4
|
+
* Evaluates findings against security policies.
|
|
5
|
+
* This agent provides context-aware analysis of findings.
|
|
6
|
+
*/
|
|
7
|
+
import { BaseAgent } from '../base.js';
|
|
8
|
+
import { AgentResult } from '../types.js';
|
|
9
|
+
import { ZoneContext } from '../../zones/types.js';
|
|
10
|
+
export declare class PolicyEvaluatorAgent extends BaseAgent {
|
|
11
|
+
constructor();
|
|
12
|
+
execute(context: ZoneContext): Promise<AgentResult>;
|
|
13
|
+
private evaluateFinding;
|
|
14
|
+
private reduceSeverity;
|
|
15
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Policy Evaluator Agent
|
|
3
|
+
*
|
|
4
|
+
* Evaluates findings against security policies.
|
|
5
|
+
* This agent provides context-aware analysis of findings.
|
|
6
|
+
*/
|
|
7
|
+
import { BaseAgent } from '../base.js';
|
|
8
|
+
const CONFIG = {
|
|
9
|
+
id: 'policy-evaluator',
|
|
10
|
+
name: 'Policy Evaluator',
|
|
11
|
+
role: 'policy',
|
|
12
|
+
description: 'Evaluate findings against security policies',
|
|
13
|
+
enabled: true,
|
|
14
|
+
};
|
|
15
|
+
const CAPABILITIES = {
|
|
16
|
+
requiresExternalTool: false,
|
|
17
|
+
supportsParallel: false, // Policy evaluation should be sequential
|
|
18
|
+
};
|
|
19
|
+
// File patterns that indicate test/dev context
|
|
20
|
+
const TEST_PATTERNS = [
|
|
21
|
+
/test[s]?\//i,
|
|
22
|
+
/spec[s]?\//i,
|
|
23
|
+
/__test__/i,
|
|
24
|
+
/\.test\./i,
|
|
25
|
+
/\.spec\./i,
|
|
26
|
+
/mock[s]?\//i,
|
|
27
|
+
/fixture[s]?\//i,
|
|
28
|
+
/example[s]?\//i,
|
|
29
|
+
/sample[s]?\//i,
|
|
30
|
+
/demo\//i,
|
|
31
|
+
];
|
|
32
|
+
// File patterns that indicate generated/vendored code
|
|
33
|
+
const GENERATED_PATTERNS = [
|
|
34
|
+
/node_modules\//i,
|
|
35
|
+
/vendor\//i,
|
|
36
|
+
/dist\//i,
|
|
37
|
+
/build\//i,
|
|
38
|
+
/\.min\./i,
|
|
39
|
+
/bundle\./i,
|
|
40
|
+
/generated\//i,
|
|
41
|
+
];
|
|
42
|
+
// Packages known to have false positive vulnerabilities or low impact
|
|
43
|
+
const LOW_PRIORITY_PACKAGES = [
|
|
44
|
+
'lodash', // Often has low-severity prototype pollution
|
|
45
|
+
'minimist', // Prototype pollution, but rarely exploitable
|
|
46
|
+
'qs', // Prototype pollution in old versions
|
|
47
|
+
];
|
|
48
|
+
export class PolicyEvaluatorAgent extends BaseAgent {
|
|
49
|
+
constructor() {
|
|
50
|
+
super(CONFIG, CAPABILITIES);
|
|
51
|
+
}
|
|
52
|
+
async execute(context) {
|
|
53
|
+
const startTime = Date.now();
|
|
54
|
+
this.status = 'running';
|
|
55
|
+
const processedFindings = [];
|
|
56
|
+
try {
|
|
57
|
+
context.log('info', 'Policy Evaluator analyzing findings');
|
|
58
|
+
// Get findings from scanner zone (passed via memory)
|
|
59
|
+
const scannerFindings = context.memory.data.get('scanner_findings') || [];
|
|
60
|
+
if (scannerFindings.length === 0) {
|
|
61
|
+
context.log('info', 'No findings to evaluate');
|
|
62
|
+
this.status = 'complete';
|
|
63
|
+
return {
|
|
64
|
+
agentId: this.config.id,
|
|
65
|
+
agentName: this.config.name,
|
|
66
|
+
status: 'success',
|
|
67
|
+
findings: [],
|
|
68
|
+
duration: Date.now() - startTime,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
context.log('info', `Evaluating ${scannerFindings.length} findings`);
|
|
72
|
+
for (const finding of scannerFindings) {
|
|
73
|
+
const evaluation = this.evaluateFinding(finding);
|
|
74
|
+
// Create annotated finding with policy metadata
|
|
75
|
+
const annotatedFinding = this.createFinding('policy-evaluator', {
|
|
76
|
+
...finding,
|
|
77
|
+
metadata: {
|
|
78
|
+
...finding.metadata,
|
|
79
|
+
policyEvaluation: evaluation,
|
|
80
|
+
originalSeverity: finding.severity,
|
|
81
|
+
},
|
|
82
|
+
severity: evaluation.adjustedSeverity,
|
|
83
|
+
});
|
|
84
|
+
// Add context notes
|
|
85
|
+
if (evaluation.notes.length > 0) {
|
|
86
|
+
annotatedFinding.description += `\n\nPolicy Notes:\n${evaluation.notes.map(n => `• ${n}`).join('\n')}`;
|
|
87
|
+
}
|
|
88
|
+
processedFindings.push(annotatedFinding);
|
|
89
|
+
context.addFinding(annotatedFinding);
|
|
90
|
+
}
|
|
91
|
+
// Store evaluated findings for validator
|
|
92
|
+
context.memory.data.set('evaluated_findings', processedFindings);
|
|
93
|
+
this.status = 'complete';
|
|
94
|
+
context.log('info', `Policy evaluation complete: ${processedFindings.length} findings processed`);
|
|
95
|
+
return {
|
|
96
|
+
agentId: this.config.id,
|
|
97
|
+
agentName: this.config.name,
|
|
98
|
+
status: 'success',
|
|
99
|
+
findings: processedFindings,
|
|
100
|
+
duration: Date.now() - startTime,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
this.status = 'error';
|
|
105
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
106
|
+
context.log('error', `Policy evaluation error: ${errorMsg}`);
|
|
107
|
+
return {
|
|
108
|
+
agentId: this.config.id,
|
|
109
|
+
agentName: this.config.name,
|
|
110
|
+
status: 'error',
|
|
111
|
+
findings: processedFindings,
|
|
112
|
+
duration: Date.now() - startTime,
|
|
113
|
+
error: errorMsg,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
evaluateFinding(finding) {
|
|
118
|
+
const notes = [];
|
|
119
|
+
let adjustedSeverity = finding.severity;
|
|
120
|
+
let isTestContext = false;
|
|
121
|
+
let isGenerated = false;
|
|
122
|
+
let shouldSuppress = false;
|
|
123
|
+
const filePath = finding.file || '';
|
|
124
|
+
// Check if in test context
|
|
125
|
+
if (TEST_PATTERNS.some((p) => p.test(filePath))) {
|
|
126
|
+
isTestContext = true;
|
|
127
|
+
notes.push('Found in test/example context - lower priority');
|
|
128
|
+
adjustedSeverity = this.reduceSeverity(adjustedSeverity);
|
|
129
|
+
}
|
|
130
|
+
// Check if generated/vendored
|
|
131
|
+
if (GENERATED_PATTERNS.some((p) => p.test(filePath))) {
|
|
132
|
+
isGenerated = true;
|
|
133
|
+
notes.push('Found in generated/vendored code');
|
|
134
|
+
shouldSuppress = true;
|
|
135
|
+
}
|
|
136
|
+
// Check for low-priority packages
|
|
137
|
+
const pkgName = finding.metadata?.package || '';
|
|
138
|
+
if (LOW_PRIORITY_PACKAGES.some((p) => pkgName.toLowerCase().includes(p))) {
|
|
139
|
+
notes.push(`${pkgName} is known for low-impact vulnerabilities`);
|
|
140
|
+
adjustedSeverity = this.reduceSeverity(adjustedSeverity);
|
|
141
|
+
}
|
|
142
|
+
// Secrets in env.example or sample files are likely intentional
|
|
143
|
+
if (finding.type === 'secret' &&
|
|
144
|
+
/\.(example|sample|template)/i.test(filePath)) {
|
|
145
|
+
notes.push('Secret in example/template file - likely placeholder');
|
|
146
|
+
shouldSuppress = true;
|
|
147
|
+
}
|
|
148
|
+
// Check for fix availability
|
|
149
|
+
const fixAvailable = finding.metadata?.fixAvailable;
|
|
150
|
+
if (fixAvailable === false) {
|
|
151
|
+
notes.push('No fix available yet');
|
|
152
|
+
}
|
|
153
|
+
else if (typeof fixAvailable === 'object' && fixAvailable && 'version' in fixAvailable && fixAvailable.version) {
|
|
154
|
+
notes.push(`Fix available: upgrade to ${fixAvailable.version}`);
|
|
155
|
+
}
|
|
156
|
+
// Direct dependencies are higher priority
|
|
157
|
+
if (finding.metadata?.isDirect === true) {
|
|
158
|
+
notes.push('Direct dependency - higher priority');
|
|
159
|
+
if (finding.severity === 'medium') {
|
|
160
|
+
adjustedSeverity = 'high';
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
adjustedSeverity,
|
|
165
|
+
notes,
|
|
166
|
+
isTestContext,
|
|
167
|
+
isGenerated,
|
|
168
|
+
shouldSuppress,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
reduceSeverity(severity) {
|
|
172
|
+
switch (severity) {
|
|
173
|
+
case 'critical':
|
|
174
|
+
return 'high';
|
|
175
|
+
case 'high':
|
|
176
|
+
return 'medium';
|
|
177
|
+
case 'medium':
|
|
178
|
+
return 'low';
|
|
179
|
+
default:
|
|
180
|
+
return 'info';
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Policy Agents
|
|
3
|
+
*
|
|
4
|
+
* Export all policy agents.
|
|
5
|
+
*/
|
|
6
|
+
export { PolicyEvaluatorAgent } from './evaluator.js';
|
|
7
|
+
export { ValidatorAgent } from './validator.js';
|
|
8
|
+
import { Agent } from '../types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Create all policy agents
|
|
11
|
+
*/
|
|
12
|
+
export declare function createPolicyAgents(): Agent[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Policy Agents
|
|
3
|
+
*
|
|
4
|
+
* Export all policy agents.
|
|
5
|
+
*/
|
|
6
|
+
export { PolicyEvaluatorAgent } from './evaluator.js';
|
|
7
|
+
export { ValidatorAgent } from './validator.js';
|
|
8
|
+
import { PolicyEvaluatorAgent } from './evaluator.js';
|
|
9
|
+
import { ValidatorAgent } from './validator.js';
|
|
10
|
+
/**
|
|
11
|
+
* Create all policy agents
|
|
12
|
+
*/
|
|
13
|
+
export function createPolicyAgents() {
|
|
14
|
+
return [new PolicyEvaluatorAgent(), new ValidatorAgent()];
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Validator Agent
|
|
3
|
+
*
|
|
4
|
+
* Validates and deduplicates findings, removes false positives.
|
|
5
|
+
*/
|
|
6
|
+
import { BaseAgent } from '../base.js';
|
|
7
|
+
import { AgentResult } from '../types.js';
|
|
8
|
+
import { ZoneContext } from '../../zones/types.js';
|
|
9
|
+
export declare class ValidatorAgent extends BaseAgent {
|
|
10
|
+
constructor();
|
|
11
|
+
execute(context: ZoneContext): Promise<AgentResult>;
|
|
12
|
+
private createFingerprint;
|
|
13
|
+
private isFalsePositive;
|
|
14
|
+
private calculateEntropy;
|
|
15
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Validator Agent
|
|
3
|
+
*
|
|
4
|
+
* Validates and deduplicates findings, removes false positives.
|
|
5
|
+
*/
|
|
6
|
+
import { BaseAgent } from '../base.js';
|
|
7
|
+
const CONFIG = {
|
|
8
|
+
id: 'validator',
|
|
9
|
+
name: 'Finding Validator',
|
|
10
|
+
role: 'validator',
|
|
11
|
+
description: 'Validate and deduplicate findings, remove false positives',
|
|
12
|
+
enabled: true,
|
|
13
|
+
};
|
|
14
|
+
const CAPABILITIES = {
|
|
15
|
+
requiresExternalTool: false,
|
|
16
|
+
supportsParallel: false,
|
|
17
|
+
};
|
|
18
|
+
// Patterns that indicate false positive secrets
|
|
19
|
+
const FALSE_POSITIVE_PATTERNS = [
|
|
20
|
+
// SHA hashes (commit hashes, file hashes)
|
|
21
|
+
/^[a-f0-9]{40}$/i,
|
|
22
|
+
/^[a-f0-9]{64}$/i,
|
|
23
|
+
// UUIDs
|
|
24
|
+
/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i,
|
|
25
|
+
// NPM package integrity hashes
|
|
26
|
+
/^sha512-/i,
|
|
27
|
+
/^sha256-/i,
|
|
28
|
+
// Example/placeholder values
|
|
29
|
+
/^(xxx|aaa|test|example|sample|placeholder|dummy|fake)/i,
|
|
30
|
+
/^your[-_]?(api[-_]?key|secret|token|password)/i,
|
|
31
|
+
// Version strings
|
|
32
|
+
/^\d+\.\d+\.\d+$/,
|
|
33
|
+
];
|
|
34
|
+
// File paths that commonly have false positives
|
|
35
|
+
const FALSE_POSITIVE_PATHS = [
|
|
36
|
+
/package-lock\.json$/i,
|
|
37
|
+
/yarn\.lock$/i,
|
|
38
|
+
/pnpm-lock\.yaml$/i,
|
|
39
|
+
/composer\.lock$/i,
|
|
40
|
+
/\.sum$/i,
|
|
41
|
+
/integrity.*\.txt$/i,
|
|
42
|
+
];
|
|
43
|
+
export class ValidatorAgent extends BaseAgent {
|
|
44
|
+
constructor() {
|
|
45
|
+
super(CONFIG, CAPABILITIES);
|
|
46
|
+
}
|
|
47
|
+
async execute(context) {
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
this.status = 'running';
|
|
50
|
+
const validatedFindings = [];
|
|
51
|
+
try {
|
|
52
|
+
context.log('info', 'Validator analyzing findings');
|
|
53
|
+
// Get findings from policy zone
|
|
54
|
+
const evaluatedFindings = context.memory.data.get('evaluated_findings') ||
|
|
55
|
+
context.memory.data.get('scanner_findings') ||
|
|
56
|
+
[];
|
|
57
|
+
if (evaluatedFindings.length === 0) {
|
|
58
|
+
context.log('info', 'No findings to validate');
|
|
59
|
+
this.status = 'complete';
|
|
60
|
+
return {
|
|
61
|
+
agentId: this.config.id,
|
|
62
|
+
agentName: this.config.name,
|
|
63
|
+
status: 'success',
|
|
64
|
+
findings: [],
|
|
65
|
+
duration: Date.now() - startTime,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
context.log('info', `Validating ${evaluatedFindings.length} findings`);
|
|
69
|
+
const seenFindings = new Set();
|
|
70
|
+
let falsePositives = 0;
|
|
71
|
+
let duplicates = 0;
|
|
72
|
+
let suppressed = 0;
|
|
73
|
+
for (const finding of evaluatedFindings) {
|
|
74
|
+
// Check for duplicates
|
|
75
|
+
const fingerprint = this.createFingerprint(finding);
|
|
76
|
+
if (seenFindings.has(fingerprint)) {
|
|
77
|
+
duplicates++;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
seenFindings.add(fingerprint);
|
|
81
|
+
// Check if suppressed by policy
|
|
82
|
+
if (finding.metadata?.policyEvaluation?.shouldSuppress) {
|
|
83
|
+
suppressed++;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// Check for false positives
|
|
87
|
+
if (this.isFalsePositive(finding)) {
|
|
88
|
+
falsePositives++;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// Valid finding
|
|
92
|
+
const validatedFinding = this.createFinding('validator', {
|
|
93
|
+
...finding,
|
|
94
|
+
metadata: {
|
|
95
|
+
...finding.metadata,
|
|
96
|
+
validated: true,
|
|
97
|
+
fingerprint,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
validatedFindings.push(validatedFinding);
|
|
101
|
+
context.addFinding(validatedFinding);
|
|
102
|
+
}
|
|
103
|
+
// Store validated findings
|
|
104
|
+
context.memory.data.set('validated_findings', validatedFindings);
|
|
105
|
+
this.status = 'complete';
|
|
106
|
+
context.log('info', `Validation complete: ${validatedFindings.length} valid, ` +
|
|
107
|
+
`${falsePositives} false positives, ${duplicates} duplicates, ${suppressed} suppressed`);
|
|
108
|
+
return {
|
|
109
|
+
agentId: this.config.id,
|
|
110
|
+
agentName: this.config.name,
|
|
111
|
+
status: 'success',
|
|
112
|
+
findings: validatedFindings,
|
|
113
|
+
duration: Date.now() - startTime,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
this.status = 'error';
|
|
118
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
119
|
+
context.log('error', `Validation error: ${errorMsg}`);
|
|
120
|
+
return {
|
|
121
|
+
agentId: this.config.id,
|
|
122
|
+
agentName: this.config.name,
|
|
123
|
+
status: 'error',
|
|
124
|
+
findings: validatedFindings,
|
|
125
|
+
duration: Date.now() - startTime,
|
|
126
|
+
error: errorMsg,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
createFingerprint(finding) {
|
|
131
|
+
// Create a unique fingerprint for deduplication
|
|
132
|
+
const parts = [
|
|
133
|
+
finding.type,
|
|
134
|
+
finding.file || '',
|
|
135
|
+
finding.line?.toString() || '',
|
|
136
|
+
finding.title,
|
|
137
|
+
finding.metadata?.vulnerabilityId || '',
|
|
138
|
+
finding.metadata?.package || '',
|
|
139
|
+
];
|
|
140
|
+
return parts.join('::').toLowerCase();
|
|
141
|
+
}
|
|
142
|
+
isFalsePositive(finding) {
|
|
143
|
+
const filePath = finding.file || '';
|
|
144
|
+
// Check file path patterns
|
|
145
|
+
if (FALSE_POSITIVE_PATHS.some((p) => p.test(filePath))) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
// Check secret-specific false positives
|
|
149
|
+
if (finding.type === 'secret') {
|
|
150
|
+
const match = finding.metadata?.match || '';
|
|
151
|
+
// Check against false positive patterns
|
|
152
|
+
if (FALSE_POSITIVE_PATTERNS.some((p) => p.test(match))) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
// Very short matches are likely false positives
|
|
156
|
+
if (match.length < 16) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
// Check for low entropy (unlikely to be real secrets)
|
|
160
|
+
const entropy = this.calculateEntropy(match);
|
|
161
|
+
if (entropy < 2.5) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
calculateEntropy(str) {
|
|
168
|
+
const len = str.length;
|
|
169
|
+
if (len === 0)
|
|
170
|
+
return 0;
|
|
171
|
+
const freq = {};
|
|
172
|
+
for (const char of str) {
|
|
173
|
+
freq[char] = (freq[char] || 0) + 1;
|
|
174
|
+
}
|
|
175
|
+
let entropy = 0;
|
|
176
|
+
for (const count of Object.values(freq)) {
|
|
177
|
+
const p = count / len;
|
|
178
|
+
entropy -= p * Math.log2(p);
|
|
179
|
+
}
|
|
180
|
+
return entropy;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Gitleaks Agent
|
|
3
|
+
*
|
|
4
|
+
* Scans for secrets and API keys using gitleaks.
|
|
5
|
+
*/
|
|
6
|
+
import { BaseAgent } from '../base.js';
|
|
7
|
+
import { AgentResult } from '../types.js';
|
|
8
|
+
import { ZoneContext } from '../../zones/types.js';
|
|
9
|
+
export declare class GitleaksAgent extends BaseAgent {
|
|
10
|
+
constructor();
|
|
11
|
+
execute(context: ZoneContext): Promise<AgentResult>;
|
|
12
|
+
private getSeverity;
|
|
13
|
+
private maskSecret;
|
|
14
|
+
}
|