brainblast 0.2.0 → 0.4.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/README.md +73 -15
- package/dist/chunk-WVHGN2HR.js +1812 -0
- package/dist/cli.js +171 -7
- package/dist/index.d.ts +230 -2
- package/dist/index.js +39 -1
- package/dist/programs/directory.yaml +179 -0
- package/dist/rules/anchor-init-if-needed-guarded.yaml +47 -0
- package/dist/rules/bags-fee-share-creator-included.yaml +6 -1
- package/dist/rules/metaplex-metadata-immutable.yaml +55 -0
- package/dist/rules/privy-jwt-verification.yaml +18 -2
- package/dist/rules/stripe-webhook-raw-body.yaml +5 -0
- package/dist/rules/token-2022-program-id-pinned.yaml +55 -0
- package/package.json +50 -9
- package/dist/chunk-H2Y75CSH.js +0 -494
package/README.md
CHANGED
|
@@ -9,25 +9,64 @@ parses your code statically and runs offline.
|
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
11
|
npx brainblast . # scan the repo, write .agent-research/report.json
|
|
12
|
-
npx brainblast . --ci # exit 1 if a confirmed
|
|
12
|
+
npx brainblast . --ci # exit 1 if a confirmed FAIL remains
|
|
13
13
|
npx brainblast . --ci --strict # also fail on CANT_TELL (can't statically prove)
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
Exit codes: **0** clean · **1** a confirmed FAIL
|
|
17
|
-
|
|
16
|
+
Exit codes: **0** clean · **1** a confirmed FAIL · CANT_TELL is a warning by
|
|
17
|
+
default (a red build always means a real, confirmed problem).
|
|
18
18
|
|
|
19
|
-
## What it catches
|
|
19
|
+
## What it catches
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
forged `payment_intent.succeeded` events accepted.
|
|
23
|
-
- **Privy / JWT** access tokens decoded without verifying the signature, or
|
|
24
|
-
without asserting `aud` + `iss` → auth bypass / cross-app token reuse.
|
|
25
|
-
- **Bags (Solana token launch)** fee-share configs that omit the creator from
|
|
26
|
-
`feeClaimers`, or whose `userBps` don't sum to 10000 → the creator earns **zero
|
|
27
|
-
fees forever** (the config is immutable on-chain after launch).
|
|
21
|
+
### Web2 / Node.js
|
|
28
22
|
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
| Rule | What's wrong | Consequence |
|
|
24
|
+
|------|--------------|-------------|
|
|
25
|
+
| `stripe-webhook-raw-body` | `constructEvent` called on the parsed body, not the raw buffer | Any `payment_intent.succeeded` can be forged |
|
|
26
|
+
| `privy-jwt-verification` | JWT decoded without signature verification, or without `aud`+`iss` claims | Auth bypass / cross-app token reuse |
|
|
27
|
+
|
|
28
|
+
### Solana / Anchor (TypeScript + Rust)
|
|
29
|
+
|
|
30
|
+
| Rule | What's wrong | Consequence |
|
|
31
|
+
|------|--------------|-------------|
|
|
32
|
+
| `bags-fee-share-creator-included` | Creator wallet omitted from `feeClaimers`, or `userBps` don't sum to 10000 | Creator earns zero fees forever — the config is immutable on-chain |
|
|
33
|
+
| `token-2022-program-id-pinned` | `createMint` passes the legacy `TOKEN_PROGRAM_ID` where Token-2022 was intended | Mint is owned by the wrong program; Token-2022 features (transfer hooks, fees, confidential transfers) are silently absent with no on-chain fix |
|
|
34
|
+
| `metaplex-metadata-immutable` | `createV1` / `createNft` omits `isMutable: false` | Metadata defaults to mutable; any update authority can change the token's name, image, or attributes after launch |
|
|
35
|
+
| `anchor-init-if-needed-guarded` | Anchor instruction uses `init_if_needed` without a re-initialization guard | Any user can reinitialize another user's account, overwriting its state |
|
|
36
|
+
|
|
37
|
+
Each finding lands in `.agent-research/report.json` (stable `schemaVersion: "1.0"`)
|
|
38
|
+
with a `checks[]` array a CI gate can read. Each confirmed FAIL ships a
|
|
39
|
+
generated behavioral test (RED on vulnerable, GREEN on fixed).
|
|
40
|
+
|
|
41
|
+
## Cost & Rent Analysis
|
|
42
|
+
|
|
43
|
+
Every run also produces `.agent-research/cost-analysis.md` — a breakdown of
|
|
44
|
+
rent-exempt lamport lockups, scalable flows (calls inside loops that grow with N),
|
|
45
|
+
and a priority-fee posture check:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
── Cost & Rent ──────────────────────────────────────────────
|
|
49
|
+
[HIGH ] priority fee not configured — add setComputeUnitPrice to critical paths
|
|
50
|
+
Metaplex Token Metadata src/mint.ts:42 +5,312,760 lamports (0.00531276 SOL) [non-recoverable]
|
|
51
|
+
─── static lockup total: 5,312,760 lamports (~0.00531276 SOL)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Trust Graph
|
|
55
|
+
|
|
56
|
+
Resolve on-chain upgrade-authority and verified-build status for any Solana
|
|
57
|
+
program:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
npx brainblast trust-graph TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
|
|
61
|
+
npx brainblast trust-graph <id1> <id2> --rpc https://api.mainnet-beta.solana.com
|
|
62
|
+
npx brainblast trust-graph <id> --no-probe # directory + cache only, no RPC
|
|
63
|
+
npx brainblast trust-graph <id> --json # machine-readable output
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Program metadata is cached in `~/.brainblast/program-cache.json` (keyed by
|
|
67
|
+
program ID, TTL 1 week). A program researched for one project pre-populates
|
|
68
|
+
all future runs — no repeat RPC probes needed. Override with
|
|
69
|
+
`BRAINBLAST_CACHE_PATH` or pass `--no-cache` to skip entirely.
|
|
31
70
|
|
|
32
71
|
## Rules are data
|
|
33
72
|
|
|
@@ -40,10 +79,27 @@ bundled ones). Invalid rules are rejected at load.
|
|
|
40
79
|
## Library API
|
|
41
80
|
|
|
42
81
|
```ts
|
|
43
|
-
import {
|
|
82
|
+
import {
|
|
83
|
+
audit, resolveRules,
|
|
84
|
+
analyzeCosts, renderCostReportMd,
|
|
85
|
+
buildTrustGraph,
|
|
86
|
+
loadProgramCache, getCacheEntry,
|
|
87
|
+
} from "brainblast";
|
|
88
|
+
|
|
89
|
+
// Static audit
|
|
44
90
|
const { checks, report } = audit(process.cwd(), resolveRules(process.cwd()));
|
|
91
|
+
|
|
92
|
+
// Cost analysis
|
|
93
|
+
const costReport = analyzeCosts(process.cwd());
|
|
94
|
+
console.log(renderCostReportMd(costReport));
|
|
95
|
+
|
|
96
|
+
// Trust graph (program-keyed cache is consulted automatically)
|
|
97
|
+
const graph = await buildTrustGraph(["TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"]);
|
|
45
98
|
```
|
|
46
99
|
|
|
100
|
+
All types are exported: `Rule`, `CheckResult`, `CostReport`, `AccountFlow`,
|
|
101
|
+
`OnChainProgram`, `TrustGraph`, `ProgramCache`, and more.
|
|
102
|
+
|
|
47
103
|
## Security model
|
|
48
104
|
|
|
49
105
|
- **The audit is static.** `brainblast <dir>` parses source with ts-morph and
|
|
@@ -53,12 +109,14 @@ const { checks, report } = audit(process.cwd(), resolveRules(process.cwd()));
|
|
|
53
109
|
them.** That's expected when you audit your own repo. If you run brainblast on
|
|
54
110
|
untrusted code (e.g. a fork PR) and then run the generated tests, run them in a
|
|
55
111
|
sandbox — the same caution as running any untrusted test suite.
|
|
112
|
+
- **Trust-graph RPC probes are read-only.** `getAccountInfo` calls only; no
|
|
113
|
+
transactions are sent.
|
|
56
114
|
|
|
57
115
|
## Develop
|
|
58
116
|
|
|
59
117
|
```sh
|
|
60
118
|
npm install
|
|
61
|
-
npm test # unit suite
|
|
119
|
+
npm test # unit suite (135 tests)
|
|
62
120
|
npm run prove # end-to-end: generated tests RED on vulnerable, GREEN on fixed
|
|
63
121
|
npm run build # produce dist/ (the published artifact)
|
|
64
122
|
```
|