kekkai-cli 1.1.1__py3-none-any.whl → 2.0.0__py3-none-any.whl
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.
- kekkai/cli.py +114 -3
- kekkai/output.py +2 -3
- kekkai/triage/fix_screen.py +232 -0
- kekkai/triage/screens.py +1 -0
- kekkai_cli-2.0.0.dist-info/METADATA +317 -0
- {kekkai_cli-1.1.1.dist-info → kekkai_cli-2.0.0.dist-info}/RECORD +9 -8
- kekkai_cli-1.1.1.dist-info/METADATA +0 -379
- {kekkai_cli-1.1.1.dist-info → kekkai_cli-2.0.0.dist-info}/WHEEL +0 -0
- {kekkai_cli-1.1.1.dist-info → kekkai_cli-2.0.0.dist-info}/entry_points.txt +0 -0
- {kekkai_cli-1.1.1.dist-info → kekkai_cli-2.0.0.dist-info}/top_level.txt +0 -0
kekkai/cli.py
CHANGED
|
@@ -58,6 +58,11 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
58
58
|
init_parser = subparsers.add_parser("init", help="initialize config and directories")
|
|
59
59
|
init_parser.add_argument("--config", type=str, help="Path to config file")
|
|
60
60
|
init_parser.add_argument("--force", action="store_true", help="Overwrite existing config")
|
|
61
|
+
init_parser.add_argument(
|
|
62
|
+
"--ci",
|
|
63
|
+
action="store_true",
|
|
64
|
+
help="Auto-generate GitHub Actions workflow for CI/CD integration",
|
|
65
|
+
)
|
|
61
66
|
|
|
62
67
|
scan_parser = subparsers.add_parser("scan", help="run a scan pipeline")
|
|
63
68
|
scan_parser.add_argument("--config", type=str, help="Path to config file")
|
|
@@ -147,7 +152,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
147
152
|
help="Minimum severity for PR comments (default: medium)",
|
|
148
153
|
)
|
|
149
154
|
|
|
150
|
-
dojo_parser = subparsers.add_parser("dojo", help=
|
|
155
|
+
dojo_parser = subparsers.add_parser("dojo", help=argparse.SUPPRESS)
|
|
151
156
|
dojo_subparsers = dojo_parser.add_subparsers(dest="dojo_command")
|
|
152
157
|
|
|
153
158
|
dojo_up = dojo_subparsers.add_parser("up", help="start the local DefectDojo stack")
|
|
@@ -378,7 +383,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
378
383
|
|
|
379
384
|
parsed = parser.parse_args(args)
|
|
380
385
|
if parsed.command == "init":
|
|
381
|
-
return _command_init(parsed.config, parsed.force)
|
|
386
|
+
return _command_init(parsed.config, parsed.force, parsed.ci)
|
|
382
387
|
if parsed.command == "scan":
|
|
383
388
|
return _command_scan(
|
|
384
389
|
parsed.config,
|
|
@@ -427,7 +432,7 @@ def _handle_no_args() -> int:
|
|
|
427
432
|
return 0
|
|
428
433
|
|
|
429
434
|
|
|
430
|
-
def _command_init(config_override: str | None, force: bool) -> int:
|
|
435
|
+
def _command_init(config_override: str | None, force: bool, ci: bool = False) -> int:
|
|
431
436
|
cfg_path = _resolve_config_path(config_override)
|
|
432
437
|
if cfg_path.exists() and not force:
|
|
433
438
|
print(f"Config already exists at {cfg_path}. Use --force to overwrite.")
|
|
@@ -441,6 +446,27 @@ def _command_init(config_override: str | None, force: bool) -> int:
|
|
|
441
446
|
cfg_path.write_text(load_config_text(base_dir))
|
|
442
447
|
print_dashboard()
|
|
443
448
|
console.print(f"\n[success]Initialized config at[/success] [cyan]{cfg_path}[/cyan]\n")
|
|
449
|
+
|
|
450
|
+
# Auto-generate GitHub Actions workflow if --ci flag is set
|
|
451
|
+
if ci:
|
|
452
|
+
workflow_created = _generate_github_workflow()
|
|
453
|
+
if workflow_created:
|
|
454
|
+
console.print(
|
|
455
|
+
"[success]✓[/success] Created GitHub Actions workflow: "
|
|
456
|
+
"[cyan].github/workflows/kekkai-security.yml[/cyan]"
|
|
457
|
+
)
|
|
458
|
+
console.print(
|
|
459
|
+
"\n[info]Next steps:[/info]\n"
|
|
460
|
+
" 1. Commit the workflow file:\n"
|
|
461
|
+
" [dim]git add .github/workflows/kekkai-security.yml[/dim]\n"
|
|
462
|
+
" 2. Push to GitHub\n"
|
|
463
|
+
" 3. Security scans will run automatically on pull requests\n"
|
|
464
|
+
)
|
|
465
|
+
else:
|
|
466
|
+
console.print(
|
|
467
|
+
"[warning]⚠[/warning] Not a Git repository or .github/workflows/ cannot be created"
|
|
468
|
+
)
|
|
469
|
+
|
|
444
470
|
return 0
|
|
445
471
|
|
|
446
472
|
|
|
@@ -1752,6 +1778,91 @@ def _resolve_dojo_open_port(parsed: argparse.Namespace, compose_root: Path) -> i
|
|
|
1752
1778
|
return dojo.DEFAULT_PORT
|
|
1753
1779
|
|
|
1754
1780
|
|
|
1781
|
+
def _generate_github_workflow() -> bool:
|
|
1782
|
+
"""Generate GitHub Actions workflow file for security scanning.
|
|
1783
|
+
|
|
1784
|
+
Returns:
|
|
1785
|
+
True if workflow was created successfully, False otherwise.
|
|
1786
|
+
"""
|
|
1787
|
+
# Check if we're in a git repository
|
|
1788
|
+
cwd = Path.cwd()
|
|
1789
|
+
git_dir = cwd / ".git"
|
|
1790
|
+
if not git_dir.exists():
|
|
1791
|
+
return False
|
|
1792
|
+
|
|
1793
|
+
# Create .github/workflows directory
|
|
1794
|
+
workflows_dir = cwd / ".github" / "workflows"
|
|
1795
|
+
try:
|
|
1796
|
+
workflows_dir.mkdir(parents=True, exist_ok=True)
|
|
1797
|
+
except (OSError, PermissionError):
|
|
1798
|
+
return False
|
|
1799
|
+
|
|
1800
|
+
# Generate workflow file
|
|
1801
|
+
workflow_path = workflows_dir / "kekkai-security.yml"
|
|
1802
|
+
if workflow_path.exists():
|
|
1803
|
+
# Don't overwrite existing workflow
|
|
1804
|
+
return False
|
|
1805
|
+
|
|
1806
|
+
workflow_content = """name: Kekkai Security Scan
|
|
1807
|
+
|
|
1808
|
+
on:
|
|
1809
|
+
pull_request:
|
|
1810
|
+
types: [opened, synchronize, reopened]
|
|
1811
|
+
push:
|
|
1812
|
+
branches:
|
|
1813
|
+
- main
|
|
1814
|
+
- develop
|
|
1815
|
+
|
|
1816
|
+
permissions:
|
|
1817
|
+
contents: read
|
|
1818
|
+
pull-requests: write
|
|
1819
|
+
|
|
1820
|
+
jobs:
|
|
1821
|
+
security-scan:
|
|
1822
|
+
runs-on: ubuntu-latest
|
|
1823
|
+
steps:
|
|
1824
|
+
- name: Checkout code
|
|
1825
|
+
uses: actions/checkout@v4
|
|
1826
|
+
|
|
1827
|
+
- name: Set up Python
|
|
1828
|
+
uses: actions/setup-python@v5
|
|
1829
|
+
with:
|
|
1830
|
+
python-version: '3.12'
|
|
1831
|
+
|
|
1832
|
+
- name: Install Kekkai
|
|
1833
|
+
run: |
|
|
1834
|
+
python -m pip install --upgrade pip
|
|
1835
|
+
pip install kekkai-cli
|
|
1836
|
+
|
|
1837
|
+
- name: Run Security Scan
|
|
1838
|
+
run: |
|
|
1839
|
+
kekkai scan --ci --fail-on high
|
|
1840
|
+
continue-on-error: true
|
|
1841
|
+
|
|
1842
|
+
- name: Post PR Comments (if PR)
|
|
1843
|
+
if: github.event_name == 'pull_request'
|
|
1844
|
+
run: |
|
|
1845
|
+
kekkai scan --pr-comment --max-comments 50
|
|
1846
|
+
env:
|
|
1847
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
1848
|
+
continue-on-error: true
|
|
1849
|
+
|
|
1850
|
+
- name: Upload Results
|
|
1851
|
+
uses: actions/upload-artifact@v4
|
|
1852
|
+
if: always()
|
|
1853
|
+
with:
|
|
1854
|
+
name: kekkai-scan-results
|
|
1855
|
+
path: ~/.kekkai/runs/*/
|
|
1856
|
+
retention-days: 30
|
|
1857
|
+
"""
|
|
1858
|
+
|
|
1859
|
+
try:
|
|
1860
|
+
workflow_path.write_text(workflow_content, encoding="utf-8")
|
|
1861
|
+
return True
|
|
1862
|
+
except (OSError, PermissionError):
|
|
1863
|
+
return False
|
|
1864
|
+
|
|
1865
|
+
|
|
1755
1866
|
def _resolve_config_path(config_override: str | None) -> Path:
|
|
1756
1867
|
if config_override:
|
|
1757
1868
|
return Path(config_override).expanduser().resolve()
|
kekkai/output.py
CHANGED
|
@@ -57,7 +57,7 @@ BANNER_ASCII = r"""
|
|
|
57
57
|
/_/\_\\___/_/\_/_/\_\\_,_/_/
|
|
58
58
|
"""
|
|
59
59
|
|
|
60
|
-
VERSION = "
|
|
60
|
+
VERSION = "2.0.0"
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def print_dashboard() -> None:
|
|
@@ -88,9 +88,8 @@ def print_dashboard() -> None:
|
|
|
88
88
|
menu_table.add_column("Description", style="desc", ratio=3)
|
|
89
89
|
|
|
90
90
|
menu_table.add_row("kekkai scan", "Run security scan in current directory")
|
|
91
|
-
menu_table.add_row("kekkai threatflow", "Generate AI-powered threat model")
|
|
92
|
-
menu_table.add_row("kekkai dojo", "Manage local DefectDojo instance")
|
|
93
91
|
menu_table.add_row("kekkai triage", "Interactive finding review (TUI)")
|
|
92
|
+
menu_table.add_row("kekkai threatflow", "Generate AI-powered threat model")
|
|
94
93
|
menu_table.add_row("kekkai report", "Generate compliance reports")
|
|
95
94
|
menu_table.add_row("kekkai config", "Manage settings and keys")
|
|
96
95
|
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""Fix generation screen for AI-powered code fixes.
|
|
2
|
+
|
|
3
|
+
Provides a modal screen that shows fix generation progress
|
|
4
|
+
and preview of AI-generated patches.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
from rich.text import Text
|
|
14
|
+
from textual.app import ComposeResult
|
|
15
|
+
from textual.binding import Binding
|
|
16
|
+
from textual.containers import Vertical, VerticalScroll
|
|
17
|
+
from textual.screen import ModalScreen
|
|
18
|
+
from textual.widgets import Footer, Label, Static
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from .models import FindingEntry
|
|
22
|
+
|
|
23
|
+
__all__ = ["FixGenerationScreen"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class FixGenerationScreen(ModalScreen[bool]):
|
|
27
|
+
"""Modal screen for generating AI-powered fixes.
|
|
28
|
+
|
|
29
|
+
Shows progress, model configuration, and fix preview.
|
|
30
|
+
|
|
31
|
+
Bindings:
|
|
32
|
+
escape: Cancel and go back
|
|
33
|
+
enter: Accept fix (if generated)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
BINDINGS = [
|
|
37
|
+
Binding("escape", "cancel", "Cancel"),
|
|
38
|
+
Binding("enter", "accept", "Accept Fix", show=False),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
DEFAULT_CSS = """
|
|
42
|
+
FixGenerationScreen {
|
|
43
|
+
align: center middle;
|
|
44
|
+
}
|
|
45
|
+
#fix-dialog {
|
|
46
|
+
width: 80;
|
|
47
|
+
height: 30;
|
|
48
|
+
border: thick $primary;
|
|
49
|
+
background: $surface;
|
|
50
|
+
padding: 1;
|
|
51
|
+
}
|
|
52
|
+
#fix-title {
|
|
53
|
+
dock: top;
|
|
54
|
+
height: 3;
|
|
55
|
+
content-align: center middle;
|
|
56
|
+
background: $primary;
|
|
57
|
+
color: $text;
|
|
58
|
+
}
|
|
59
|
+
#fix-content {
|
|
60
|
+
height: 1fr;
|
|
61
|
+
padding: 1;
|
|
62
|
+
}
|
|
63
|
+
#fix-preview {
|
|
64
|
+
height: 1fr;
|
|
65
|
+
border: solid $accent;
|
|
66
|
+
padding: 1;
|
|
67
|
+
background: $panel;
|
|
68
|
+
}
|
|
69
|
+
#fix-status {
|
|
70
|
+
dock: bottom;
|
|
71
|
+
height: 3;
|
|
72
|
+
padding: 1;
|
|
73
|
+
background: $surface;
|
|
74
|
+
}
|
|
75
|
+
.fix-button {
|
|
76
|
+
margin: 1;
|
|
77
|
+
}
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
finding: FindingEntry,
|
|
83
|
+
on_fix_generated: Callable[[bool, str], None] | None = None,
|
|
84
|
+
name: str | None = None,
|
|
85
|
+
id: str | None = None,
|
|
86
|
+
) -> None:
|
|
87
|
+
super().__init__(name=name, id=id)
|
|
88
|
+
self.finding = finding
|
|
89
|
+
self.on_fix_generated = on_fix_generated
|
|
90
|
+
self.fix_preview: str | None = None
|
|
91
|
+
self.fix_generated = False
|
|
92
|
+
|
|
93
|
+
def compose(self) -> ComposeResult:
|
|
94
|
+
with Vertical(id="fix-dialog"):
|
|
95
|
+
yield Label("🤖 AI-Powered Fix Generation", id="fix-title")
|
|
96
|
+
with VerticalScroll(id="fix-content"):
|
|
97
|
+
yield Label(self._get_finding_summary())
|
|
98
|
+
yield Label(self._get_model_info())
|
|
99
|
+
yield Static("", id="fix-preview")
|
|
100
|
+
yield Static(self._get_initial_status(), id="fix-status")
|
|
101
|
+
yield Footer()
|
|
102
|
+
|
|
103
|
+
def _get_finding_summary(self) -> Text:
|
|
104
|
+
"""Generate summary of finding to fix."""
|
|
105
|
+
text = Text()
|
|
106
|
+
text.append("Finding:\n", style="bold")
|
|
107
|
+
text.append(f" {self.finding.scanner}: ", style="cyan")
|
|
108
|
+
text.append(f"{self.finding.title}\n")
|
|
109
|
+
if self.finding.file_path:
|
|
110
|
+
text.append(f" File: {self.finding.file_path}", style="dim")
|
|
111
|
+
if self.finding.line:
|
|
112
|
+
text.append(f":{self.finding.line}", style="dim")
|
|
113
|
+
text.append("\n")
|
|
114
|
+
return text
|
|
115
|
+
|
|
116
|
+
def _get_model_info(self) -> Text:
|
|
117
|
+
"""Display model configuration info."""
|
|
118
|
+
text = Text()
|
|
119
|
+
text.append("\nModel Configuration:\n", style="bold")
|
|
120
|
+
|
|
121
|
+
# Check for Ollama
|
|
122
|
+
if self._is_ollama_available():
|
|
123
|
+
text.append(" ✓ Ollama detected (local-first AI)\n", style="green")
|
|
124
|
+
text.append(" No API keys needed - runs on your machine\n", style="dim")
|
|
125
|
+
# Check for API keys
|
|
126
|
+
elif os.environ.get("KEKKAI_FIX_API_KEY"):
|
|
127
|
+
text.append(" ⚠ Using remote API (OpenAI/Anthropic)\n", style="yellow")
|
|
128
|
+
text.append(" Code will be sent to external service\n", style="dim")
|
|
129
|
+
else:
|
|
130
|
+
text.append(" ✗ No AI backend configured\n", style="red")
|
|
131
|
+
text.append(" Install Ollama or set KEKKAI_FIX_API_KEY\n", style="dim")
|
|
132
|
+
|
|
133
|
+
return text
|
|
134
|
+
|
|
135
|
+
def _get_initial_status(self) -> Text:
|
|
136
|
+
"""Initial status message."""
|
|
137
|
+
if self._is_ollama_available() or os.environ.get("KEKKAI_FIX_API_KEY"):
|
|
138
|
+
return Text("Press Enter to generate fix, or Escape to cancel", style="italic")
|
|
139
|
+
else:
|
|
140
|
+
return Text(
|
|
141
|
+
"❌ Cannot generate fix: No AI backend configured\n"
|
|
142
|
+
"Install Ollama (recommended) or set KEKKAI_FIX_API_KEY",
|
|
143
|
+
style="red",
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
def _is_ollama_available(self) -> bool:
|
|
147
|
+
"""Check if Ollama is available on the system."""
|
|
148
|
+
import shutil
|
|
149
|
+
|
|
150
|
+
return shutil.which("ollama") is not None
|
|
151
|
+
|
|
152
|
+
def on_mount(self) -> None:
|
|
153
|
+
"""Auto-generate fix if backend is available."""
|
|
154
|
+
if self._is_ollama_available() or os.environ.get("KEKKAI_FIX_API_KEY"):
|
|
155
|
+
# Auto-start fix generation
|
|
156
|
+
self.set_timer(0.5, self._generate_fix)
|
|
157
|
+
|
|
158
|
+
def _generate_fix(self) -> None:
|
|
159
|
+
"""Generate AI-powered fix."""
|
|
160
|
+
status = self.query_one("#fix-status", Static)
|
|
161
|
+
status.update(Text("⏳ Generating fix with AI...", style="yellow italic"))
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
# Import fix engine
|
|
165
|
+
from ..fix import FixConfig
|
|
166
|
+
|
|
167
|
+
# Determine model mode
|
|
168
|
+
if self._is_ollama_available():
|
|
169
|
+
model_mode = "ollama"
|
|
170
|
+
model_name = os.environ.get("KEKKAI_FIX_MODEL_NAME", "mistral")
|
|
171
|
+
else:
|
|
172
|
+
model_mode = "openai"
|
|
173
|
+
model_name = None
|
|
174
|
+
|
|
175
|
+
# Create fix config (for future integration)
|
|
176
|
+
_config = FixConfig(
|
|
177
|
+
model_mode=model_mode,
|
|
178
|
+
model_name=model_name,
|
|
179
|
+
api_key=os.environ.get("KEKKAI_FIX_API_KEY"),
|
|
180
|
+
max_fixes=1,
|
|
181
|
+
timeout_seconds=60,
|
|
182
|
+
dry_run=True,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# Note: This is a simplified mock - actual implementation would:
|
|
186
|
+
# 1. Convert FindingEntry to proper format for FixEngine
|
|
187
|
+
# 2. Call fix engine with proper error handling
|
|
188
|
+
# 3. Display actual fix preview
|
|
189
|
+
|
|
190
|
+
# For now, show a placeholder
|
|
191
|
+
self.fix_preview = (
|
|
192
|
+
"# AI-Powered Fix (Preview)\n"
|
|
193
|
+
f"# Finding: {self.finding.title}\n"
|
|
194
|
+
f"# Scanner: {self.finding.scanner}\n\n"
|
|
195
|
+
"# Fix would be generated here using:\n"
|
|
196
|
+
f"# - Model: {model_name or 'gpt-4'}\n"
|
|
197
|
+
f"# - Mode: {model_mode}\n"
|
|
198
|
+
"# - Context from source file\n\n"
|
|
199
|
+
"# Press Enter to apply (dry-run mode)\n"
|
|
200
|
+
"# Press Escape to cancel"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
preview = self.query_one("#fix-preview", Static)
|
|
204
|
+
preview.update(Text(self.fix_preview, style="green"))
|
|
205
|
+
|
|
206
|
+
status.update(
|
|
207
|
+
Text("✓ Fix generated! Press Enter to apply or Escape to cancel", style="green")
|
|
208
|
+
)
|
|
209
|
+
self.fix_generated = True
|
|
210
|
+
|
|
211
|
+
except Exception as e:
|
|
212
|
+
status.update(Text(f"✗ Fix generation failed: {e}", style="red"))
|
|
213
|
+
self.fix_generated = False
|
|
214
|
+
|
|
215
|
+
def action_accept(self) -> None:
|
|
216
|
+
"""Accept and apply the generated fix."""
|
|
217
|
+
if not self.fix_generated:
|
|
218
|
+
return
|
|
219
|
+
|
|
220
|
+
if self.on_fix_generated:
|
|
221
|
+
self.on_fix_generated(
|
|
222
|
+
True, "Fix generated successfully (dry-run mode - review before applying)"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
self.dismiss(True)
|
|
226
|
+
|
|
227
|
+
def action_cancel(self) -> None:
|
|
228
|
+
"""Cancel fix generation."""
|
|
229
|
+
if self.on_fix_generated:
|
|
230
|
+
self.on_fix_generated(False, "Fix generation cancelled")
|
|
231
|
+
|
|
232
|
+
self.dismiss(False)
|
kekkai/triage/screens.py
CHANGED
|
@@ -49,6 +49,7 @@ class FindingListScreen(Screen[None]):
|
|
|
49
49
|
Binding("down", "cursor_down", "Next", show=False),
|
|
50
50
|
Binding("up", "cursor_up", "Previous", show=False),
|
|
51
51
|
Binding("enter", "view_detail", "View"),
|
|
52
|
+
Binding("x", "fix_with_ai", "🤖 Fix with AI"),
|
|
52
53
|
Binding("f", "mark_false_positive", "False Positive"),
|
|
53
54
|
Binding("c", "mark_confirmed", "Confirmed"),
|
|
54
55
|
Binding("d", "mark_deferred", "Deferred"),
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kekkai-cli
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Terminal UI for Trivy/Semgrep/Gitleaks. Local-first security triage.
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: rich>=13.0.0
|
|
8
|
+
Requires-Dist: jsonschema>=4.20.0
|
|
9
|
+
Requires-Dist: textual>=0.50.0
|
|
10
|
+
Requires-Dist: httpx>=0.24.0
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/logos/kekkai-slim.png" alt="Kekkai CLI Logo" width="250"/>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center"><strong>Stop parsing JSON. Security triage in your terminal.</strong></p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<img src="https://img.shields.io/github/actions/workflow/status/kademoslabs/kekkai/docker-publish.yml?logo=github"/>
|
|
20
|
+
<img src="https://img.shields.io/circleci/build/github/kademoslabs/kekkai?logo=circleci"/>
|
|
21
|
+
<img src="https://img.shields.io/pypi/v/kekkai-cli?pypiBaseUrl=https%3A%2F%2Fpypi.org&logo=pypi"/>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Kekkai
|
|
27
|
+
|
|
28
|
+
**Interactive security triage in the terminal.**
|
|
29
|
+
|
|
30
|
+
Kekkai is a small open-source CLI that wraps existing security scanners (Trivy, Semgrep, Gitleaks) and focuses on the part that tends to be slow and frustrating: reviewing and triaging results.
|
|
31
|
+
|
|
32
|
+
Running scanners is easy. Interpreting noisy output, dealing with false positives, and making CI usable is not. Kekkai exists to make that part tolerable..
|
|
33
|
+
|
|
34
|
+

|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What it does
|
|
39
|
+
|
|
40
|
+
- Runs Trivy (dependencies), Semgrep (code), and Gitleaks (secrets)
|
|
41
|
+
- Normalizes their outputs into a single report format
|
|
42
|
+
- Provides an interactive terminal UI for reviewing findings
|
|
43
|
+
- Lets you mark findings as false positives and persist decisions locally
|
|
44
|
+
- Supports CI mode with severity-based failure thresholds
|
|
45
|
+
|
|
46
|
+
Kekkai does not replace scanners or introduce proprietary detection logic. It sits on top of existing tools and focuses on workflow and UX.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
> Requires Docker and Python 3.12
|
|
53
|
+
|
|
54
|
+
### 1. Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pipx install kekkai-cli
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Scan
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
kekkai scan
|
|
64
|
+
# Runs Trivy (CVEs), Semgrep (code), Gitleaks (secrets)
|
|
65
|
+
# Outputs unified kekkai-report.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Triage
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
kekkai triage
|
|
72
|
+
# Interactive TUI to review findings with keyboard navigation
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
No signup, no cloud service required.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Why Kekkai?
|
|
80
|
+
|
|
81
|
+
| Problem | Kekkai Solution |
|
|
82
|
+
|---------|-----------------|
|
|
83
|
+
| **Juggling 3+ tools** | One CLI for Trivy, Semgrep, Gitleaks |
|
|
84
|
+
| **Reading JSON logs** | Interactive terminal UI |
|
|
85
|
+
| **Installing scanners** | Auto-pulls Docker containers |
|
|
86
|
+
| **Parsing different formats** | Unified `kekkai-report.json` |
|
|
87
|
+
| **False positives** | Mark and ignore with `.kekkaiignore` |
|
|
88
|
+
| **CI/CD integration** | `kekkai scan --ci --fail-on high` |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Features
|
|
93
|
+
|
|
94
|
+
### Interactive Triage TUI
|
|
95
|
+
|
|
96
|
+
Stop reading JSON. Use keyboard navigation to review findings, mark false positives, and generate ignore files.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
kekkai triage
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Controls:**
|
|
103
|
+
- `j/k` or `↑/↓`: Navigate findings
|
|
104
|
+
- `f`: Mark as false positive
|
|
105
|
+
- `c`: Confirm finding
|
|
106
|
+
- `d`: Defer/ignore
|
|
107
|
+
- `Ctrl+S`: Save decisions
|
|
108
|
+
- `q`: Quit
|
|
109
|
+
|
|
110
|
+
<!-- Screenshot placeholder:  -->
|
|
111
|
+
|
|
112
|
+
[Full Triage Documentation →](docs/triage/README.md)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### CI/CD Policy Gate
|
|
117
|
+
|
|
118
|
+
Break builds on severity thresholds.
|
|
119
|
+
|
|
120
|
+
Kekkai can be used as a CI gate based on severity thresholds.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Fail on any critical or high findings
|
|
124
|
+
kekkai scan --ci --fail-on high
|
|
125
|
+
|
|
126
|
+
# Fail only on critical
|
|
127
|
+
kekkai scan --ci --fail-on critical
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Exit Codes:**
|
|
131
|
+
| Code | Meaning |
|
|
132
|
+
|------|---------|
|
|
133
|
+
| 0 | No findings above threshold |
|
|
134
|
+
| 1 | Findings exceed threshold |
|
|
135
|
+
| 2 | Scanner error |
|
|
136
|
+
|
|
137
|
+
**GitHub Actions Example:**
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
- name: Security Scan
|
|
141
|
+
run: |
|
|
142
|
+
pipx install kekkai-cli
|
|
143
|
+
kekkai scan --ci --fail-on high
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
[Full CI Documentation →](docs/ci/ci-mode.md)
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### GitHub PR Comments
|
|
151
|
+
|
|
152
|
+
Get security feedback directly in pull requests.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
export GITHUB_TOKEN="ghp_..."
|
|
156
|
+
kekkai scan --pr-comment
|
|
157
|
+
```
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Unified Scanning
|
|
161
|
+
|
|
162
|
+
Run industry-standard scanners without installing them individually. Each scanner runs in an isolated Docker container.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
kekkai scan # Scan current directory
|
|
166
|
+
kekkai scan --repo /path/to/project # Scan specific path
|
|
167
|
+
kekkai scan --output results.json # Custom output path
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Scanners Included:**
|
|
171
|
+
| Scanner | Finds | Image |
|
|
172
|
+
|---------|-------|-------|
|
|
173
|
+
| Trivy | CVEs in dependencies | `aquasec/trivy:latest` |
|
|
174
|
+
| Semgrep | Code vulnerabilities | `semgrep/semgrep:latest` |
|
|
175
|
+
| Gitleaks | Hardcoded secrets | `zricethezav/gitleaks:latest` |
|
|
176
|
+
|
|
177
|
+
**Container Security:**
|
|
178
|
+
- Read-only filesystem
|
|
179
|
+
- No network access
|
|
180
|
+
- Memory limited (2GB)
|
|
181
|
+
- No privilege escalation
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
#### Design choices
|
|
186
|
+
|
|
187
|
+
- Local-first: no SaaS required, runs entirely on your machine or CI
|
|
188
|
+
- No network access for scanner containers
|
|
189
|
+
- Read-only filesystems, memory-limited containers
|
|
190
|
+
- Uses existing tools instead of reimplementing scanners
|
|
191
|
+
- Terminal-first UX instead of dashboards
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Optional features
|
|
196
|
+
|
|
197
|
+
These are opt-in and not required for basic use:
|
|
198
|
+
|
|
199
|
+
### Local-First AI Threat Modeling
|
|
200
|
+
|
|
201
|
+
Generate STRIDE threat models with AI that runs on **your machine**. No API keys. No cloud.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Ollama (recommended - easy setup, privacy-preserving)
|
|
205
|
+
ollama pull mistral
|
|
206
|
+
kekkai threatflow --repo . --model-mode ollama --model-name mistral
|
|
207
|
+
|
|
208
|
+
# Output: THREATS.md with attack surface analysis and Mermaid.js diagrams
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Supports:**
|
|
212
|
+
- Ollama (recommended)
|
|
213
|
+
- Local GGUF models (llama.cpp)
|
|
214
|
+
- OpenAI/Anthropic (if you trust them with your code)
|
|
215
|
+
|
|
216
|
+
[Full Local-First AI Threat Modeling Documentation →](docs/threatflow/README.md)
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### DefectDojo Integration
|
|
221
|
+
|
|
222
|
+
Spin up a vulnerability management dashboard locally if you need it.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
kekkai dojo up --wait # Start DefectDojo
|
|
226
|
+
kekkai upload # Import scan results
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**What You Get:**
|
|
230
|
+
- DefectDojo web UI at `http://localhost:8080`
|
|
231
|
+
- Automatic credential generation
|
|
232
|
+
- Pre-configured for Kekkai imports
|
|
233
|
+
|
|
234
|
+
[DefectDojo Quick Start →](docs/dojo/dojo-quickstart.md)
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
### AI-Powered Fix Engine
|
|
239
|
+
|
|
240
|
+
Generate code patches for findings (experimental).
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
kekkai fix --input scan-results.json --apply
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### Compliance Reporting
|
|
249
|
+
|
|
250
|
+
Map findings to PCI-DSS, OWASP, HIPAA, SOC 2.
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
kekkai report --input scan-results.json --format pdf --frameworks PCI-DSS,OWASP
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## What this is not
|
|
259
|
+
|
|
260
|
+
- Not a replacement for commercial AppSec platforms
|
|
261
|
+
- Not a new scanner or detection engine
|
|
262
|
+
- Not optimized for large enterprises (yet)
|
|
263
|
+
- Not a hosted service
|
|
264
|
+
|
|
265
|
+
Right now, Kekkai is aimed at individual developers and small teams who already run scanners but want better triage and less noise.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Security
|
|
270
|
+
|
|
271
|
+
Kekkai is designed with security as a core principle:
|
|
272
|
+
|
|
273
|
+
- **Container Isolation**: Scanners run in hardened Docker containers
|
|
274
|
+
- **No Network Access**: Containers cannot reach external networks
|
|
275
|
+
- **Local-First AI**: run entirely on your machine
|
|
276
|
+
- **SLSA Level 3**: Release artifacts include provenance attestations
|
|
277
|
+
- **Signed Images**: Docker images are Cosign-signed
|
|
278
|
+
|
|
279
|
+
For vulnerability reports, see [SECURITY.md](SECURITY.md).
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Documentation
|
|
284
|
+
|
|
285
|
+
| Guide | Description |
|
|
286
|
+
|-------|-------------|
|
|
287
|
+
| [Installation](docs/README.md#installation-methods) | All installation methods |
|
|
288
|
+
| [ThreatFlow](docs/threatflow/README.md) | AI threat modeling setup |
|
|
289
|
+
| [Triage TUI](docs/triage/README.md) | Interactive finding review |
|
|
290
|
+
| [CI Mode](docs/ci/ci-mode.md) | Pipeline integration |
|
|
291
|
+
| [DefectDojo](docs/dojo/dojo-quickstart.md) | Optional vulnerability management |
|
|
292
|
+
| [Security](docs/security/slsa-provenance.md) | SLSA provenance verification |
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Roadmap (short-term)
|
|
297
|
+
|
|
298
|
+
1. Persistent triage state across runs (baselines)
|
|
299
|
+
2. “New findings only” diffs
|
|
300
|
+
3. Better PR-level workflows
|
|
301
|
+
4. Cleaner reporting for small teams
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Contributing
|
|
306
|
+
|
|
307
|
+
We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## License
|
|
312
|
+
|
|
313
|
+
Apache-2.0 — See [LICENSE](LICENSE) for details.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
<p align="center"><i>Built by <a href="https://kademos.org">Kademos Labs</a></i></p>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
kekkai/__init__.py,sha256=_VrBvJRyqHiXs31S8HOhATk_O2iy-ac0_9X7rHH75j8,143
|
|
2
|
-
kekkai/cli.py,sha256
|
|
2
|
+
kekkai/cli.py,sha256=Y99dHzSRLV4sqbFiSe81nJRtvx2dQWmRDPyOVdghIIQ,66616
|
|
3
3
|
kekkai/config.py,sha256=LE7bKsmv5dim5KnZya0V7_LtviNQ1V0pMN_6FyAsMpc,13084
|
|
4
4
|
kekkai/dojo.py,sha256=erLdTMOioTyzVhXYW8xgdbU5Ro-KQx1OcTQN7_zemmY,18634
|
|
5
5
|
kekkai/dojo_import.py,sha256=D0ZQM_0JYHqUqJA3l4nKD-RkpvcOcgj-4zv59HRcQ6k,7274
|
|
6
6
|
kekkai/manifest.py,sha256=Ph5xGDKuVxMW1GVIisRhxUelaiVZQe-W5sZWsq4lHqs,1887
|
|
7
|
-
kekkai/output.py,sha256=
|
|
7
|
+
kekkai/output.py,sha256=QdIFsXCRb9aT5PaKmj0j0y2fg3IRjcLXQMzuGlASNFY,5426
|
|
8
8
|
kekkai/paths.py,sha256=EcyG3CEOQFQygowu7O5Mp85dKkXWWvnm1h0j_BetGxY,1190
|
|
9
9
|
kekkai/policy.py,sha256=0XCUH-SbnO1PsM-exjSFHYHRnLkiNa50QfkyPakwNko,9792
|
|
10
10
|
kekkai/runner.py,sha256=MBFUiJ4sSVEGNbJ6cv-8p1WHaHqjio6yWEfr_K4GuTs,2037
|
|
@@ -61,10 +61,11 @@ kekkai/threatflow/sanitizer.py,sha256=uQsxYZ5VDXutZoj-WMl7fo5T07uHuQZqgVzoVMoaKe
|
|
|
61
61
|
kekkai/triage/__init__.py,sha256=gYf4XPIYZTthU0Q0kaptbgMKulkjLxWQWG0HQvtlu-o,2182
|
|
62
62
|
kekkai/triage/app.py,sha256=MU2tBI50d8sOdDKESGNrWYiREG9bBtrSccaMoiMv5gM,5027
|
|
63
63
|
kekkai/triage/audit.py,sha256=UVaSKKC6tZkHxEoMcnIZkMOT_ngj7QzHWYuDAHas_sc,5842
|
|
64
|
+
kekkai/triage/fix_screen.py,sha256=mj_waXwKPCrT01bVSSu5Ohi-3JvN2lT18Yy44xICItY,7667
|
|
64
65
|
kekkai/triage/ignore.py,sha256=uBKM7zKyzORj9LJ5AAnoYWZQTRy57P0ZofSapiDWcfI,7305
|
|
65
66
|
kekkai/triage/loader.py,sha256=vywhS8fcre7PiBX3H2CpKXFxzvO7LcDnIHIB0kzG3R4,5850
|
|
66
67
|
kekkai/triage/models.py,sha256=nRmWtELMqHWHX1NqZ2upH2ZAJVeBxa3Wh8f3kkB9WYo,5384
|
|
67
|
-
kekkai/triage/screens.py,sha256=
|
|
68
|
+
kekkai/triage/screens.py,sha256=MbudQkdQ4JFt5c80V3LtqCeXxAIu7nIfZpm7G5wRXT0,11061
|
|
68
69
|
kekkai/triage/widgets.py,sha256=eOF6Qoo5uBqjxiEkbpgcO1tbIOGBQBKn75wP9Jw_AaE,4733
|
|
69
70
|
kekkai_core/__init__.py,sha256=gREN4oarM0azTkSTWTnlDnPZGgv1msai2Deq9Frj3gc,122
|
|
70
71
|
kekkai_core/redaction.py,sha256=EeWYPjAs2hIXlLKGmGn_PRdK08G4KcOBmbRCoFklbHc,2893
|
|
@@ -84,8 +85,8 @@ kekkai_core/windows/chocolatey.py,sha256=tF5S5eN-HeENRt6yQ4TZgwng0oRMX_ScskQ3-eb
|
|
|
84
85
|
kekkai_core/windows/installer.py,sha256=MePAywHH3JTIAENv52XtkUMOGqmYqZqkH77VW5PST8o,6945
|
|
85
86
|
kekkai_core/windows/scoop.py,sha256=lvothICrAoB3lGfkvhqVeNTB50eMmVGA0BE7JNCfHdI,5284
|
|
86
87
|
kekkai_core/windows/validators.py,sha256=45xUuAbHcKc0WLIZ-0rByPeDD88MAV8KvopngyYBHpQ,6525
|
|
87
|
-
kekkai_cli-
|
|
88
|
-
kekkai_cli-
|
|
89
|
-
kekkai_cli-
|
|
90
|
-
kekkai_cli-
|
|
91
|
-
kekkai_cli-
|
|
88
|
+
kekkai_cli-2.0.0.dist-info/METADATA,sha256=FiwQoECQj5ks2uQEiZ3oMkOSlkf7QE0d9ke-UNRnbPw,8125
|
|
89
|
+
kekkai_cli-2.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
90
|
+
kekkai_cli-2.0.0.dist-info/entry_points.txt,sha256=MBV1OIfxJmT2oJvzeeFKIH1eh8M9kKAn7JqFBeuMfWA,43
|
|
91
|
+
kekkai_cli-2.0.0.dist-info/top_level.txt,sha256=wWwh7GGPaUjcaCRmt70ueL3WQoQbeGa5L0T0hgOh-MY,19
|
|
92
|
+
kekkai_cli-2.0.0.dist-info/RECORD,,
|
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: kekkai-cli
|
|
3
|
-
Version: 1.1.1
|
|
4
|
-
Summary: Kekkai monorepo (local-first AppSec orchestration + compliance checker)
|
|
5
|
-
Requires-Python: >=3.12
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: rich>=13.0.0
|
|
8
|
-
Requires-Dist: jsonschema>=4.20.0
|
|
9
|
-
Requires-Dist: textual>=0.50.0
|
|
10
|
-
Requires-Dist: httpx>=0.24.0
|
|
11
|
-
|
|
12
|
-
<p align="center">
|
|
13
|
-
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/logos/kekkai-slim.png" alt="Kekkai CLI Logo" width="250"/>
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<p align="center"><strong>Security orchestration at developer speed.</strong></p>
|
|
17
|
-
<p align="center"><i>One tool for the entire AppSec lifecycle: Predict, Detect, Triage, Manage.</i></p>
|
|
18
|
-
|
|
19
|
-
<p align="center">
|
|
20
|
-
<img src="https://img.shields.io/github/actions/workflow/status/kademoslabs/kekkai/docker-publish.yml?logo=github"/>
|
|
21
|
-
<img src="https://img.shields.io/circleci/build/github/kademoslabs/kekkai?logo=circleci"/>
|
|
22
|
-
<img src="https://img.shields.io/pypi/v/kekkai-cli?pypiBaseUrl=https%3A%2F%2Fpypi.org&logo=pypi"/>
|
|
23
|
-
</p>
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
# Kekkai
|
|
28
|
-
|
|
29
|
-
Stop juggling security tools. **Kekkai orchestrates your entire AppSec lifecycle** — from AI-powered threat modeling to vulnerability management — in a single CLI.
|
|
30
|
-
|
|
31
|
-

|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## The Five Pillars
|
|
36
|
-
|
|
37
|
-
| Pillar | Feature | Command | Description |
|
|
38
|
-
|--------|---------|---------|-------------|
|
|
39
|
-
| 🔮 **Predict** | AI Threat Modeling | `kekkai threatflow` | Generate STRIDE threat models before writing code |
|
|
40
|
-
| 🔍 **Detect** | Unified Scanning | `kekkai scan` | Run Trivy, Semgrep, Gitleaks in isolated containers |
|
|
41
|
-
| ✅ **Triage** | Interactive Review | `kekkai triage` | Review findings in a terminal UI, mark false positives |
|
|
42
|
-
| 🚦 **Gate** | CI/CD Policy | `kekkai scan --ci` | Break builds on severity thresholds |
|
|
43
|
-
| 📊 **Manage** | DefectDojo | `kekkai dojo up` | Spin up vulnerability management in 60 seconds |
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Quick Start (60 Seconds)
|
|
48
|
-
|
|
49
|
-
### 1. Install
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
pipx install kekkai-cli
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### 2. Predict (Threat Model)
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
kekkai threatflow --repo . --model-mode local
|
|
59
|
-
# Generates THREATS.md with STRIDE analysis and Data Flow Diagram
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### 3. Detect (Scan)
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
kekkai scan
|
|
66
|
-
# Runs Trivy (CVEs), Semgrep (code), Gitleaks (secrets)
|
|
67
|
-
# Outputs unified kekkai-report.json
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 4. Triage (Review)
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
kekkai triage
|
|
74
|
-
# Interactive TUI to accept, reject, or ignore findings
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### 5. Manage (DefectDojo)
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
kekkai dojo up --wait
|
|
81
|
-
kekkai upload
|
|
82
|
-
# Full vulnerability management platform + automated import
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Why Kekkai?
|
|
88
|
-
|
|
89
|
-
| Capability | Manual Approach | Kekkai |
|
|
90
|
-
|------------|-----------------|--------|
|
|
91
|
-
| **Tooling** | Install/update 5+ tools individually | One binary, auto-pulls scanner containers |
|
|
92
|
-
| **Output** | Parse 5 different JSON formats | Unified `kekkai-report.json` |
|
|
93
|
-
| **Threat Modeling** | Expensive consultants or whiteboarding | AI-generated `THREATS.md` locally |
|
|
94
|
-
| **DefectDojo** | 200-line docker-compose + debugging | `kekkai dojo up` (one command) |
|
|
95
|
-
| **Triage** | Read JSON files manually | Interactive terminal UI |
|
|
96
|
-
| **CI/CD** | Complex bash scripts | `kekkai scan --ci --fail-on high` |
|
|
97
|
-
| **PR Feedback** | Manual security review comments | Auto-comments on GitHub PRs |
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## Feature Deep Dives
|
|
102
|
-
|
|
103
|
-
### 🔮 ThreatFlow — AI-Powered Threat Modeling
|
|
104
|
-
|
|
105
|
-
Generate STRIDE-aligned threat models and Mermaid.js Data Flow Diagrams from your codebase.
|
|
106
|
-
|
|
107
|
-

|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
# Ollama (recommended - easy setup, privacy-preserving)
|
|
111
|
-
ollama pull mistral
|
|
112
|
-
kekkai threatflow --repo . --model-mode ollama --model-name mistral
|
|
113
|
-
|
|
114
|
-
# Local GGUF model (requires llama-cpp-python)
|
|
115
|
-
kekkai threatflow --repo . --model-mode local --model-path ./mistral-7b.gguf
|
|
116
|
-
|
|
117
|
-
# Remote API (faster, requires API key)
|
|
118
|
-
export KEKKAI_THREATFLOW_API_KEY="sk-..."
|
|
119
|
-
kekkai threatflow --repo . --model-mode openai
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
**Output:** `THREATS.md` containing:
|
|
123
|
-
- Attack surface analysis
|
|
124
|
-
- STRIDE threat classification
|
|
125
|
-
- Mermaid.js architecture diagram
|
|
126
|
-
- Recommended mitigations
|
|
127
|
-
|
|
128
|
-
[Full ThreatFlow Documentation →](docs/threatflow/README.md)
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
### 🔍 Unified Scanning
|
|
133
|
-
|
|
134
|
-
Run industry-standard scanners without installing them individually. Each scanner runs in an isolated Docker container with security hardening.
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
kekkai scan # Scan current directory
|
|
138
|
-
kekkai scan --repo /path/to/project # Scan specific path
|
|
139
|
-
kekkai scan --output results.json # Custom output path
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
**Scanners Included:**
|
|
143
|
-
| Scanner | Finds | Image |
|
|
144
|
-
|---------|-------|-------|
|
|
145
|
-
| Trivy | CVEs in dependencies | `aquasec/trivy:latest` |
|
|
146
|
-
| Semgrep | Code vulnerabilities | `semgrep/semgrep:latest` |
|
|
147
|
-
| Gitleaks | Hardcoded secrets | `zricethezav/gitleaks:latest` |
|
|
148
|
-
|
|
149
|
-
**Container Security:**
|
|
150
|
-
- Read-only filesystem
|
|
151
|
-
- No network access
|
|
152
|
-
- Memory limited (2GB)
|
|
153
|
-
- No privilege escalation
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
### ✅ Interactive Triage TUI
|
|
158
|
-
|
|
159
|
-
Stop reading JSON. Review security findings in your terminal.
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
kekkai triage
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
**Features:**
|
|
166
|
-
- Navigate findings with keyboard
|
|
167
|
-
- Mark as: Accept, Reject, False Positive, Ignore
|
|
168
|
-
- Filter by severity, scanner, or status
|
|
169
|
-
- Persist decisions in `.kekkai-ignore`
|
|
170
|
-
- Export triaged results
|
|
171
|
-
|
|
172
|
-
<!-- Screenshot placeholder:  -->
|
|
173
|
-
|
|
174
|
-
[Full Triage Documentation →](docs/triage/README.md)
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
### 🚦 CI/CD Policy Gate
|
|
179
|
-
|
|
180
|
-
Automate security enforcement in your pipelines.
|
|
181
|
-
|
|
182
|
-
<p align="center">
|
|
183
|
-
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-scan.png" alt="Kekkai Scanning" width="650"/>
|
|
184
|
-
</p>
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
# Fail on any critical or high findings
|
|
188
|
-
kekkai scan --ci --fail-on high
|
|
189
|
-
|
|
190
|
-
# Fail only on critical
|
|
191
|
-
kekkai scan --ci --fail-on critical
|
|
192
|
-
|
|
193
|
-
# Custom threshold: fail on 5+ medium findings
|
|
194
|
-
kekkai scan --ci --fail-on medium --max-findings 5
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
**Exit Codes:**
|
|
198
|
-
| Code | Meaning |
|
|
199
|
-
|------|---------|
|
|
200
|
-
| 0 | No findings above threshold |
|
|
201
|
-
| 1 | Findings exceed threshold |
|
|
202
|
-
| 2 | Scanner error |
|
|
203
|
-
|
|
204
|
-
**GitHub Actions Example:**
|
|
205
|
-
|
|
206
|
-
```yaml
|
|
207
|
-
- name: Security Scan
|
|
208
|
-
run: |
|
|
209
|
-
pipx install kekkai-cli
|
|
210
|
-
kekkai scan --ci --fail-on high
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
[Full CI Documentation →](docs/ci/ci-mode.md)
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
### 📊 DefectDojo Integration
|
|
218
|
-
|
|
219
|
-
Spin up a complete vulnerability management platform locally.
|
|
220
|
-
|
|
221
|
-
<p align="center">
|
|
222
|
-
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-dojo.png" alt="Kekkai Dojo" width="650"/>
|
|
223
|
-
</p>
|
|
224
|
-
|
|
225
|
-
```bash
|
|
226
|
-
kekkai dojo up --wait # Start DefectDojo (Nginx, Postgres, Redis, Celery)
|
|
227
|
-
kekkai dojo status # Check service health
|
|
228
|
-
kekkai upload # Import scan results
|
|
229
|
-
kekkai dojo down # Stop and clean up (removes volumes)
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
**What You Get:**
|
|
233
|
-
- DefectDojo web UI at `http://localhost:8080`
|
|
234
|
-
- Automatic credential generation
|
|
235
|
-
- Pre-configured for Kekkai imports
|
|
236
|
-
- Clean teardown (no orphaned volumes)
|
|
237
|
-
|
|
238
|
-
<p align="center">
|
|
239
|
-
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/Active-Engagements-kekkai-dojo.png" alt="Kekkai Dojo" width="850"/>
|
|
240
|
-
</p>
|
|
241
|
-
|
|
242
|
-
<p align="center">
|
|
243
|
-
<img src="https://raw.githubusercontent.com/kademoslabs/assets/main/screenshots/kekkai-dojo-dashboard-findings.png" alt="Kekkai Dojo" width="850"/>
|
|
244
|
-
</p
|
|
245
|
-
|
|
246
|
-
[Full Dojo Documentation →](docs/dojo/dojo.md)
|
|
247
|
-
|
|
248
|
-
---
|
|
249
|
-
|
|
250
|
-
### 🔔 GitHub PR Comments
|
|
251
|
-
|
|
252
|
-
Get security feedback directly in pull requests.
|
|
253
|
-
|
|
254
|
-
```bash
|
|
255
|
-
export GITHUB_TOKEN="ghp_..."
|
|
256
|
-
kekkai scan --github-comment
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
Kekkai will:
|
|
260
|
-
1. Run all scanners
|
|
261
|
-
2. Post findings as PR review comments
|
|
262
|
-
3. Annotate specific lines with inline comments
|
|
263
|
-
|
|
264
|
-
---
|
|
265
|
-
|
|
266
|
-
## Installation
|
|
267
|
-
|
|
268
|
-
### pipx (Recommended)
|
|
269
|
-
|
|
270
|
-
Isolated environment, no conflicts with system Python.
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
pipx install kekkai-cli
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Homebrew (macOS/Linux)
|
|
277
|
-
|
|
278
|
-
```bash
|
|
279
|
-
brew install kademoslabs/tap/kekkai
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Scoop (Windows)
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
scoop bucket add kademoslabs https://github.com/kademoslabs/scoop-bucket
|
|
286
|
-
scoop install kekkai
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### Docker (No Python Required)
|
|
290
|
-
|
|
291
|
-
```bash
|
|
292
|
-
docker pull kademoslabs/kekkai:latest
|
|
293
|
-
alias kekkai='docker run --rm -v "$(pwd):/repo" kademoslabs/kekkai:latest'
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
### pip (Traditional)
|
|
297
|
-
|
|
298
|
-
```bash
|
|
299
|
-
pip install kekkai-cli
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
---
|
|
303
|
-
|
|
304
|
-
## Enterprise Features
|
|
305
|
-
|
|
306
|
-
For organizations that need advanced capabilities, **Kekkai Enterprise** provides:
|
|
307
|
-
|
|
308
|
-
| Feature | Description |
|
|
309
|
-
|---------|-------------|
|
|
310
|
-
| **Multi-Tenant Portal** | Web dashboard for managing multiple teams/projects ([Learn More](docs/portal/README.md)) |
|
|
311
|
-
| **SAML 2.0 SSO** | Integrate with Okta, Azure AD, Google Workspace |
|
|
312
|
-
| **Role-Based Access Control** | Fine-grained permissions per team/project |
|
|
313
|
-
| **Advanced Operations** | Automated backup/restore, monitoring, zero-downtime upgrades ([Learn More](docs/ops/README.md)) |
|
|
314
|
-
| **Compliance Reporting** | Map findings to OWASP, PCI-DSS, HIPAA, SOC 2 |
|
|
315
|
-
| **Audit Logging** | Cryptographically signed compliance trails |
|
|
316
|
-
|
|
317
|
-
**Architecture:**
|
|
318
|
-
- Open-source CLI remains fully functional standalone
|
|
319
|
-
- Enterprise features available in separate private repository for licensed customers
|
|
320
|
-
- Optional integration: CLI can sync results to enterprise portal
|
|
321
|
-
- Self-hosted or Kademos-managed deployment options
|
|
322
|
-
|
|
323
|
-
[Contact us for enterprise access →](mailto:sales@kademos.org)
|
|
324
|
-
|
|
325
|
-
---
|
|
326
|
-
|
|
327
|
-
## Security
|
|
328
|
-
|
|
329
|
-
Kekkai is designed with security as a core principle:
|
|
330
|
-
|
|
331
|
-
- **Container Isolation**: Scanners run in hardened Docker containers
|
|
332
|
-
- **No Network Access**: Containers cannot reach external networks
|
|
333
|
-
- **Local-First AI**: ThreatFlow can run entirely on your machine
|
|
334
|
-
- **SLSA Level 3**: Release artifacts include provenance attestations
|
|
335
|
-
- **Signed Images**: Docker images are Cosign-signed
|
|
336
|
-
|
|
337
|
-
For vulnerability reports, see [SECURITY.md](SECURITY.md).
|
|
338
|
-
|
|
339
|
-
---
|
|
340
|
-
|
|
341
|
-
## Documentation
|
|
342
|
-
|
|
343
|
-
| Guide | Description |
|
|
344
|
-
|-------|-------------|
|
|
345
|
-
| [Installation](docs/README.md#installation-methods) | All installation methods |
|
|
346
|
-
| [ThreatFlow](docs/threatflow/README.md) | AI threat modeling setup |
|
|
347
|
-
| [Dojo Quick Start](docs/dojo/dojo-quickstart.md) | DefectDojo in 5 minutes |
|
|
348
|
-
| [CI Mode](docs/ci/ci-mode.md) | Pipeline integration |
|
|
349
|
-
| [Portal](docs/portal/README.md) | Enterprise features overview |
|
|
350
|
-
| [Portal SSO](docs/portal/saml-setup.md) | SAML 2.0 SSO configuration |
|
|
351
|
-
| [Portal RBAC](docs/portal/rbac.md) | Role-based access control |
|
|
352
|
-
| [Portal Deployment](docs/portal/deployment.md) | Self-hosted deployment |
|
|
353
|
-
| [Security](docs/security/slsa-provenance.md) | SLSA provenance verification |
|
|
354
|
-
|
|
355
|
-
---
|
|
356
|
-
|
|
357
|
-
## CI/CD Status
|
|
358
|
-
|
|
359
|
-
[](https://github.com/kademoslabs/kekkai/actions/workflows/kekkai-pr-scan.yml)
|
|
360
|
-
[](https://github.com/kademoslabs/kekkai/actions/workflows/docker-publish.yml)
|
|
361
|
-
[](https://github.com/kademoslabs/kekkai/actions/workflows/docker-security-scan.yml)
|
|
362
|
-
[](https://github.com/kademoslabs/kekkai/actions/workflows/test-cross-platform.yml)
|
|
363
|
-
[](https://github.com/kademoslabs/kekkai/actions/workflows/release-slsa.yml)
|
|
364
|
-
|
|
365
|
-
---
|
|
366
|
-
|
|
367
|
-
## Contributing
|
|
368
|
-
|
|
369
|
-
We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
370
|
-
|
|
371
|
-
---
|
|
372
|
-
|
|
373
|
-
## License
|
|
374
|
-
|
|
375
|
-
Apache-2.0 — See [LICENSE](LICENSE) for details.
|
|
376
|
-
|
|
377
|
-
---
|
|
378
|
-
|
|
379
|
-
<p align="center"><i>Built by <a href="https://kademos.org">Kademos Labs</a></i></p>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|