break-anything 0.0.0-stage → 0.2.0
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/DISCLAIMER.md +44 -0
- package/LICENSE +21 -0
- package/README.md +222 -2
- package/bin/brk.js +187 -0
- package/docs/assets/break-flow.svg +54 -0
- package/docs/assets/hero.gif +0 -0
- package/docs/hero-gif.md +51 -0
- package/docs/installation.md +73 -0
- package/docs/launch.md +70 -0
- package/docs/mcp-tools.md +205 -0
- package/docs/readme/README_zh.md +172 -0
- package/docs/roadmap.md +51 -0
- package/package.json +48 -4
- package/src/epss.js +28 -0
- package/src/http.js +44 -0
- package/src/image.js +114 -0
- package/src/lockfiles.js +118 -0
- package/src/mcp.js +121 -0
- package/src/osv.js +92 -0
- package/src/reachability.js +66 -0
- package/src/report.js +225 -0
- package/src/sast.js +128 -0
- package/src/scan.js +93 -0
- package/src/secrets.js +160 -0
package/DISCLAIMER.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Responsible use
|
|
2
|
+
|
|
3
|
+
Break Anything is a **defensive security tool**. It helps you find, prove, and fix
|
|
4
|
+
vulnerabilities in software **you own or are explicitly authorized to test**.
|
|
5
|
+
|
|
6
|
+
## Authorized scope only
|
|
7
|
+
|
|
8
|
+
Use Break Anything only against:
|
|
9
|
+
|
|
10
|
+
- code, dependencies, images, and infrastructure that you own;
|
|
11
|
+
- systems you have **written, contractual authorization** to test (e.g. a pentest engagement
|
|
12
|
+
with a signed scope);
|
|
13
|
+
- deliberately vulnerable labs and open-source projects intended for security practice.
|
|
14
|
+
|
|
15
|
+
Do **not** point Break Anything — especially its dynamic (running-app and API) capabilities — at
|
|
16
|
+
any system you do not own or are not authorized to test. Unauthorized testing of computer systems
|
|
17
|
+
is illegal in most jurisdictions and is not supported by this project.
|
|
18
|
+
|
|
19
|
+
## Safety defaults
|
|
20
|
+
|
|
21
|
+
- **Dynamic capabilities are off by default.** Running-app scanning, API testing, and any
|
|
22
|
+
capability that sends traffic to a target require both an operator policy and an explicit
|
|
23
|
+
per-run authorization flag.
|
|
24
|
+
- **Static analysis reads your files; it does not run them.**
|
|
25
|
+
- **Proof-of-concept output targets your own build.** Break Anything is designed to demonstrate a
|
|
26
|
+
weakness against your target so you can fix it — not to produce reusable weapons against third
|
|
27
|
+
parties.
|
|
28
|
+
- **Analysis is local.** Break Anything does not ship your code to a hosted analysis service. The
|
|
29
|
+
coding agent and model provider you use have their own data policies.
|
|
30
|
+
|
|
31
|
+
## Not weaponization
|
|
32
|
+
|
|
33
|
+
Break Anything orchestrates well-known security tooling to help defenders. It is not intended for
|
|
34
|
+
developing malware, building attack infrastructure, targeting systems at scale, or evading the
|
|
35
|
+
defenses of systems you do not control. Contributions that turn it in those directions will be
|
|
36
|
+
declined.
|
|
37
|
+
|
|
38
|
+
## Your responsibility
|
|
39
|
+
|
|
40
|
+
You are responsible for using Break Anything in compliance with all applicable laws and
|
|
41
|
+
regulations, and with the license terms of every third-party tool it orchestrates. If you are
|
|
42
|
+
unsure whether you are authorized to test a given target, assume you are not.
|
|
43
|
+
|
|
44
|
+
Report security issues in Break Anything itself through the process in [SECURITY.md](SECURITY.md).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Break Anything contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,223 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**English** · [简体中文](docs/readme/README_zh.md)
|
|
4
|
+
|
|
5
|
+
# Break Anything
|
|
6
|
+
|
|
7
|
+
### You think your service is secure. You've never seen it the way an attacker would.
|
|
8
|
+
|
|
9
|
+
Break Anything points your coding agent at your own code, apps, and infrastructure and hunts them
|
|
10
|
+
**like an attacker** — surfacing what's genuinely exploitable, proving it on your own build, and
|
|
11
|
+
fixing it. Before someone else finds it first.
|
|
12
|
+
|
|
13
|
+
*See your own service through an attacker's eyes.*
|
|
14
|
+
|
|
15
|
+
[](https://www.npmjs.com/package/break-anything)
|
|
16
|
+
[](docs/mcp-tools.md)
|
|
17
|
+
[](DISCLAIMER.md)
|
|
18
|
+
[](LICENSE)
|
|
19
|
+
|
|
20
|
+
**[Quick start](#quick-start) · [Why it's different](#why-its-different) · [See it in 30s](#see-it-in-30-seconds) · [The arsenal](#the-arsenal) · [FAQ](#faq)**
|
|
21
|
+
|
|
22
|
+
<code>npx break-anything setup</code>
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
> [!IMPORTANT]
|
|
27
|
+
> Break Anything tests software **you own or are explicitly authorized to test**. Every
|
|
28
|
+
> proof-of-concept runs against your own target. It's a defensive tool, not an attack framework,
|
|
29
|
+
> and must never be pointed at third-party systems.
|
|
30
|
+
|
|
31
|
+
<div align="center">
|
|
32
|
+
|
|
33
|
+
<!-- Record with: vhs demos/hero.tape -->
|
|
34
|
+
<img src="docs/assets/hero.gif" alt="Break Anything: which vulnerabilities actually reach your code, plus a secret hiding in git history" width="900" />
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
"It's probably fine." It shipped, it works, nobody has complained — so you assume it's secure. But
|
|
41
|
+
"no breach yet" was never a security test. The only honest one is to look at your own service the
|
|
42
|
+
way an attacker will: which dependency is an open door, what key is still in your git history,
|
|
43
|
+
which endpoint hands over another user's data.
|
|
44
|
+
|
|
45
|
+
And you're never done. A critical unauthenticated RCE turned up in PHP itself in October 2026 after
|
|
46
|
+
years in plain sight (php2shell) — if the language behind much of the web still has critical holes,
|
|
47
|
+
so does your app. Every dependency you add widens the surface, and you can't close them all. So fix
|
|
48
|
+
the few an attacker can reach *today*.
|
|
49
|
+
|
|
50
|
+
And the economics just flipped: the same AI agents that write code now hunt vulnerabilities at
|
|
51
|
+
scale — and attackers have them too. Find your holes first, with the same leverage.
|
|
52
|
+
|
|
53
|
+
**Break Anything gives your coding agent that attacker's-eye view** — in one sentence, on software
|
|
54
|
+
you own: what's genuinely exploitable, proven on *your* build, with the fix. Everything runs
|
|
55
|
+
locally. Nothing is pointed anywhere you don't own.
|
|
56
|
+
|
|
57
|
+
## Quick start
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx break-anything setup
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Pick your agent, approve the changes, restart. Works with Claude Code, Codex, Cursor, Gemini CLI,
|
|
64
|
+
Windsurf, and anything that runs a local MCP server. Then just ask:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
Use Break Anything on this project. Show me only the vulnerabilities that are
|
|
68
|
+
actually reachable in my code, prove the worst one, and give me the fix.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Prefer the terminal? One command, shipped today:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx -y break-anything deps ./ # dependency CVEs, ranked by reachability + EPSS
|
|
75
|
+
npx -y break-anything secrets ./ --history # leaked keys in the tree and full git history
|
|
76
|
+
npx -y break-anything image my-svc:latest # OS + app CVEs in a container image
|
|
77
|
+
npx -y break-anything sast ./src # static code analysis (injection, authz, SSRF…)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Why it's different
|
|
81
|
+
|
|
82
|
+
Every scanner can hand you a list. The list is the problem. Break Anything is built around the
|
|
83
|
+
three things a list can't do:
|
|
84
|
+
|
|
85
|
+
- **Reachability — it thinks like an attacker.** An attacker doesn't work through 400 theoretical
|
|
86
|
+
CVEs; they go straight for the few they can actually reach. Break Anything does the same:
|
|
87
|
+
`confirmed` → `reachable` → `present` → `not-reachable`. The vulnerable `lodash` you never call
|
|
88
|
+
is noise; the one on a live code path is the finding. You triage 3, not 400.
|
|
89
|
+
- **Proof, not prose.** Instead of a CVSS paragraph, it builds a proof-of-concept against *your*
|
|
90
|
+
build — the exact input or request that breaks it — so "theoretically vulnerable" becomes
|
|
91
|
+
"here's the repro."
|
|
92
|
+
- **A fix, even when upstream is gone.** No patched version because the maintainer vanished? It
|
|
93
|
+
proposes a patch, a pin, a compatibility shim, or a maintained fork — so an abandoned dependency
|
|
94
|
+
doesn't become your breach. Hand it to [Patch Anything](#companion-patch-anything) for a
|
|
95
|
+
merge-ready PR.
|
|
96
|
+
|
|
97
|
+
It doesn't replace OSV, Trivy, Semgrep or ZAP — it **orchestrates** them behind one agent
|
|
98
|
+
interface and does the reasoning they can't.
|
|
99
|
+
|
|
100
|
+
## See it in 30 seconds
|
|
101
|
+
|
|
102
|
+
Three things you'll reach for it, each one sentence to your agent:
|
|
103
|
+
|
|
104
|
+
| The moment | Ask | What you get back |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
| **"A CVE is trending — are we hit?"** | *"Scan my deps, only flag what's reachable."* | 3 reachable CVEs with fix versions — not a 400-line wall |
|
|
107
|
+
| **"Did someone commit a key?"** | *"Scan the repo and git history for secrets."* | The leaked key, the commit that introduced it, "rotate don't delete" |
|
|
108
|
+
| **"Can user A read user B's data?"** | *"Check /orders/:id for broken access control."* | The IDOR, proven against localhost with two accounts |
|
|
109
|
+
|
|
110
|
+
## What you point it at
|
|
111
|
+
|
|
112
|
+
You don't pick a mode. Hand it whatever you have — it detects the form and routes to the right
|
|
113
|
+
engine.
|
|
114
|
+
|
|
115
|
+
| You give it | Form | Categories |
|
|
116
|
+
| --- | --- | --- |
|
|
117
|
+
| A repo or source tree | source / tech stack | SCA, SAST, Secrets |
|
|
118
|
+
| A lockfile (`package-lock.json`, `composer.lock`, `go.mod`…) | manifest | SCA |
|
|
119
|
+
| A container image | build artifact | Containers |
|
|
120
|
+
| An APK / IPA or compiled binary | build artifact | Mobile, Fuzzing |
|
|
121
|
+
| A Terraform / Kubernetes / Dockerfile | config | IaC |
|
|
122
|
+
| A running URL or API (yours) | live system | DAST, API |
|
|
123
|
+
| Cloud credentials (yours) | live account | Cloud posture |
|
|
124
|
+
| Git history | repo metadata | Secrets |
|
|
125
|
+
|
|
126
|
+
## The arsenal
|
|
127
|
+
|
|
128
|
+
Organized by scan category — the language security teams speak — each orchestrating tools that
|
|
129
|
+
already run in real pipelines. ✅ shipped in 0.1.0 · 🧭 on the roadmap.
|
|
130
|
+
|
|
131
|
+
### ✅ Shipped today
|
|
132
|
+
|
|
133
|
+
- **Dependencies (SCA)** — known CVEs across your whole tree, ranked by reachability + EPSS, with fix versions. Engines: [OSV](https://osv.dev), [Trivy](https://github.com/aquasecurity/trivy), [Grype](https://github.com/anchore/grype), `pip-audit`, `govulncheck`, `composer audit`. Ecosystems: npm, PyPI, Composer, Go, Maven, Cargo, RubyGems, NuGet.
|
|
134
|
+
- **Secrets** — leaked keys/tokens/private keys in the working tree and full git history, redacted. Engines: [Gitleaks](https://github.com/gitleaks/gitleaks), [TruffleHog](https://github.com/trufflesecurity/trufflehog).
|
|
135
|
+
- **Container images** — OS + app CVEs, Dockerfile smells, secrets in layers. Engines: [Trivy](https://github.com/aquasecurity/trivy), [Grype](https://github.com/anchore/grype), [Hadolint](https://github.com/hadolint/hadolint).
|
|
136
|
+
- **Static code (SAST)** — injection, broken access control, insecure deserialization, SSRF, hardcoded secrets — each with file/line, CWE/OWASP tags, and the offending snippet. Engine: [Semgrep](https://semgrep.dev).
|
|
137
|
+
|
|
138
|
+
### 🧭 On the roadmap
|
|
139
|
+
|
|
140
|
+
- **More SAST engines** — [CodeQL](https://codeql.github.com), SonarQube CE, Bandit (Python), gosec (Go), Brakeman (Rails), Find-Sec-Bugs (Java), security-code-scan (.NET), retire.js (frontend JS).
|
|
141
|
+
- **Infrastructure & Kubernetes (IaC)** — public buckets, open ports, over-broad IAM, misconfigured clusters — before `apply`. [Checkov](https://www.checkov.io), tfsec, Terrascan, [KICS](https://kics.io), [Kubescape](https://github.com/kubescape/kubescape), kube-bench, [Falco](https://falco.org) (runtime).
|
|
142
|
+
- **Running apps & attack surface (DAST)** — OWASP Top 10, content/parameter discovery, XSS, injection against your authorized app. [OWASP ZAP](https://www.zaproxy.org), [Nuclei](https://github.com/projectdiscovery/nuclei), [Nikto](https://github.com/sullo/nikto), [ffuf](https://github.com/ffuf/ffuf), [Katana](https://github.com/projectdiscovery/katana), [Dalfox](https://github.com/hahwul/dalfox), [sqlmap](https://sqlmap.org); surface mapping via [Nmap](https://nmap.org) + [Amass](https://github.com/owasp-amass/amass) + ProjectDiscovery.
|
|
143
|
+
- **API** — BOLA/IDOR, broken auth, mass assignment (OWASP API Top 10). [Schemathesis](https://github.com/schemathesis/schemathesis), ZAP.
|
|
144
|
+
- **Offensive / exploitation** — *authorized pentest only; gated, off by default, written permission required.* Prove exploitability on targets you own. [Metasploit](https://www.metasploit.com), sqlmap, [Hydra](https://github.com/vanhauser-thc/thc-hydra), [Hashcat](https://hashcat.net), [BloodHound](https://github.com/SpecterOps/BloodHound) + Impacket (Active Directory), [OpenVAS](https://www.openvas.org).
|
|
145
|
+
- **AI / LLM security** — prompt injection, jailbreaks, data leakage in your own models and agents. [Garak](https://github.com/NVIDIA/garak).
|
|
146
|
+
- **Binary & artifact analysis** — known-vulnerable deps and unsafe patterns in compiled binaries. [Ghidra](https://ghidra-sre.org), [radare2](https://github.com/radareorg/radare2), [angr](https://github.com/angr/angr) (pairs with REA).
|
|
147
|
+
- **Cloud posture · Smart contracts · Mobile · Fuzzing** — [Prowler](https://github.com/prowler-cloud/prowler) · [Slither](https://github.com/crytic/slither), Mythril, Echidna · [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF) · [AFL++](https://github.com/AFLplusplus/AFLplusplus), libFuzzer, Jazzer.
|
|
148
|
+
|
|
149
|
+
Full per-tool catalog and MCP contracts: [docs/mcp-tools.md](docs/mcp-tools.md). Every dynamic
|
|
150
|
+
(traffic-sending) category is **off by default** and refuses any target not on your allowlist.
|
|
151
|
+
|
|
152
|
+
## How it works
|
|
153
|
+
|
|
154
|
+
Your agent calls Break Anything over MCP to inspect a target you control. It routes to the right
|
|
155
|
+
engine, confirms reachability, and returns each finding with its evidence and a fix. The CLI uses
|
|
156
|
+
the same workflows.
|
|
157
|
+
|
|
158
|
+

|
|
159
|
+
|
|
160
|
+
**Find** weaknesses across deps, code, secrets, images, IaC, and running apps → **Prove** the
|
|
161
|
+
finding is reachable with a PoC against your target → **Fix** it inline or via Patch Anything.
|
|
162
|
+
Absence of a finding is never reported as proof of safety.
|
|
163
|
+
|
|
164
|
+
## Companion: Patch Anything
|
|
165
|
+
|
|
166
|
+
> **Break Anything** finds it and proves it → **[Patch Anything](https://github.com/EnkiHQ/patch-anything)** fixes it.
|
|
167
|
+
|
|
168
|
+
Hand any finding over and it drafts the patch, bump, shim, or fork. Discovery and repair, one
|
|
169
|
+
loop. Use either alone, or run it end to end.
|
|
170
|
+
|
|
171
|
+
## FAQ
|
|
172
|
+
|
|
173
|
+
<details>
|
|
174
|
+
<summary><strong>How is this different from `npm audit` / Trivy / Snyk?</strong></summary>
|
|
175
|
+
|
|
176
|
+
They report presence — every vulnerability that exists anywhere in your tree. Break Anything adds
|
|
177
|
+
**reachability** (is it actually called), **proof** (a PoC against your own build), and
|
|
178
|
+
**self-remediation** when upstream has no fix, and unifies deps, code, secrets, images, IaC, and
|
|
179
|
+
runtime behind one agent interface.
|
|
180
|
+
|
|
181
|
+
</details>
|
|
182
|
+
|
|
183
|
+
<details>
|
|
184
|
+
<summary><strong>Does it replace those tools?</strong></summary>
|
|
185
|
+
|
|
186
|
+
No — it orchestrates them. Break Anything is the brain and the interface; OSV, Trivy, Semgrep, ZAP
|
|
187
|
+
are the engines. You get their depth without learning each one.
|
|
188
|
+
|
|
189
|
+
</details>
|
|
190
|
+
|
|
191
|
+
<details>
|
|
192
|
+
<summary><strong>Is this an attack tool? Will my repo get taken down?</strong></summary>
|
|
193
|
+
|
|
194
|
+
No. It's defensive and authorized-targets-only; every PoC runs against your own target and it
|
|
195
|
+
ships no weaponized exploits. See [DISCLAIMER.md](DISCLAIMER.md). GitHub policy explicitly supports
|
|
196
|
+
dual-use security research.
|
|
197
|
+
|
|
198
|
+
</details>
|
|
199
|
+
|
|
200
|
+
<details>
|
|
201
|
+
<summary><strong>Does it upload my code?</strong></summary>
|
|
202
|
+
|
|
203
|
+
Analysis runs locally. Your agent receives the results; its model provider has its own data
|
|
204
|
+
policy — review that separately.
|
|
205
|
+
|
|
206
|
+
</details>
|
|
207
|
+
|
|
208
|
+
<details>
|
|
209
|
+
<summary><strong>Which agents can use it?</strong></summary>
|
|
210
|
+
|
|
211
|
+
Any agent that supports local MCP servers. Setup configures the common ones automatically.
|
|
212
|
+
|
|
213
|
+
</details>
|
|
214
|
+
|
|
215
|
+
## Documentation
|
|
216
|
+
|
|
217
|
+
[Installation](docs/installation.md) · [Tool catalog & MCP contracts](docs/mcp-tools.md) ·
|
|
218
|
+
[Roadmap](docs/roadmap.md) · [Security model](SECURITY.md) · [Responsible use](DISCLAIMER.md)
|
|
219
|
+
|
|
220
|
+
## License
|
|
221
|
+
|
|
222
|
+
[MIT](LICENSE). Break-authored code is MIT; the engines it orchestrates keep their own licenses —
|
|
223
|
+
see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
package/bin/brk.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { scanDependencies } from "../src/scan.js";
|
|
3
|
+
import { renderHuman } from "../src/report.js";
|
|
4
|
+
|
|
5
|
+
const VERSION = "0.2.0";
|
|
6
|
+
|
|
7
|
+
const HELP = `Break Anything (brk) v${VERSION}
|
|
8
|
+
点你的 Agent 指向你拥有或已授权的软件,找到漏洞、证明它、修好它。
|
|
9
|
+
|
|
10
|
+
用法:
|
|
11
|
+
brk deps [path] 扫描依赖 lockfile 的已知漏洞(默认当前目录)
|
|
12
|
+
brk secrets [path] 扫描泄露的密钥(工作区,--history 加扫 git 历史)
|
|
13
|
+
brk image <ref> 扫描容器镜像的已知漏洞(需 trivy)
|
|
14
|
+
brk sast [path] 静态代码分析找漏洞(需 semgrep)
|
|
15
|
+
brk mcp 以 MCP server 模式启动(供 Agent 调用)
|
|
16
|
+
brk doctor 检查运行环境与网络连通性
|
|
17
|
+
brk setup 打印把 Break Anything 接入 Agent 的 MCP 配置
|
|
18
|
+
brk --help 显示本帮助
|
|
19
|
+
brk --version 显示版本
|
|
20
|
+
|
|
21
|
+
通用选项:
|
|
22
|
+
--json 输出 JSON(用于脚本 / Agent)
|
|
23
|
+
--no-color 关闭彩色输出
|
|
24
|
+
deps 选项:
|
|
25
|
+
--no-reachability 跳过源码可达性初判
|
|
26
|
+
secrets 选项:
|
|
27
|
+
--history 加扫 git 历史中的密钥
|
|
28
|
+
|
|
29
|
+
范围声明:只对你拥有、或已获得明确授权的目标使用。详见 DISCLAIMER.md。
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
function parseFlags(argv) {
|
|
33
|
+
const flags = {};
|
|
34
|
+
const positional = [];
|
|
35
|
+
for (const a of argv) {
|
|
36
|
+
if (a === "--json") flags.json = true;
|
|
37
|
+
else if (a === "--no-reachability") flags.reachability = false;
|
|
38
|
+
else if (a === "--no-color") flags.color = false;
|
|
39
|
+
else if (a.startsWith("--") && a.includes("=")) { const [k, v] = a.slice(2).split("="); flags[k] = v; }
|
|
40
|
+
else if (a.startsWith("--")) flags[a.slice(2)] = true;
|
|
41
|
+
else positional.push(a);
|
|
42
|
+
}
|
|
43
|
+
return { flags, positional };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function main() {
|
|
47
|
+
const [cmd, ...rest] = process.argv.slice(2);
|
|
48
|
+
|
|
49
|
+
if (!cmd || cmd === "--help" || cmd === "-h" || cmd === "help") {
|
|
50
|
+
process.stdout.write(HELP);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (cmd === "--version" || cmd === "-v") {
|
|
54
|
+
process.stdout.write(VERSION + "\n");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (cmd === "mcp") {
|
|
59
|
+
const { startMcpServer } = await import("../src/mcp.js");
|
|
60
|
+
await startMcpServer();
|
|
61
|
+
return; // 保持进程存活
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (cmd === "deps") {
|
|
65
|
+
const { flags, positional } = parseFlags(rest);
|
|
66
|
+
const target = positional[0] || process.cwd();
|
|
67
|
+
const result = await scanDependencies(target, {
|
|
68
|
+
reachability: flags.reachability !== false,
|
|
69
|
+
});
|
|
70
|
+
if (flags.json) {
|
|
71
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
72
|
+
} else {
|
|
73
|
+
const color = flags.color !== false && process.stdout.isTTY;
|
|
74
|
+
process.stdout.write(renderHuman(result, { color, top: flags.top ? Number(flags.top) : undefined }) + "\n");
|
|
75
|
+
}
|
|
76
|
+
// 有高危且可达的发现时用非零退出码,方便接 CI
|
|
77
|
+
const hasReachableHigh = result.findings?.some(
|
|
78
|
+
(f) => f.reachability === "imported" && (f.severity === "CRITICAL" || f.severity === "HIGH"),
|
|
79
|
+
);
|
|
80
|
+
process.exitCode = hasReachableHigh ? 1 : 0;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (cmd === "secrets") {
|
|
85
|
+
const { flags, positional } = parseFlags(rest);
|
|
86
|
+
const target = positional[0] || process.cwd();
|
|
87
|
+
const { scanSecrets } = await import("../src/secrets.js");
|
|
88
|
+
const { renderSecrets } = await import("../src/report.js");
|
|
89
|
+
const result = await scanSecrets(target, { history: !!flags.history });
|
|
90
|
+
if (flags.json) {
|
|
91
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
92
|
+
} else {
|
|
93
|
+
const color = flags.color !== false && process.stdout.isTTY;
|
|
94
|
+
process.stdout.write(renderSecrets(result, { color }) + "\n");
|
|
95
|
+
}
|
|
96
|
+
process.exitCode = result.findings.length ? 1 : 0;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (cmd === "image") {
|
|
101
|
+
const { flags, positional } = parseFlags(rest);
|
|
102
|
+
const ref = positional[0];
|
|
103
|
+
if (!ref) {
|
|
104
|
+
process.stderr.write("用法:brk image <镜像引用>,例如 brk image nginx:1.21\n");
|
|
105
|
+
process.exitCode = 2;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const { scanImage } = await import("../src/image.js");
|
|
109
|
+
const { renderImage } = await import("../src/report.js");
|
|
110
|
+
const result = await scanImage(ref);
|
|
111
|
+
if (flags.json) {
|
|
112
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
113
|
+
} else {
|
|
114
|
+
const color = flags.color !== false && process.stdout.isTTY;
|
|
115
|
+
process.stdout.write(renderImage(result, { color }) + "\n");
|
|
116
|
+
}
|
|
117
|
+
const hasHigh = result.findings?.some((f) => f.severity === "CRITICAL" || f.severity === "HIGH");
|
|
118
|
+
process.exitCode = hasHigh ? 1 : 0;
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (cmd === "sast") {
|
|
123
|
+
const { flags, positional } = parseFlags(rest);
|
|
124
|
+
const target = positional[0] || process.cwd();
|
|
125
|
+
const { scanSast } = await import("../src/sast.js");
|
|
126
|
+
const { renderSast } = await import("../src/report.js");
|
|
127
|
+
const result = await scanSast(target, flags.config ? { config: flags.config } : {});
|
|
128
|
+
if (flags.json) {
|
|
129
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
130
|
+
} else {
|
|
131
|
+
const color = flags.color !== false && process.stdout.isTTY;
|
|
132
|
+
process.stdout.write(renderSast(result, { color, top: flags.top ? Number(flags.top) : undefined }) + "\n");
|
|
133
|
+
}
|
|
134
|
+
const hasHigh = result.findings?.some((f) => f.severity === "CRITICAL" || f.severity === "HIGH");
|
|
135
|
+
process.exitCode = hasHigh ? 1 : 0;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (cmd === "doctor") {
|
|
140
|
+
await doctor();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (cmd === "setup") {
|
|
145
|
+
printSetup();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
process.stderr.write(`未知命令:${cmd}\n\n${HELP}`);
|
|
150
|
+
process.exitCode = 2;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function doctor() {
|
|
154
|
+
const out = [];
|
|
155
|
+
const [maj] = process.versions.node.split(".").map(Number);
|
|
156
|
+
out.push(`Node.js ${process.versions.node} ${maj >= 18 ? "✓" : "✗ 需要 >= 18.17"}`);
|
|
157
|
+
try {
|
|
158
|
+
const { fetchJson } = await import("../src/http.js");
|
|
159
|
+
await fetchJson("https://api.osv.dev/v1/query", {
|
|
160
|
+
method: "POST",
|
|
161
|
+
body: { version: "4.17.4", package: { name: "lodash", ecosystem: "npm" } },
|
|
162
|
+
timeoutMs: 8000,
|
|
163
|
+
});
|
|
164
|
+
out.push("OSV API 可达 ✓");
|
|
165
|
+
} catch (e) {
|
|
166
|
+
out.push(`OSV API 不可达 ✗ (${e instanceof Error ? e.message : e})`);
|
|
167
|
+
}
|
|
168
|
+
process.stdout.write(out.join("\n") + "\n");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function printSetup() {
|
|
172
|
+
const config = {
|
|
173
|
+
mcpServers: {
|
|
174
|
+
"break-anything": { command: "npx", args: ["-y", "break-anything", "mcp"] },
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
process.stdout.write(
|
|
178
|
+
"把下面的配置加入你的 MCP 客户端(Claude Code / Cursor / Codex 等):\n\n" +
|
|
179
|
+
JSON.stringify(config, null, 2) +
|
|
180
|
+
"\n\n然后重启 Agent,对它说:用 Break Anything 扫描我的项目依赖。\n",
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
main().catch((err) => {
|
|
185
|
+
process.stderr.write(`错误:${err instanceof Error ? err.stack || err.message : String(err)}\n`);
|
|
186
|
+
process.exitCode = 1;
|
|
187
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 360" font-family="-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
4
|
+
<path d="M0,0 L8,3 L0,6 Z" fill="#8b93a7"/>
|
|
5
|
+
</marker>
|
|
6
|
+
<style>
|
|
7
|
+
.box{rx:12;ry:12;stroke-width:1.5;}
|
|
8
|
+
.t{fill:#0f1222;font-size:15px;font-weight:600;}
|
|
9
|
+
.s{fill:#5b6478;font-size:12px;}
|
|
10
|
+
.lbl{fill:#8b93a7;font-size:11px;}
|
|
11
|
+
</style>
|
|
12
|
+
</defs>
|
|
13
|
+
|
|
14
|
+
<rect x="24" y="140" width="180" height="80" class="box" fill="#eef1fb" stroke="#5c4ee5"/>
|
|
15
|
+
<text x="114" y="172" text-anchor="middle" class="t">Coding agent</text>
|
|
16
|
+
<text x="114" y="194" text-anchor="middle" class="s">or your terminal</text>
|
|
17
|
+
|
|
18
|
+
<line x1="204" y1="180" x2="300" y2="180" stroke="#8b93a7" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
19
|
+
|
|
20
|
+
<rect x="304" y="130" width="200" height="100" class="box" fill="#f4f6fd" stroke="#5c4ee5"/>
|
|
21
|
+
<text x="404" y="166" text-anchor="middle" class="t">Break Anything</text>
|
|
22
|
+
<text x="404" y="188" text-anchor="middle" class="s">CLI + MCP</text>
|
|
23
|
+
<text x="404" y="208" text-anchor="middle" class="s">capability router</text>
|
|
24
|
+
|
|
25
|
+
<line x1="504" y1="180" x2="600" y2="180" stroke="#8b93a7" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
26
|
+
|
|
27
|
+
<rect x="604" y="40" width="200" height="56" class="box" fill="#fff" stroke="#c7ccda"/>
|
|
28
|
+
<text x="704" y="66" text-anchor="middle" class="t">Dependencies</text>
|
|
29
|
+
<text x="704" y="84" text-anchor="middle" class="lbl">OSV · GHSA · EPSS · KEV</text>
|
|
30
|
+
|
|
31
|
+
<rect x="604" y="110" width="200" height="56" class="box" fill="#fff" stroke="#c7ccda"/>
|
|
32
|
+
<text x="704" y="136" text-anchor="middle" class="t">Source (SAST)</text>
|
|
33
|
+
<text x="704" y="154" text-anchor="middle" class="lbl">Semgrep · CodeQL · gitleaks</text>
|
|
34
|
+
|
|
35
|
+
<rect x="604" y="180" width="200" height="56" class="box" fill="#fff" stroke="#c7ccda"/>
|
|
36
|
+
<text x="704" y="206" text-anchor="middle" class="t">Running app (DAST)</text>
|
|
37
|
+
<text x="704" y="224" text-anchor="middle" class="lbl">ZAP · Nuclei · API tests</text>
|
|
38
|
+
|
|
39
|
+
<rect x="604" y="250" width="200" height="56" class="box" fill="#fff" stroke="#c7ccda"/>
|
|
40
|
+
<text x="704" y="276" text-anchor="middle" class="t">Images · IaC</text>
|
|
41
|
+
<text x="704" y="294" text-anchor="middle" class="lbl">Trivy · Grype · checkov</text>
|
|
42
|
+
|
|
43
|
+
<line x1="804" y1="68" x2="900" y2="150" stroke="#8b93a7" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
44
|
+
<line x1="804" y1="138" x2="900" y2="168" stroke="#8b93a7" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
45
|
+
<line x1="804" y1="208" x2="900" y2="190" stroke="#8b93a7" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
46
|
+
<line x1="804" y1="278" x2="900" y2="210" stroke="#8b93a7" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
47
|
+
|
|
48
|
+
<rect x="904" y="130" width="250" height="100" class="box" fill="#eafaf0" stroke="#1f9d57"/>
|
|
49
|
+
<text x="1029" y="162" text-anchor="middle" class="t">Findings + evidence</text>
|
|
50
|
+
<text x="1029" y="184" text-anchor="middle" class="s">reachability · PoC on your target</text>
|
|
51
|
+
<text x="1029" y="206" text-anchor="middle" class="s">→ fix plan / Patch Anything</text>
|
|
52
|
+
|
|
53
|
+
<text x="590" y="332" text-anchor="middle" class="lbl">Authorized targets only — software you own or are explicitly permitted to test</text>
|
|
54
|
+
</svg>
|
|
Binary file
|
package/docs/hero-gif.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Hero GIF — how it's made
|
|
2
|
+
|
|
3
|
+
The README's first image. Short (~12s), tight, cool, real tool output. Generated with
|
|
4
|
+
[VHS](https://github.com/charmbracelet/vhs) from a repeatable script.
|
|
5
|
+
|
|
6
|
+
## What it shows
|
|
7
|
+
|
|
8
|
+
Two beats:
|
|
9
|
+
|
|
10
|
+
1. **Dependencies** — `brk deps` plays a quick scanning animation, then snaps the real top
|
|
11
|
+
findings for an old `lodash`/`minimist`: two CRITICALs + a HIGH at 21.3% EPSS, each tagged
|
|
12
|
+
`reachable`, with fix versions, over a bold `12 findings · 10 reachable` summary.
|
|
13
|
+
2. **Secrets** — `brk secrets --history` finds an AWS key removed from the code but still in git
|
|
14
|
+
history, pinned to the commit, with the "rotate, don't just delete" warning.
|
|
15
|
+
|
|
16
|
+
Outro: `# find -> prove -> fix npx break-anything`.
|
|
17
|
+
|
|
18
|
+
## Why the deps output is pre-captured
|
|
19
|
+
|
|
20
|
+
The `deps` scan hits the OSV network, which adds several seconds of dead air to a recording. So
|
|
21
|
+
the real colored output is captured once, off-camera, and replayed instantly behind a scanning
|
|
22
|
+
animation — the data is genuine, the GIF stays tight.
|
|
23
|
+
|
|
24
|
+
Re-capture it (real, colored, top 3) any time:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
script -q demos/.hero/deps.ansi node bin/brk.js deps demos/sample-npm --top=3
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`demos/hero-brk.sh` is the tape's `brk` wrapper: it animates + replays that file for `deps`, and
|
|
31
|
+
runs the real CLI for everything else (`secrets` is local and instant, so it runs live).
|
|
32
|
+
|
|
33
|
+
## Re-render
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
brew install vhs # once
|
|
37
|
+
vhs demos/hero.tape # writes docs/assets/hero.gif
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Tuning
|
|
41
|
+
|
|
42
|
+
- **Look:** `Set Theme / FontSize / Width / Height / WindowBar / MarginFill / BorderRadius` at the
|
|
43
|
+
top of [`demos/hero.tape`](../demos/hero.tape).
|
|
44
|
+
- **Findings shown:** `--top=N` in the capture command (and the real CLI).
|
|
45
|
+
- **Avoid `→` in `Type` lines** — VHS can drop the multibyte arrow; use `->`. Arrows inside the
|
|
46
|
+
captured `deps.ansi` render fine.
|
|
47
|
+
|
|
48
|
+
## Guardrails
|
|
49
|
+
|
|
50
|
+
- Every target is a sample project or a throwaway repo you own — never a third party.
|
|
51
|
+
- The CVEs and EPSS numbers are real (captured from a live OSV / FIRST.org scan). Don't fake them.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Installation and setup
|
|
2
|
+
|
|
3
|
+
## Requirements
|
|
4
|
+
|
|
5
|
+
- Node.js 22.19+ and npm
|
|
6
|
+
- macOS, Linux, or Windows (WSL recommended on Windows for dynamic tools)
|
|
7
|
+
- Optional analysis engines depending on the target (see below)
|
|
8
|
+
|
|
9
|
+
## Set up your agent
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx break-anything setup
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Setup detects installed agents, prints every proposed change, backs up existing configuration,
|
|
16
|
+
and asks before applying anything. Supported agents:
|
|
17
|
+
|
|
18
|
+
- Claude Code
|
|
19
|
+
- Claude Desktop
|
|
20
|
+
- Codex
|
|
21
|
+
- Cursor
|
|
22
|
+
- Gemini CLI
|
|
23
|
+
- Windsurf
|
|
24
|
+
|
|
25
|
+
Any other client that can run a local MCP server can use the
|
|
26
|
+
[manual registration](mcp-tools.md#manual-mcp-registration).
|
|
27
|
+
|
|
28
|
+
## Install the CLI
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install --global break-anything
|
|
32
|
+
brk --help
|
|
33
|
+
brk doctor
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`brk doctor` is read-only. It reports which optional engines are present and which capabilities
|
|
37
|
+
are therefore available.
|
|
38
|
+
|
|
39
|
+
## Optional analysis engines
|
|
40
|
+
|
|
41
|
+
Break Anything orchestrates tools you already trust. It does not bundle or re-license them.
|
|
42
|
+
|
|
43
|
+
| Capability | Engine | Install |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| Dependency CVEs | OSV database | built-in (queries OSV.dev) |
|
|
46
|
+
| SAST | Semgrep | `pipx install semgrep` |
|
|
47
|
+
| SAST (deep) | CodeQL | CodeQL CLI from GitHub |
|
|
48
|
+
| Secrets | gitleaks | `brew install gitleaks` |
|
|
49
|
+
| Images / IaC | Trivy | `brew install trivy` |
|
|
50
|
+
| Images (second opinion) | Grype | `brew install grype` |
|
|
51
|
+
| Dynamic web | OWASP ZAP | ZAP desktop or `zaproxy` |
|
|
52
|
+
| Templates | Nuclei | `brew install nuclei` |
|
|
53
|
+
| Smart contracts | Slither | `pipx install slither-analyzer` |
|
|
54
|
+
|
|
55
|
+
## Enable dynamic (running-app) capabilities
|
|
56
|
+
|
|
57
|
+
Dynamic tools are off by default. To test your own running app or API:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
export BRK_DYNAMIC_ENABLED=true
|
|
61
|
+
export BRK_AUTHORIZED_TARGETS_JSON='["http://localhost:3000"]'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Dynamic tools refuse any target not in the allowlist. See [DISCLAIMER.md](../DISCLAIMER.md).
|
|
65
|
+
|
|
66
|
+
## Uninstall
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
brk uninstall # remove MCP registrations + managed skill
|
|
70
|
+
brk uninstall --purge # also remove ~/.brk cache and state
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Uninstall preserves your other MCP servers, your installed engines, and your evidence bundles.
|