brainblast 0.2.0 → 0.3.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-BZVZ3WAU.js +1659 -0
- package/dist/cli.js +68 -2
- package/dist/index.d.ts +200 -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 +5 -1
- package/dist/rules/token-2022-program-id-pinned.yaml +55 -0
- package/package.json +50 -9
- package/dist/chunk-H2Y75CSH.js +0 -494
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Pure-data rule (facts). Binds to vetted templates by `check.kind`/`test.kind`.
|
|
2
|
+
# Promoted from findings/metaplex-metadata-immutable.json after the
|
|
3
|
+
# proof-as-classifier loop (synth-prove) closed RED->GREEN against the
|
|
4
|
+
# new `object-arg-property-literal-equals` checker kind.
|
|
5
|
+
id: metaplex-metadata-immutable
|
|
6
|
+
severity: critical
|
|
7
|
+
title: Metaplex createV1 called with isMutable false to seal token metadata at mint
|
|
8
|
+
component:
|
|
9
|
+
name: Metaplex Token Metadata
|
|
10
|
+
type: Blockchain
|
|
11
|
+
version: unversioned
|
|
12
|
+
sourceUrl: https://developers.metaplex.com/token-metadata
|
|
13
|
+
detect:
|
|
14
|
+
modules: ["@metaplex-foundation/mpl-token-metadata"]
|
|
15
|
+
# Brand-specific terms only. Bare "token"/"mint" cross-match SPL-token,
|
|
16
|
+
# Bags, and other handlers. Metaplex candidates still resolve via the
|
|
17
|
+
# @metaplex-foundation/mpl-token-metadata import or the createV1/createNft
|
|
18
|
+
# trigger calls.
|
|
19
|
+
nameRegex: "metaplex|mpl|createNft"
|
|
20
|
+
triggerCalls: [createV1, createNft, createAndMint, createMetadataAccountV3]
|
|
21
|
+
check:
|
|
22
|
+
kind: object-arg-property-literal-equals
|
|
23
|
+
params:
|
|
24
|
+
call: createV1
|
|
25
|
+
argIndex: 1
|
|
26
|
+
propName: isMutable
|
|
27
|
+
expectedValue: false
|
|
28
|
+
passDetail: >-
|
|
29
|
+
createV1 passes isMutable: false — token metadata is permanently sealed
|
|
30
|
+
at mint time. Name, symbol, and URI cannot be changed regardless of who
|
|
31
|
+
holds the update authority.
|
|
32
|
+
failAbsentDetail: >-
|
|
33
|
+
createV1 omits isMutable (SDK defaults to true). The update authority
|
|
34
|
+
retains the ability to change the token name, symbol, and URI after mint —
|
|
35
|
+
permanently. Seal the metadata by passing isMutable: false. There is no
|
|
36
|
+
on-chain migration path once metadata is minted as mutable.
|
|
37
|
+
failWrongDetail: >-
|
|
38
|
+
createV1 passes isMutable: true explicitly. Token metadata will remain
|
|
39
|
+
mutable after mint — the update authority key becomes a permanent attack
|
|
40
|
+
surface. Pass isMutable: false to seal it at mint time.
|
|
41
|
+
failArgDetail: >-
|
|
42
|
+
createV1's options argument is not an inline object literal; cannot
|
|
43
|
+
statically verify isMutable. Inline the options object so static analysis
|
|
44
|
+
can confirm isMutable: false.
|
|
45
|
+
failDynamicDetail: >-
|
|
46
|
+
isMutable is set via a variable or expression; cannot confirm it resolves
|
|
47
|
+
to false statically. Use the boolean literal false directly.
|
|
48
|
+
absentCallDetail: >-
|
|
49
|
+
Handler is in Metaplex scope but does not call createV1; the
|
|
50
|
+
metadata-immutability rule does not apply here.
|
|
51
|
+
scopeNotMetDetail: >-
|
|
52
|
+
File does not import from @metaplex-foundation/mpl-token-metadata; the
|
|
53
|
+
metadata-immutability rule does not apply.
|
|
54
|
+
test:
|
|
55
|
+
kind: metaplex-immutable-metadata
|
|
@@ -9,7 +9,11 @@ component:
|
|
|
9
9
|
sourceUrl: https://docs.privy.io/authentication/user-authentication/access-tokens
|
|
10
10
|
detect:
|
|
11
11
|
modules: [jose, jsonwebtoken, "@privy-io/node", "@privy-io/server-auth"]
|
|
12
|
-
|
|
12
|
+
# Brand-specific terms only. Bare "token"/"auth" cross-match unrelated
|
|
13
|
+
# Solana handlers (launchToken, etc.) and produce spurious cant_tell noise.
|
|
14
|
+
# Privy handlers are still picked up by the @privy-io/* / jose / jsonwebtoken
|
|
15
|
+
# imports, and by triggerCalls like decodeJwt / jwtVerify.
|
|
16
|
+
nameRegex: "privy|jwt"
|
|
13
17
|
triggerCalls: [decodeJwt, jwtVerify, verify, decode]
|
|
14
18
|
check:
|
|
15
19
|
kind: required-call-with-options
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Pure-data rule (facts). Binds to vetted templates by `check.kind`/`test.kind`.
|
|
2
|
+
# Promoted from findings/token-2022-program-id-mismatch.json after the
|
|
3
|
+
# proof-as-classifier loop (synth-prove) closed RED->GREEN against the
|
|
4
|
+
# new `arg-equals-constant-identifier` checker kind.
|
|
5
|
+
id: token-2022-program-id-pinned
|
|
6
|
+
severity: critical
|
|
7
|
+
title: Token-2022 createMint passes TOKEN_2022_PROGRAM_ID as the program ID argument
|
|
8
|
+
component:
|
|
9
|
+
name: SPL Token-2022
|
|
10
|
+
type: Blockchain
|
|
11
|
+
version: unversioned
|
|
12
|
+
sourceUrl: https://spl.solana.com/token-2022
|
|
13
|
+
detect:
|
|
14
|
+
modules: ["@solana/spl-token"]
|
|
15
|
+
# Keep the regex narrow to terms specific to SPL-token-mint construction;
|
|
16
|
+
# bare "token"/"launch" would cross-match unrelated handlers (Privy
|
|
17
|
+
# verifyPrivyToken, etc.). Real Token-2022 handlers still resolve via the
|
|
18
|
+
# @solana/spl-token import or the createMint trigger call.
|
|
19
|
+
nameRegex: "createMint|mint22|token2022"
|
|
20
|
+
triggerCalls: [createMint]
|
|
21
|
+
check:
|
|
22
|
+
kind: arg-equals-constant-identifier
|
|
23
|
+
params:
|
|
24
|
+
call: createMint
|
|
25
|
+
argIndex: 7
|
|
26
|
+
expectedIdentifier: TOKEN_2022_PROGRAM_ID
|
|
27
|
+
forbiddenIdentifiers: [TOKEN_PROGRAM_ID]
|
|
28
|
+
# Scope predicate: only enforce when the file imports TOKEN_2022_PROGRAM_ID.
|
|
29
|
+
# Without this, every legacy-mint codebase would false-positive.
|
|
30
|
+
requireImport: TOKEN_2022_PROGRAM_ID
|
|
31
|
+
passDetail: >-
|
|
32
|
+
createMint passes {expected} as its programId argument — Token-2022
|
|
33
|
+
features will work as designed.
|
|
34
|
+
failForbiddenDetail: >-
|
|
35
|
+
createMint passes {got} (legacy Token program) where Token-2022 was
|
|
36
|
+
intended. The mint will be owned by the legacy program; Token-2022
|
|
37
|
+
features (transfer hooks, transfer fees, confidential transfers) will
|
|
38
|
+
not work and there is NO on-chain fix — a mint's owner program is part
|
|
39
|
+
of its identity.
|
|
40
|
+
failMissingDetail: >-
|
|
41
|
+
createMint omits its programId argument (or passes undefined), which
|
|
42
|
+
silently defaults to the LEGACY Token program even though the file
|
|
43
|
+
imports {expected}. Pass {expected} explicitly.
|
|
44
|
+
failOtherDetail: >-
|
|
45
|
+
createMint passes '{got}' as programId; expected {expected}. If this is
|
|
46
|
+
a custom constant, alias it to {expected} or pass the canonical name so
|
|
47
|
+
the trap detector and downstream readers agree.
|
|
48
|
+
absentCallDetail: >-
|
|
49
|
+
Handler is in the SPL-token scope but does not call createMint; the
|
|
50
|
+
Token-2022 pin rule does not apply here.
|
|
51
|
+
scopeNotMetDetail: >-
|
|
52
|
+
File does not import TOKEN_2022_PROGRAM_ID; legacy-token codebase — the
|
|
53
|
+
Token-2022 pin rule does not apply.
|
|
54
|
+
test:
|
|
55
|
+
kind: token-program-consistency
|
package/package.json
CHANGED
|
@@ -1,35 +1,76 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainblast",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deterministic auditor for catastrophic AI-integration bugs: scan a repo, find the silent money/auth traps, and generate the behavioral test that proves they're fixed.",
|
|
6
|
-
"keywords": [
|
|
6
|
+
"keywords": [
|
|
7
|
+
"security",
|
|
8
|
+
"static-analysis",
|
|
9
|
+
"audit",
|
|
10
|
+
"stripe",
|
|
11
|
+
"webhook",
|
|
12
|
+
"jwt",
|
|
13
|
+
"solana",
|
|
14
|
+
"anchor",
|
|
15
|
+
"metaplex",
|
|
16
|
+
"token-2022",
|
|
17
|
+
"trust-graph",
|
|
18
|
+
"bags",
|
|
19
|
+
"rent",
|
|
20
|
+
"ci",
|
|
21
|
+
"ai"
|
|
22
|
+
],
|
|
7
23
|
"license": "MIT",
|
|
8
24
|
"author": "DSB-117",
|
|
9
25
|
"homepage": "https://github.com/DSB-117/brainblast/tree/main/packages/core#readme",
|
|
10
|
-
"bugs": {
|
|
11
|
-
|
|
12
|
-
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/DSB-117/brainblast/issues"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/DSB-117/brainblast.git",
|
|
32
|
+
"directory": "packages/core"
|
|
33
|
+
},
|
|
34
|
+
"bin": {
|
|
35
|
+
"brainblast": "dist/cli.js"
|
|
36
|
+
},
|
|
13
37
|
"exports": {
|
|
14
|
-
".": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"import": "./dist/index.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md"
|
|
46
|
+
],
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"provenance": true
|
|
15
53
|
},
|
|
16
|
-
"files": ["dist", "README.md"],
|
|
17
|
-
"engines": { "node": ">=18" },
|
|
18
|
-
"publishConfig": { "access": "public", "provenance": true },
|
|
19
54
|
"scripts": {
|
|
20
55
|
"build": "tsup",
|
|
21
56
|
"prepublishOnly": "npm run typecheck && npm test && npm run build",
|
|
22
57
|
"audit": "tsx src/cli.ts",
|
|
23
58
|
"prove": "tsx scripts/prove.ts",
|
|
59
|
+
"synth": "tsx scripts/synth-prove.ts",
|
|
60
|
+
"synth:bags": "tsx scripts/synth-prove.ts findings/bags-known-answer.json",
|
|
24
61
|
"test": "vitest run",
|
|
25
62
|
"coverage": "vitest run --coverage",
|
|
26
63
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
27
64
|
},
|
|
28
65
|
"dependencies": {
|
|
66
|
+
"tree-sitter": "^0.22.4",
|
|
67
|
+
"tree-sitter-rust": "^0.24.0",
|
|
29
68
|
"ts-morph": "^23",
|
|
30
69
|
"yaml": "^2"
|
|
31
70
|
},
|
|
32
71
|
"devDependencies": {
|
|
72
|
+
"@metaplex-foundation/mpl-token-metadata": "^3.4.0",
|
|
73
|
+
"@solana/spl-token": "^0.4.14",
|
|
33
74
|
"@types/node": "^22",
|
|
34
75
|
"@vitest/coverage-v8": "^2",
|
|
35
76
|
"jose": "^5",
|