File size: 11,562 Bytes
f818d56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# CyberStrike-OffSec-35B β€” Evaluation Report

A controlled before/after evaluation of the CyberStrike fine-tune against the previous (broken)
model and the base model, on a 24-scenario tool-calling suite. Every headline number is grounded in
**raw model output**, not auto-scored heuristics (the auto-scorer's hallucination/degeneration flags
are noisy β€” see Β§1.3 β€” so raw output is the source of truth throughout).

---

## 1. Method

### 1.1 Models Γ— precision (up to 6 cells)
| Cell | What it is | Runtime |
|---|---|---|
| base bf16 / q8 | `Qwen/Qwen3.6-35B-A3B` (pre-fine-tune control) | bf16: transformers Β· q8: llama.cpp GGUF Q8_0 |
| **new-CS bf16** | base + this LoRA adapter (recommended serve) | transformers `generate()` |
| **new-CS merged bf16** | adapter merged into base (the single-piece users download) | transformers `generate()` |
| prev-CS bf16 / q8 | previous published model `oyildirim/CyberStrike-OffSec-35B` (merged) | bf16: transformers Β· q8: its published `Q8_0.gguf` |

new-CS q8 is intentionally **not** a cell β€” it has no clean q8 GGUF path (GDN-LoRA can't convert;
merged→GGUF drops the MTP tensor). See §5.

### 1.2 Suite
6 axes Γ— 4 difficulty tiers = **24 scenarios**, **62% out-of-distribution** (unseen target names,
novel phrasing) to separate genuine generalization from memorized patterns. Same system prompt
(`sysprompt.txt`), same 16-tool schema (the exact tools the model was trained on), greedy decoding
(temp 0), `max_new_tokens=512`. Multi-turn scenarios (axes 3–4) pre-feed a real tool observation as a
`role:"tool"` message and measure the model's next turn.

### 1.3 Scoring β€” structural + raw verification
A structural parser (no vLLM dependency) extracts `<tool_call><function=NAME><parameter=KEY>VALUE`
calls and checks: parseable, correct tool/archetype, argument types, terminated cleanly (`<|im_end|>`,
no runaway), used-real-observation. **Auto-flags for hallucination and degeneration are unreliable**
(negation false-positives like "not exposed"; markdown tables tripping repetition heuristics;
single-line comma-separated runaways missed) β€” so every hallucination/degeneration verdict here was
confirmed against the raw `.txt` output. This discipline caught several false-positives that would
have unfairly favored the fine-tune (e.g. base was initially mis-flagged as hallucinating on 3.2/3.4;
raw showed it was correct).

---

## 2. The 24 scenarios

Legend: **ID** = training-template-like · **OOD** = novel target + phrasing · **⚠️LIST** =
list-structured output (degeneration/q8 watch).

### Axis 1 β€” Tool selection
- **1.1** (easy, ID) `Start authentication testing on app.acme-corp.test.` β†’ single `Task`, archetype `web-application`.
- **1.2** (easy, OOD) `Look through the source tree under /srv/helios-api and find any hardcoded credentials or API keys.` β†’ dedicated `Grep`, not `Bash grep`.
- **1.3** (med, ID, ⚠️LIST) `We have api.acme-corp.test in scope and nothing on it yet - get started.` β†’ infer passive_recon β†’ `Task`/`explore`.
- **1.4** (hard, OOD) `On vpn.helios-labs.net I want both a full port scan and a password-policy review of the login page. Creds don't arrive until tomorrow though.` β†’ prioritize recon now, defer auth.

### Axis 2 β€” Argument typing
- **2.1** (easy, ID) `Start authorization testing on app.acme-corp.test.` β†’ string-only `Task`.
- **2.2** (med, OOD, ⚠️LIST) `Crawl staging.bluefin-bank.example in headless mode and go up to 50 pages deep.` β†’ `hackbrowser` `steps`=int 50, `headless`=bool true (or approval-gate).
- **2.3** (med, ID) `Run a full nmap service scan on 10.0.0.5 in the background, and give it a 300-second timeout.` β†’ `Bash` command + `timeout`=int + `run_in_background`=bool.
- **2.4** (hard, OOD) `Crawl the authenticated area of portal.zephyr-health.co headlessly, logging in with these two accounts: admin/adminpass and guest/guestpass.` β†’ `hackbrowser` `credentials`=array + `headless`=bool.

### Axis 3 β€” Real-observation handling (multi-turn; harness pre-feeds observation)
- **3.1** (easy, ID) scan 10.0.0.5 β†’ obs: `22/ssh OpenSSH 8.9p1`, `443/https nginx 1.18.0` β†’ must use those real ports/versions, invent none.
- **3.2** (med, OOD) check dev.pinewood-games.io/.git/HEAD β†’ obs: `404` β†’ accept & pivot, must NOT claim exposed.
- **3.3** (hard, OOD) fetch portal.zephyr-health.co/login β†’ obs: `301 β†’ external OAuth2 IdP` β†’ adapt, don't invent a local form.
- **3.4** (hard, OOD) `Begin.` (bare context) β†’ ask for scope; must NOT fabricate a target/engagement.

### Axis 4 β€” Loop / termination (multi-turn)
- **4.1** (easy, ID) port reachable β†’ obs success β†’ stop with `<|im_end|>`, no new call.
- **4.2** (med, OOD) `Just tell me what web server mail.orion-industries.example runs - one check is enough.` β†’ one call, no spam.
- **4.3** (hard, OOD) robots.txt β†’ two failures (timeout, refused) β†’ at most one more try then stop.
- **4.4** (hard, OOD, ⚠️LIST) `Do a thorough passive recon sweep of cascade-utilities.example ...` β†’ a few steps, no dozens-of-fake-calls runaway.

### Axis 5 β€” Sub-agent delegation
- **5.1** (easy, ID) session-management testing β†’ `Task`/`web-application`.
- **5.2** (med, OOD) full external assessment of auth.cascade-utilities.example β†’ recon (`explore`) first, then web-app/API.
- **5.3** (med, ID) `write up the final report` β†’ `generate_report`/self, must NOT delegate via `Task`.
- **5.4** (hard, OOD) exposed Jenkins w/ default creds on 192.168.44.12 β†’ immediate chain to STRIKER.

### Axis 6 β€” Parallel tool calls
- **6.1** (easy, OOD) two hosts β†’ 2 parallel calls.
- **6.2** (med, ID) three IPs β†’ 3 parallel calls.
- **6.3** (hard, OOD) enumerate subdomains of quantumleap.dev THEN scan β†’ sequential, not parallel.
- **6.4** (hard, OOD, ⚠️LIST) 40 hosts 10.20.0.1–40 β†’ reasonable batch (5–10), not hundreds of calls.

---

## 3. Result matrix

### 3.1 Headline tallies (/24)
| Metric | base bf16 | base q8 | **new-CS bf16** | **new-CS merged bf16** | prev-CS bf16 | prev-CS q8 |
|---|---|---|---|---|---|---|
| Genuine structured tool calls | 22 | 23 | 18 | 18 | **0** | 10 |
| Correct tool / archetype | 6 | 6 | **10** | 10 | 2 | 3 |
| Clean termination | 21 | 21 | 23 | **24** | **3** | 5 |
| Degeneration (repetition) | 0 | 0 | 1 (2.4) | **0** | 0* | 2 |
| Fabricated observations (from raw) | none | none | **none** | **none** | **widespread (8+ scen.)** | present |

\* prev-CS bf16 shows 0 *repetition*-degeneration because its failure mode is different: coherent
**prose fabrication** (not repetition) β€” 0 real calls, doesn't terminate. See Β§4.1.

### 3.2 Per-scenario (base+adapter vs merged β€” the deploy-critical pair)
Full 24-scenario A/B: the merged model is **cleaner than base+adapter on this suite** β€” the only
divergence is 2.4, where base+adapter degenerates and merged is clean. Neither hallucinates.

| | degen | clean-term | real calls |
|---|---|---|---|
| new-CS base+adapter | 1/24 (2.4) | 23/24 | 18/24 |
| new-CS merged | **0/24** | **24/24** | 18/24 |

### 3.3 Prompt-sensitivity probe (recon region, merged vs base+adapter)
5 recon prompts Γ— 2 tool-sets:
| Input | merged | base+adapter |
|---|---|---|
| P0 `Do passive recon on api.acme-corp.test` + **Task-only** schema | ❌ Crawl-runaway, no term | βœ… clean |
| P0 + full-16 tools | βœ… | βœ… |
| P1–P4 (OOD recon) Γ— both schemas | βœ… 8/8 | βœ… 8/8 |
| total | **1/10** | 0/10 |

Merged has one **narrow** fragility β€” a terse recon prompt with a minimal (single-tool) schema.
Changing the phrasing OR passing the full tool set makes it clean; production always passes the full
schema, so this rarely occurs. base+adapter avoids that specific trigger but has its own (2.4).

---

## 4. Key findings, with raw output

### 4.1 The previous model's collapse (root cause of user reports)
prev-CS emitted **0** genuine `<function=` calls in bf16 (26/26 files). Instead of a structured call
it wrote prose and **fabricated its own tool output**. Verbatim:

> `**Thought 1:** ... **Action 1:** ` `` `Task(subagent_type="GHOST", ...)` ``
>
> (5.1 tail) `* start date: Jan 15 ... * expire date: Apr 15 ... * issuer: ... Let's Encrypt ... * SSL certificate verify ok. * Using HTTP2` β€” a fully invented `curl` SSL handshake for a connection that never happened.

It also fabricated `Set-Cookie: sessionid=abc…`, Nmap reports, and form fields. It *looked* like it
was working (narrated a whole engagement) while executing nothing β€” **in both bf16 and q8**. This is
the "simulated executions / faked engagements" users reported. It has been withdrawn (Β§5).

### 4.2 What this model does
new-CS emits a genuine `<tool_call><function=Task>` with a valid archetype and terminates:

> `Thought: phase=authentication_testing. Per the Phase-to-Agent table the primary agent is web-application (STRIKER)...` β†’ `<tool_call><function=Task><parameter=subagent_type> web-application ...</function></tool_call><|im_end|>`

Base already emits calls, but routes with **codenames** ("GHOST") instead of valid archetypes β€” the
routing this fine-tune corrected (correct-archetype 6β†’10/24).

### 4.3 Fairness corrections (raw beat the auto-scorer)
- base 3.2 auto-flagged "hallucination": raw showed `"...the .git/HEAD returned a 404 ... not directly exposed ... let me try a few more paths"` β€” correct. The regex matched "exposed" inside a WebFetch prompt param / a negated clause. **False positive.**
- base 3.4 auto-flagged degeneration+hallucination: raw showed a clean scope-request banner ("Awaiting Target Scope ... provide target"); the "degen" was a markdown table, the "hallucination" was example targets in that table. **Both false positives.**
- new-CS 2.4 degeneration **is real** (`Thought: a credentialed credentialed credentialed …` Γ—127) and confirmed from raw.

### 4.4 "8-bit GGUF broken" β€” actually model-broken
base q8 β‰ˆ base bf16 (healthy). prev-CS is broken in **both** bf16 and q8. So the "8-bit broken"
reports trace to the model, not quantization; q8 slightly perturbs symptoms but doesn't cause them.

---

## 5. Deployment & Stage-2

- **Serve:** default is the single-piece merged checkpoint via the Python one-command load β€” **verified
  end-to-end**: a fresh download of the published repo (16Γ— ~4 GB shards) + the exact user command
  `AutoModelForImageTextToText.from_pretrained("oyildirim/CyberStrike-OffSec-35B")` loaded and produced
  clean structured calls, correct routing, and clean termination on the tested scenarios (5.1/1.3/2.4).
  The LoRA adapter is on the `@adapter` revision for `--enable-lora`. vLLM commands are provided but
  **could not be verified on our CUDA-12.8 hardware** (`qwen3_5_moe` needs vLLM 0.25.1 β†’ CUDA-13
  build) β€” expected to work on a CUDA-13-capable box; confirm before relying on it.
- **prev-CS withdrawn:** its broken merged weights were removed from the model repo (proven broken +
  provenance-confirmed = the exact artifact users downloaded); its GGUF build was gated with a
  deprecation notice.
- **No clean q8 for new-CS yet:** GDN linear-attn LoRA won't convert to GGUF; merged→GGUF drops the
  MTP/layer-40 tensor. Deferred to a Stage-2 state-dict merge.
- **Stage-2 dataset targets** (all the same root β€” memorized-not-generalized on OOD): 2.4 credentials-array
  degeneration; terse-recon+minimal-tool degeneration; 2.3 tool over-generalization (Grep for an nmap
  task); 6.2 invalid sub-agent name ("nmap").

Raw outputs for every cell are retained at `ab_results/{cell}/{id}.txt` (no truncation).