@collabchron/tharos 0.1.0 ā 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +31 -7
- package/dist/hooks/manager.js +4 -2
- package/dist/index.js +14 -113
- package/dist/tharos-core.exe +0 -0
- package/dist/tharos.exe +0 -0
- package/package.json +3 -8
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -12,8 +12,11 @@ Tharos is a comprehensive security analysis tool that combines static code analy
|
|
|
12
12
|
|
|
13
13
|
### š Multi-Layer Security Analysis
|
|
14
14
|
- **AST-Based Detection**: Fast, accurate pattern matching for common vulnerabilities
|
|
15
|
+
- **Scanner Mindset**: Context-aware analysis that ignores test files and mock data
|
|
16
|
+
- **Weighted Blocking**: Intelligent CI/CD gating based on finding severity
|
|
15
17
|
- **AI Semantic Analysis**: Deep understanding of code context and intent
|
|
16
18
|
- **Risk Scoring**: Automated 0-100 risk assessment for every finding
|
|
19
|
+
- **SARIF Export**: Standardized reporting for GitHub Advanced Security & other tools
|
|
17
20
|
- **Suggested Fixes**: AI-generated code snippets to resolve issues
|
|
18
21
|
|
|
19
22
|
### š Multi-Language Support
|
|
@@ -115,18 +118,39 @@ cp node_modules/tharos/policies/soc2.yaml tharos.yaml
|
|
|
115
118
|
cp node_modules/tharos/policies/gdpr.yaml tharos.yaml
|
|
116
119
|
```
|
|
117
120
|
|
|
118
|
-
### 3. Set Up AI (Optional)
|
|
121
|
+
### 3. Set Up AI Providers (Optional but Recommended)
|
|
122
|
+
|
|
123
|
+
Tharos works without AI but provides **deeper insights** with it enabled. Choose either provider (both have free tiers):
|
|
124
|
+
|
|
125
|
+
#### š§ Option 1: Google Gemini (Recommended)
|
|
126
|
+
**Best for:** Powerful analysis, generous free tier
|
|
127
|
+
|
|
119
128
|
```bash
|
|
120
|
-
#
|
|
121
|
-
export
|
|
129
|
+
# Get your API key from https://makersuite.google.com/app/apikey
|
|
130
|
+
export GEMINI_API_KEY="your-gemini-key-here"
|
|
122
131
|
|
|
123
|
-
#
|
|
124
|
-
|
|
132
|
+
# Or on Windows PowerShell:
|
|
133
|
+
$env:GEMINI_API_KEY="your-gemini-key-here"
|
|
134
|
+
```
|
|
125
135
|
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
#### ā” Option 2: Groq (Fast & Free)
|
|
137
|
+
**Best for:** Speed, low latency
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Get your free API key from https://console.groq.com
|
|
141
|
+
export GROQ_API_KEY="your-groq-key-here"
|
|
142
|
+
|
|
143
|
+
# Or on Windows PowerShell:
|
|
144
|
+
$env:GROQ_API_KEY="your-groq-key-here"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Check your setup:**
|
|
148
|
+
```bash
|
|
149
|
+
tharos core setup
|
|
128
150
|
```
|
|
129
151
|
|
|
152
|
+
|
|
153
|
+
|
|
130
154
|
### 4. Run Analysis
|
|
131
155
|
```bash
|
|
132
156
|
# Check all staged files
|
package/dist/hooks/manager.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
const execAsync = promisify(exec);
|
|
4
6
|
const HOOK_CONTENT = `#!/bin/sh
|
|
5
7
|
# Tharos Git Hook
|
|
6
8
|
// This hook is managed by Tharos. Do not modify manually.
|
|
@@ -52,7 +54,7 @@ export async function verifyHooks() {
|
|
|
52
54
|
}
|
|
53
55
|
async function findGitDir() {
|
|
54
56
|
try {
|
|
55
|
-
const { stdout } = await
|
|
57
|
+
const { stdout } = await execAsync('git rev-parse --git-dir');
|
|
56
58
|
return path.resolve(stdout.trim());
|
|
57
59
|
}
|
|
58
60
|
catch {
|
package/dist/index.js
CHANGED
|
@@ -1,120 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import chalk from 'chalk';
|
|
2
|
+
import { spawn } from 'child_process';
|
|
4
3
|
import path from 'path';
|
|
5
4
|
import { fileURLToPath } from 'url';
|
|
6
|
-
import { initHooks, verifyHooks } from './hooks/manager.js';
|
|
7
5
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
.action(async () => {
|
|
17
|
-
console.log(chalk.cyan('š”ļø Initializing Tharos...'));
|
|
18
|
-
try {
|
|
19
|
-
await initHooks();
|
|
20
|
-
console.log(chalk.green('ā
Tharos hooks installed successfully!'));
|
|
21
|
-
}
|
|
22
|
-
catch (error) {
|
|
23
|
-
console.error(chalk.red('ā Failed to initialize Tharos:'), error);
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
6
|
+
// Path to the Go binary
|
|
7
|
+
const binaryName = process.platform === 'win32' ? 'tharos.exe' : 'tharos';
|
|
8
|
+
const binaryPath = path.resolve(__dirname, binaryName);
|
|
9
|
+
// Pass all arguments to the Go binary
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const child = spawn(binaryPath, args, {
|
|
12
|
+
stdio: 'inherit',
|
|
13
|
+
shell: false
|
|
26
14
|
});
|
|
27
|
-
|
|
28
|
-
.
|
|
29
|
-
.description('Synchronize organizational policies with the cloud')
|
|
30
|
-
.action(async () => {
|
|
31
|
-
console.log(chalk.cyan('āļø Syncing Tharos policies with cloud...'));
|
|
32
|
-
await new Promise(resolve => setTimeout(resolve, 1500)); // Simulate network latency
|
|
33
|
-
console.log(chalk.green('ā
Organizational policies synchronized!'));
|
|
34
|
-
console.log(chalk.gray(' Applied Policy: SEC-RULE-2026 (Enforced)'));
|
|
15
|
+
child.on('exit', (code) => {
|
|
16
|
+
process.exit(code || 0);
|
|
35
17
|
});
|
|
36
|
-
|
|
37
|
-
.
|
|
38
|
-
.
|
|
39
|
-
.option('--self-heal', 'Perform self-healing if hooks are missing or tampered')
|
|
40
|
-
.action(async (options) => {
|
|
41
|
-
if (options.selfHeal) {
|
|
42
|
-
await verifyHooks();
|
|
43
|
-
}
|
|
44
|
-
console.log(chalk.cyan('š”ļø Tharos is analyzing your intent...'));
|
|
45
|
-
try {
|
|
46
|
-
const { execa } = await import('execa');
|
|
47
|
-
// Get staged files
|
|
48
|
-
const { stdout: stagedFiles } = await execa('git', ['diff', '--cached', '--name-only']);
|
|
49
|
-
const files = stagedFiles.split('\n').filter(f => f.match(/\.(js|ts|jsx|tsx)$/));
|
|
50
|
-
if (files.length === 0) {
|
|
51
|
-
console.log(chalk.gray('No relevant files staged for commit.'));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
let globalBlock = false;
|
|
55
|
-
for (const file of files) {
|
|
56
|
-
console.log(chalk.white(`\nš Analyzing ${chalk.bold(file)}...`));
|
|
57
|
-
try {
|
|
58
|
-
const corePath = path.resolve(__dirname, 'tharos-core.exe');
|
|
59
|
-
const { stdout } = await execa(corePath, ['analyze', file]);
|
|
60
|
-
const result = JSON.parse(stdout);
|
|
61
|
-
// Display Findings
|
|
62
|
-
if (result.findings && result.findings.length > 0) {
|
|
63
|
-
result.findings.forEach((finding) => {
|
|
64
|
-
const color = finding.severity === 'block' ? chalk.red : chalk.yellow;
|
|
65
|
-
const icon = finding.severity === 'block' ? 'š' : 'ā ļø';
|
|
66
|
-
console.log(` ${icon} ${color(finding.type.toUpperCase())}: ${finding.message}`);
|
|
67
|
-
if (finding.line) {
|
|
68
|
-
console.log(chalk.gray(` Line ${finding.line}`));
|
|
69
|
-
}
|
|
70
|
-
if (finding.severity === 'block')
|
|
71
|
-
globalBlock = true;
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
console.log(chalk.green(' ā
No issues found.'));
|
|
76
|
-
}
|
|
77
|
-
// Display AI Insights
|
|
78
|
-
if (result.ai_insights && result.ai_insights.length > 0) {
|
|
79
|
-
console.log(chalk.blue.italic('\n š§ Tharos AI Semantic Insights:'));
|
|
80
|
-
result.ai_insights.forEach((insight) => {
|
|
81
|
-
if (typeof insight === 'string') {
|
|
82
|
-
console.log(` ⨠${insight}`);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const score = insight.risk_score || 50;
|
|
86
|
-
const recommendation = insight.recommendation || insight;
|
|
87
|
-
const scoreColor = score > 70 ? chalk.red : score > 40 ? chalk.yellow : chalk.green;
|
|
88
|
-
console.log(` ⨠${recommendation}`);
|
|
89
|
-
console.log(` š Risk Score: ${scoreColor(score + '/100')}`);
|
|
90
|
-
if (insight.suggested_fix) {
|
|
91
|
-
console.log(chalk.cyan('\n š” Suggested Fix:'));
|
|
92
|
-
console.log(chalk.gray(' ---------------------------------------'));
|
|
93
|
-
console.log(insight.suggested_fix.split('\n').map((line) => ` ${line}`).join('\n'));
|
|
94
|
-
console.log(chalk.gray(' ---------------------------------------'));
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
else if (result.findings && result.findings.length > 0) {
|
|
99
|
-
console.log(chalk.gray('\n š” Tip: No AI insights available.'));
|
|
100
|
-
console.log(chalk.gray(' Run "ollama serve" or use Tharos Cloud for smart analysis.'));
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
catch (e) {
|
|
104
|
-
console.error(chalk.red(` ā Failed to analyze ${file}:`), e);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (globalBlock) {
|
|
108
|
-
console.log(chalk.red('\nš Commit blocked by Tharos policy. Please fix the issues above.'));
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
console.log(chalk.green('\n⨠Tharos logic check passed! Proceeding...'));
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
console.error(chalk.red('ā Tharos check execution failed:'), error);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
18
|
+
child.on('error', (err) => {
|
|
19
|
+
console.error(`Failed to start Tharos binary: ${err.message}`);
|
|
20
|
+
process.exit(1);
|
|
119
21
|
});
|
|
120
|
-
program.parse();
|
|
Binary file
|
package/dist/tharos.exe
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@collabchron/tharos",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Tharos: Intelligent, Unbreakable Code Policy Enforcement",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"security",
|
|
@@ -26,18 +26,13 @@
|
|
|
26
26
|
"tharos": "dist/index.js"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
|
-
"build": "tsc",
|
|
29
|
+
"build": "tsc && copy go-core\\tharos.exe dist\\tharos.exe",
|
|
30
30
|
"start": "node --loader ts-node/esm src/index.ts",
|
|
31
31
|
"dev": "node --loader ts-node/esm src/index.ts",
|
|
32
32
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
33
33
|
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"chalk": "^5.3.0",
|
|
36
|
-
"commander": "^12.0.0",
|
|
37
|
-
"execa": "^8.0.1"
|
|
38
|
-
},
|
|
34
|
+
"dependencies": {},
|
|
39
35
|
"devDependencies": {
|
|
40
|
-
"@napi-rs/cli": "^3.5.1",
|
|
41
36
|
"@types/node": "^20.11.0",
|
|
42
37
|
"ts-node": "^10.9.2",
|
|
43
38
|
"typescript": "^5.3.3"
|