Repository navigation
Commit 3fb26e8
authored
fix(statusline): overlay ruflo's fabricated CVE counter with the real scan (#26)
The statusline told every clean repo it had 3 CVEs. Upstream's
getSecurityStatus (@claude-flow/cli funnel/local-signals.js) hardcodes
`const totalCves = 3` — ruflo's OWN v3 roadmap items (CVE-1/2/3 in their
v3-security-architect.md: an outdated dep + SHA-256 hashing + hardcoded
creds in THEIR api/auth-service.ts), not the rendered project's risk — and
derives cvesFixed from scans.length, a FILE count. The alarm therefore
cleared itself: run the suggested scan, it writes a JSON file, the counter
drops. Three files reach CLEAN with nothing scanned, let alone fixed, while
a real finding never registers. Reported upstream: ruvnet/ruflo#2694.
The overlay reports what the newest scan actually found and never invents a
CVE: totalCves/cvesFixed are pinned to 0 so the "N CVEs" branch cannot fire,
and real state rides in `status`, which ruflo's renderer prints verbatim —
PENDING when never scanned (an honest unknown, not a false green), "N
ISSUES" when the scan found things, CLEAN, or STALE past 7 days.
Wired by wrapping getStatuslineData rather than patching applyLocalOverlays:
the fresh-cache early return (`if (cache.fresh && cache.promoFresh) return
overlayMemoPromo(cache.data)`) bypasses applyLocalOverlays entirely, so a
patch there is never called during the 60s TTL and the fabricated count
renders anyway. Wrapping the one entry point covers all four return paths.
The count also reaches the screen a second way — funnel/insights.js computes
`pending = totalCves - cvesFixed` CLI-side and ships a finished sentence —
so rufloHonestInsight rebuilds that one line from the real scan, matching on
text because promo.js discards the insight id.
Gated on positively detecting the defect in the installed CLI rather than a
pinned version, mirroring improvement-eval's --cli-check stopgap: the patch
retires itself on the first sync after upstream fixes this. Covered by a
test.
Also in this change:
- status: detect statusline CONTENT drift, not just marker presence. Drift
is now "would a sync change this file?", which fixStatusline's dry run
already answers. A marker test reported 'ok' on a stale injected block, and
since sync builds its plan from rows carrying a `fix`, re-injection never
ran. This bit us live: an updated overlay silently failed to land. It also
means any kit upgrade revising the footer would not have re-injected.
- statusline: make the aidefence segment alarm-only. It was a permanent green
"aidefence on" — the one pure binary badge in the footer (SONA/QE counts
move; a constant "on" says nothing after the first glance) — and its shield
glyph collided with ruflo's line-2 scan shield, a different concern
entirely: `security scan` audits your source, `security defend`/AIMDS
screens prompts for injection, jailbreak and PII. Per issue #8's rule,
already law for the proof segment, the expected state is now silent and
only the failure surfaces, with no shield glyph in the alarm.
Kept rather than deleted because it is load-bearing: @claude-flow/aidefence
is still not a declared dependency of ruflo or @claude-flow/cli on 3.32.0
while `security defend` imports it (ruvnet/ruflo#2670), so it is present
only because healAidefence installs it. A plain `npm i -g ruflo` can
silently remove injection defense.
The probe is three-state, not boolean: inverting a signal inverts its
failure mode, and a probe miss (custom npm prefix, statusline running under
a different node) would otherwise fail loud and WRONG. "off" requires
positive evidence — a located ruflo install lacking aidefence; anything
unverifiable stays "unknown" and silent.1 parent 6105d9f commit 3fb26e8
5 files changed
Lines changed: 582 additions & 19 deletions
File tree
- src
- commands
- lib
- templates
- tests
- kit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
261 | 262 | | |
262 | 263 | | |
263 | 264 | | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
268 | 294 | | |
269 | 295 | | |
270 | 296 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
18 | 18 | | |
19 | 19 | | |
20 | 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 | + | |
21 | 76 | | |
22 | 77 | | |
23 | 78 | | |
| |||
35 | 90 | | |
36 | 91 | | |
37 | 92 | | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
38 | 97 | | |
39 | 98 | | |
40 | | - | |
| 99 | + | |
41 | 100 | | |
42 | 101 | | |
43 | 102 | | |
| |||
71 | 130 | | |
72 | 131 | | |
73 | 132 | | |
74 | | - | |
| 133 | + | |
75 | 134 | | |
0 commit comments