diff --git a/CHANGELOG.md b/CHANGELOG.md index 18b2a82b02..ed22c3a951 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,15 +18,19 @@ Format based on [Keep a Changelog](https://keepachangelog.com/), versions follow - Version-pinned MCP catalog with manual/optional install states and three additional owner-maintained integrations - Safe recovery startup with `--safe` and namespaced extension configuration - Target-selectable source builds and a localhost-only systemd user service template for Kali/Linux deployments +- Always-visible live workbench status with resilient activity streaming, meaningful change badges, and event-driven Mission, Topology, and Memory refresh ### Changed - MCP tool materialization now filters schemas before conversion and enforces real context-budget eviction +- Agent methodology now routes Nmap through the approval-gated `nmap_scan` system of record and explicitly records verified discoveries, findings, and reusable memory for workbench projection ### Fixed - Release and local-binary installs now deploy the bundled HackBrowser worker to the runtime data directory - Web update checks now honor disabled auto-updates, avoiding false upgrade prompts for managed source builds +- Hidden workbench panels no longer miss live changes or depend on visible-only polling; repeated session lifecycle events and reconnect gaps are recovered +- Nmap permissions now identify active/elevated execution, privileged profiles use non-interactive sudo when required, and Topology explains why generic shell output is not graphable ## [1.1.16] — 2026-08-08 diff --git a/README.md b/README.md index d7cd88e929..76eab5e19e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@
- English |
+ English (personal fork) |
+ Upstream translations:
简体中文 |
繁體中文 |
한국어 |
@@ -28,428 +29,114 @@
+
- A personal open-source project maintained by Suren Sahaydachny. -
- -
- The old model made the security professional the middleware between dozens of disconnected tools.
- CyberStrike replaces that fragmentation with one intelligent, inspectable, open-source orchestration layer.
- Bring Claude, GPT, Gemini, Copilot, or a local model. Leave with an autonomous red team.
-
- 150+ AI providers • 5,300+ models • 56+ built-in tools • 176+ MCP tools -
+
-
-
-
+ Maintained by Suren Sahayachny (
spetro511)
+ and built on the original open-source project from
+ CyberStrikeus/CyberStrike
+ and its contributors.
-
-
-
-
-
+ About this fork •
+ Workbench •
+ Installation •
+ Upstream •
+ Ethical use •
+ License
- Why I Built This •
- Quick Start •
- Intelligence Layer •
- What Makes It Different •
- Agents •
- Skills •
- Web UI •
- Bolt •
- MCP Ecosystem •
- Post-Exploitation •
- Installation •
- Docs •
- Website
+
+
+
| - -**Specialized Security Agents, Not Generic Chat** - -CyberStrike ships with 13+ agents purpose-built for security domains. Each agent carries domain-specific methodology, tool knowledge, and testing patterns. The web-application agent follows OWASP WSTG. The cloud-security agent knows CIS benchmarks. The mobile agent uses Frida and follows MASTG/MASVS. They don't guess — they follow proven offensive security frameworks. - - | -- -**Intelligence Layer, Not Just an LLM Wrapper** - -Most AI security tools are thin wrappers that send your prompt to an API. CyberStrike's intelligence layer normalizes outputs across 150+ providers and 5,300+ models, guards context between test phases, auto-detects your provider configuration, and orchestrates multi-step attack chains. The result: consistent, methodology-driven pentesting regardless of which model you use. - - | -
| - -**150+ Providers, Zero Lock-in** - -Anthropic, OpenAI, Google, Amazon Bedrock, Azure, Groq, Mistral, xAI, DeepSeek, Cerebras, Cohere, OpenRouter, Together AI, GitHub Copilot — or run fully offline with Ollama and LM Studio. 150+ providers, 5,300+ models. You choose the model. You own the results. As AI models get better and cheaper, CyberStrike gets better with them. Switch providers in seconds without reconfiguring anything. - - | -- -**Remote Tool Execution with Bolt** - -Your security tools don't have to run on your laptop. Deploy Bolt on one or many remote servers, pair with Ed25519 keys, and control everything from your local terminal. One CyberStrike instance can orchestrate dozens of Bolt servers — each with its own toolkit, network position, and attack surface access. - - | -
|
- Suren Sahaydachny - |
-- -**Suren Sahaydachny** maintains this public CyberStrike workstream as a personal open-source project focused on AI-first systems, multi-agent orchestration, security automation, and the future of human-machine collaboration. - -- **Email:** [surenpeter511@gmail.com](mailto:surenpeter511@gmail.com) -- **LinkedIn:** [linkedin.com/in/suren-sahaydachny](https://www.linkedin.com/in/suren-sahaydachny) -- **GitHub:** [github.com/spetro511](https://github.com/spetro511) - - | -
- Suren Sahaydachny · Email · GitHub · CyberStrike · Docs · Discord -
-- A personal open-source workstream maintained by Suren Sahaydachny — for security professionals who got tired of being the middleware between their tools. + Original CyberStrike project · + Suren's personal fork · + Upstream docs · + Upstream website
- The next era will not be defined by more software. It will be defined by better orchestration. + Upstream CyberStrike and its contributors are the foundation of this enhanced personal distribution.
diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index a942ada714..72fea45a53 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -21,6 +21,7 @@ import { TerminalProvider } from "@/context/terminal" import { PromptProvider } from "@/context/prompt" import { FileProvider } from "@/context/file" import { CommentsProvider } from "@/context/comments" +import { WorkbenchProvider } from "@/context/workbench" import { NotificationProvider } from "@/context/notification" import { ModelsProvider } from "@/context/models" import { DialogProvider } from "@cyberstrike-io/ui/context/dialog" @@ -92,7 +93,9 @@ function SessionProviders(props: ParentProps) {
{JSON.stringify(
@@ -70,79 +57,23 @@ function ActivityRow(props: { event: Activity }) {
export function ActivityPanel() {
const params = useParams()
- const sdk = useSDK()
- const [events, setEvents] = createStore([])
+ const workbench = useWorkbench()
const [source, setSource] = createSignal("all")
const [search, setSearch] = createSignal("")
const [mode, setMode] = createSignal<"timeline" | "lanes">("timeline")
const [follow, setFollow] = createSignal(true)
- const [error, setError] = createSignal("")
let scroll!: HTMLDivElement
- const add = (event: Activity) => {
- const index = events.findIndex((item) => item.id === event.id)
- if (index !== -1) {
- setEvents(index, reconcile(event))
- return
- }
- setEvents(
- produce((draft) => {
- draft.push(event)
- if (draft.length > 2_000) draft.splice(0, draft.length - 2_000)
- }),
- )
- }
-
- const merge = (incoming: Activity[]) => {
- setEvents(reconcile(mergeActivity(incoming, [...events])))
- }
-
createEffect(() => {
- const sessionID = params.id
- if (!sessionID) {
- setEvents(reconcile([]))
- return
- }
-
- const abort = new AbortController()
- const client = sdk.createClient({
- directory: sdk.directory,
- throwOnError: true,
- signal: abort.signal,
- })
- setError("")
- void client.eventLog
- .list({ sessionID, limit: 500 })
- .then((response) => merge(response.data ?? []))
- .catch((cause) => {
- if (!abort.signal.aborted) setError(cause instanceof Error ? cause.message : String(cause))
- })
- void (async () => {
- try {
- const response = await client.eventLog.stream(
- { sessionID },
- {
- onSseError: (cause) => {
- if (!abort.signal.aborted) setError(cause instanceof Error ? cause.message : String(cause))
- },
- },
- )
- for await (const event of response.stream) {
- if (isActivity(event)) add(event)
- }
- } catch (cause) {
- if (!abort.signal.aborted) setError(cause instanceof Error ? cause.message : String(cause))
- }
- })()
- onCleanup(() => abort.abort())
+ if (workbench.changes("activity") > 0) workbench.ack("activity")
})
const filtered = createMemo(() => {
const query = search().trim().toLowerCase()
- return events.filter((event) => {
+ return workbench.events.filter((event) => {
if (source() !== "all" && event.source !== source()) return false
if (!query) return true
- return `${event.type} ${summary(event)} ${event.correlationID ?? ""}`.toLowerCase().includes(query)
+ return `${event.type} ${activitySummary(event)} ${event.correlationID ?? ""}`.toLowerCase().includes(query)
})
})
@@ -174,7 +105,7 @@ export function ActivityPanel() {
}}
onClick={() => setSource("all")}
>
- All {events.length}
+ All {workbench.events.length}
{(item) => (
@@ -226,8 +157,10 @@ export function ActivityPanel() {
+ {String(perm.metadata?.command)}
+
+