@trynullsec/s1-zk 1.0.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/LIMITATIONS.md +17 -0
- package/README.md +149 -0
- package/ROADMAP.md +21 -0
- package/RULES.md +229 -0
- package/benchmarks/historical/orchard-inspired/partial-ec-mul-halo2.rs +53 -0
- package/benchmarks/historical/orchard-inspired/safe-ec-mul-halo2.rs +69 -0
- package/dist/ai/prompt-builder.d.ts +2 -0
- package/dist/ai/prompt-builder.js +33 -0
- package/dist/ai/prompt-builder.js.map +1 -0
- package/dist/ai/reasoning-interface.d.ts +15 -0
- package/dist/ai/reasoning-interface.js +2 -0
- package/dist/ai/reasoning-interface.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +71 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.js +41 -0
- package/dist/config.js.map +1 -0
- package/dist/core/audit-engine.d.ts +3 -0
- package/dist/core/audit-engine.js +31 -0
- package/dist/core/audit-engine.js.map +1 -0
- package/dist/core/file-loader.d.ts +6 -0
- package/dist/core/file-loader.js +28 -0
- package/dist/core/file-loader.js.map +1 -0
- package/dist/core/issue-builder.d.ts +16 -0
- package/dist/core/issue-builder.js +27 -0
- package/dist/core/issue-builder.js.map +1 -0
- package/dist/core/range-check-classifier.d.ts +16 -0
- package/dist/core/range-check-classifier.js +194 -0
- package/dist/core/range-check-classifier.js.map +1 -0
- package/dist/core/rule-engine.d.ts +10 -0
- package/dist/core/rule-engine.js +41 -0
- package/dist/core/rule-engine.js.map +1 -0
- package/dist/core/severity.d.ts +6 -0
- package/dist/core/severity.js +21 -0
- package/dist/core/severity.js.map +1 -0
- package/dist/core/source-map.d.ts +3 -0
- package/dist/core/source-map.js +16 -0
- package/dist/core/source-map.js.map +1 -0
- package/dist/frontends/circom/circom-comments.d.ts +8 -0
- package/dist/frontends/circom/circom-comments.js +52 -0
- package/dist/frontends/circom/circom-comments.js.map +1 -0
- package/dist/frontends/circom/circom-ir-builder.d.ts +2 -0
- package/dist/frontends/circom/circom-ir-builder.js +12 -0
- package/dist/frontends/circom/circom-ir-builder.js.map +1 -0
- package/dist/frontends/circom/circom-parser.d.ts +2 -0
- package/dist/frontends/circom/circom-parser.js +218 -0
- package/dist/frontends/circom/circom-parser.js.map +1 -0
- package/dist/frontends/circom/circom-tokenizer.d.ts +7 -0
- package/dist/frontends/circom/circom-tokenizer.js +79 -0
- package/dist/frontends/circom/circom-tokenizer.js.map +1 -0
- package/dist/frontends/circom/circom-utils.d.ts +9 -0
- package/dist/frontends/circom/circom-utils.js +88 -0
- package/dist/frontends/circom/circom-utils.js.map +1 -0
- package/dist/frontends/gnark/gnark-adapter.d.ts +5 -0
- package/dist/frontends/gnark/gnark-adapter.js +7 -0
- package/dist/frontends/gnark/gnark-adapter.js.map +1 -0
- package/dist/frontends/halo2/halo2-adapter.d.ts +8 -0
- package/dist/frontends/halo2/halo2-adapter.js +12 -0
- package/dist/frontends/halo2/halo2-adapter.js.map +1 -0
- package/dist/frontends/halo2/halo2-constraint-extractor.d.ts +29 -0
- package/dist/frontends/halo2/halo2-constraint-extractor.js +38 -0
- package/dist/frontends/halo2/halo2-constraint-extractor.js.map +1 -0
- package/dist/frontends/halo2/halo2-constraint-graph.d.ts +16 -0
- package/dist/frontends/halo2/halo2-constraint-graph.js +96 -0
- package/dist/frontends/halo2/halo2-constraint-graph.js.map +1 -0
- package/dist/frontends/halo2/halo2-dataflow.d.ts +11 -0
- package/dist/frontends/halo2/halo2-dataflow.js +19 -0
- package/dist/frontends/halo2/halo2-dataflow.js.map +1 -0
- package/dist/frontends/halo2/halo2-expression-parser.d.ts +14 -0
- package/dist/frontends/halo2/halo2-expression-parser.js +62 -0
- package/dist/frontends/halo2/halo2-expression-parser.js.map +1 -0
- package/dist/frontends/halo2/halo2-ir-builder.d.ts +2 -0
- package/dist/frontends/halo2/halo2-ir-builder.js +17 -0
- package/dist/frontends/halo2/halo2-ir-builder.js.map +1 -0
- package/dist/frontends/halo2/halo2-parser.d.ts +2 -0
- package/dist/frontends/halo2/halo2-parser.js +316 -0
- package/dist/frontends/halo2/halo2-parser.js.map +1 -0
- package/dist/frontends/halo2/halo2-patterns.d.ts +6 -0
- package/dist/frontends/halo2/halo2-patterns.js +54 -0
- package/dist/frontends/halo2/halo2-patterns.js.map +1 -0
- package/dist/frontends/halo2/halo2-types.d.ts +100 -0
- package/dist/frontends/halo2/halo2-types.js +2 -0
- package/dist/frontends/halo2/halo2-types.js.map +1 -0
- package/dist/frontends/noir/noir-adapter.d.ts +5 -0
- package/dist/frontends/noir/noir-adapter.js +7 -0
- package/dist/frontends/noir/noir-adapter.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/ir/circuit-ir.d.ts +1 -0
- package/dist/ir/circuit-ir.js +2 -0
- package/dist/ir/circuit-ir.js.map +1 -0
- package/dist/ir/component-table.d.ts +6 -0
- package/dist/ir/component-table.js +11 -0
- package/dist/ir/component-table.js.map +1 -0
- package/dist/ir/constraint-graph.d.ts +26 -0
- package/dist/ir/constraint-graph.js +130 -0
- package/dist/ir/constraint-graph.js.map +1 -0
- package/dist/ir/dataflow.d.ts +3 -0
- package/dist/ir/dataflow.js +10 -0
- package/dist/ir/dataflow.js.map +1 -0
- package/dist/ir/reference-index.d.ts +6 -0
- package/dist/ir/reference-index.js +18 -0
- package/dist/ir/reference-index.js.map +1 -0
- package/dist/ir/signal-table.d.ts +6 -0
- package/dist/ir/signal-table.js +16 -0
- package/dist/ir/signal-table.js.map +1 -0
- package/dist/report/json.d.ts +2 -0
- package/dist/report/json.js +4 -0
- package/dist/report/json.js.map +1 -0
- package/dist/report/markdown.d.ts +2 -0
- package/dist/report/markdown.js +45 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/sarif.d.ts +2 -0
- package/dist/report/sarif.js +52 -0
- package/dist/report/sarif.js.map +1 -0
- package/dist/report/summary.d.ts +2 -0
- package/dist/report/summary.js +7 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/terminal.d.ts +2 -0
- package/dist/report/terminal.js +50 -0
- package/dist/report/terminal.js.map +1 -0
- package/dist/rules/NS-ZK-001-dangerous-hint-assignment.d.ts +2 -0
- package/dist/rules/NS-ZK-001-dangerous-hint-assignment.js +27 -0
- package/dist/rules/NS-ZK-001-dangerous-hint-assignment.js.map +1 -0
- package/dist/rules/NS-ZK-002-assigned-but-unconstrained.d.ts +2 -0
- package/dist/rules/NS-ZK-002-assigned-but-unconstrained.js +22 -0
- package/dist/rules/NS-ZK-002-assigned-but-unconstrained.js.map +1 -0
- package/dist/rules/NS-ZK-003-unbound-public-input.d.ts +2 -0
- package/dist/rules/NS-ZK-003-unbound-public-input.js +22 -0
- package/dist/rules/NS-ZK-003-unbound-public-input.js.map +1 -0
- package/dist/rules/NS-ZK-004-unconstrained-output.d.ts +2 -0
- package/dist/rules/NS-ZK-004-unconstrained-output.js +27 -0
- package/dist/rules/NS-ZK-004-unconstrained-output.js.map +1 -0
- package/dist/rules/NS-ZK-005-missing-booleanity.d.ts +2 -0
- package/dist/rules/NS-ZK-005-missing-booleanity.js +26 -0
- package/dist/rules/NS-ZK-005-missing-booleanity.js.map +1 -0
- package/dist/rules/NS-ZK-006-missing-range-check.d.ts +2 -0
- package/dist/rules/NS-ZK-006-missing-range-check.js +32 -0
- package/dist/rules/NS-ZK-006-missing-range-check.js.map +1 -0
- package/dist/rules/NS-ZK-007-unsafe-assertion.d.ts +2 -0
- package/dist/rules/NS-ZK-007-unsafe-assertion.js +24 -0
- package/dist/rules/NS-ZK-007-unsafe-assertion.js.map +1 -0
- package/dist/rules/NS-ZK-008-unsafe-division-or-inverse.d.ts +2 -0
- package/dist/rules/NS-ZK-008-unsafe-division-or-inverse.js +39 -0
- package/dist/rules/NS-ZK-008-unsafe-division-or-inverse.js.map +1 -0
- package/dist/rules/NS-ZK-009-unconstrained-component-output.d.ts +2 -0
- package/dist/rules/NS-ZK-009-unconstrained-component-output.js +25 -0
- package/dist/rules/NS-ZK-009-unconstrained-component-output.js.map +1 -0
- package/dist/rules/NS-ZK-010-alias-overflow-risk.d.ts +2 -0
- package/dist/rules/NS-ZK-010-alias-overflow-risk.js +48 -0
- package/dist/rules/NS-ZK-010-alias-overflow-risk.js.map +1 -0
- package/dist/rules/NS-ZK-011-unused-signal.d.ts +2 -0
- package/dist/rules/NS-ZK-011-unused-signal.js +26 -0
- package/dist/rules/NS-ZK-011-unused-signal.js.map +1 -0
- package/dist/rules/NS-ZK-012-suspicious-selector.d.ts +2 -0
- package/dist/rules/NS-ZK-012-suspicious-selector.js +33 -0
- package/dist/rules/NS-ZK-012-suspicious-selector.js.map +1 -0
- package/dist/rules/halo2/NS-H2-001-assigned-advice-not-constrained.d.ts +2 -0
- package/dist/rules/halo2/NS-H2-001-assigned-advice-not-constrained.js +40 -0
- package/dist/rules/halo2/NS-H2-001-assigned-advice-not-constrained.js.map +1 -0
- package/dist/rules/halo2/NS-H2-002-instance-not-bound.d.ts +2 -0
- package/dist/rules/halo2/NS-H2-002-instance-not-bound.js +32 -0
- package/dist/rules/halo2/NS-H2-002-instance-not-bound.js.map +1 -0
- package/dist/rules/halo2/NS-H2-003-selector-risk.d.ts +2 -0
- package/dist/rules/halo2/NS-H2-003-selector-risk.js +37 -0
- package/dist/rules/halo2/NS-H2-003-selector-risk.js.map +1 -0
- package/dist/rules/halo2/NS-H2-004-unsafe-inverse.d.ts +2 -0
- package/dist/rules/halo2/NS-H2-004-unsafe-inverse.js +43 -0
- package/dist/rules/halo2/NS-H2-004-unsafe-inverse.js.map +1 -0
- package/dist/rules/halo2/NS-H2-005-partial-ec-operation.d.ts +2 -0
- package/dist/rules/halo2/NS-H2-005-partial-ec-operation.js +43 -0
- package/dist/rules/halo2/NS-H2-005-partial-ec-operation.js.map +1 -0
- package/dist/rules/halo2/NS-H2-006-missing-enable-equality.d.ts +2 -0
- package/dist/rules/halo2/NS-H2-006-missing-enable-equality.js +31 -0
- package/dist/rules/halo2/NS-H2-006-missing-enable-equality.js.map +1 -0
- package/dist/rules/halo2/halo2-rule-utils.d.ts +8 -0
- package/dist/rules/halo2/halo2-rule-utils.js +24 -0
- package/dist/rules/halo2/halo2-rule-utils.js.map +1 -0
- package/dist/rules/index.d.ts +2 -0
- package/dist/rules/index.js +39 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/scanner.d.ts +8 -0
- package/dist/scanner.js +52 -0
- package/dist/scanner.js.map +1 -0
- package/dist/types.d.ts +171 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/examples/halo2/safe/bound-instance.rs +23 -0
- package/examples/halo2/safe/constrained-advice.rs +27 -0
- package/examples/halo2/safe/safe-inverse.rs +30 -0
- package/examples/halo2/safe/safe-selector.rs +27 -0
- package/examples/halo2/vulnerable/missing-selector-booleanity.rs +20 -0
- package/examples/halo2/vulnerable/partial-ec-mul.rs +23 -0
- package/examples/halo2/vulnerable/unbound-instance.rs +20 -0
- package/examples/halo2/vulnerable/unconstrained-advice.rs +24 -0
- package/examples/halo2/vulnerable/unsafe-inverse.rs +20 -0
- package/examples/safe/safe-boolean.circom +15 -0
- package/examples/safe/safe-component-output.circom +18 -0
- package/examples/safe/safe-division.circom +14 -0
- package/examples/safe/safe-public-input.circom +15 -0
- package/examples/safe/safe-range-check.circom +16 -0
- package/examples/safe/safe-transfer.circom +19 -0
- package/examples/vulnerable/alias-overflow-risk.circom +12 -0
- package/examples/vulnerable/merkle-selector-bug.circom +12 -0
- package/examples/vulnerable/missing-boolean.circom +11 -0
- package/examples/vulnerable/missing-range-check.circom +11 -0
- package/examples/vulnerable/public-input-not-bound.circom +12 -0
- package/examples/vulnerable/unconstrained-component-output.circom +15 -0
- package/examples/vulnerable/unconstrained-transfer.circom +17 -0
- package/examples/vulnerable/unsafe-assertion.circom +12 -0
- package/examples/vulnerable/unsafe-division.circom +11 -0
- package/package.json +46 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { buildIssue } from "../../core/issue-builder.js";
|
|
2
|
+
import { halo2Graph, hasHalo2 } from "./halo2-rule-utils.js";
|
|
3
|
+
export const halo2InstanceNotBoundRule = {
|
|
4
|
+
id: "NS-H2-002",
|
|
5
|
+
title: "Instance value not bound",
|
|
6
|
+
description: "Detects Halo2 instance/public values that are queried without an obvious constrain_instance binding.",
|
|
7
|
+
defaultSeverity: "HIGH",
|
|
8
|
+
tags: ["halo2", "instance", "public-input"],
|
|
9
|
+
analyze(context) {
|
|
10
|
+
if (!hasHalo2(context))
|
|
11
|
+
return [];
|
|
12
|
+
const graph = halo2Graph(context);
|
|
13
|
+
if (!graph)
|
|
14
|
+
return [];
|
|
15
|
+
return (context.halo2?.queries ?? [])
|
|
16
|
+
.filter((query) => query.queryType === "instance")
|
|
17
|
+
.filter((query) => !graph.instanceQueryIsBound(query.columnName, query.file))
|
|
18
|
+
.map((query) => buildIssue({
|
|
19
|
+
ruleId: "NS-H2-002",
|
|
20
|
+
title: "Instance value not bound",
|
|
21
|
+
severity: "HIGH",
|
|
22
|
+
confidence: "MEDIUM",
|
|
23
|
+
location: query,
|
|
24
|
+
signalName: query.columnName,
|
|
25
|
+
explanation: `The instance column/value \`${query.columnName}\` is queried but no matching constrain_instance binding was found in this file.`,
|
|
26
|
+
impact: "The circuit may read a public instance value without binding an assigned cell to the public statement.",
|
|
27
|
+
suggestedFix: "Use layouter.constrain_instance or an equivalent public input binding for the intended cell and instance row.",
|
|
28
|
+
tags: halo2InstanceNotBoundRule.tags
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=NS-H2-002-instance-not-bound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NS-H2-002-instance-not-bound.js","sourceRoot":"","sources":["../../../src/rules/halo2/NS-H2-002-instance-not-bound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,CAAC,MAAM,yBAAyB,GAAS;IAC7C,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,0BAA0B;IACjC,WAAW,EAAE,sGAAsG;IACnH,eAAe,EAAE,MAAM;IACvB,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC;IAC3C,OAAO,CAAC,OAAO;QACb,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QACtB,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC;aAClC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,UAAU,CAAC;aACjD,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;aAC5E,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACb,UAAU,CAAC;YACT,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,0BAA0B;YACjC,QAAQ,EAAE,MAAM;YAChB,UAAU,EAAE,QAAQ;YACpB,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,WAAW,EAAE,+BAA+B,KAAK,CAAC,UAAU,kFAAkF;YAC9I,MAAM,EAAE,wGAAwG;YAChH,YAAY,EAAE,+GAA+G;YAC7H,IAAI,EAAE,yBAAyB,CAAC,IAAI;SACrC,CAAC,CACH,CAAC;IACN,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { buildIssue } from "../../core/issue-builder.js";
|
|
2
|
+
import { halo2Graph, hasHalo2 } from "./halo2-rule-utils.js";
|
|
3
|
+
export const halo2SelectorRiskRule = {
|
|
4
|
+
id: "NS-H2-003",
|
|
5
|
+
title: "Selector discipline risk",
|
|
6
|
+
description: "Detects selectors used in Halo2 gates without clear enable usage.",
|
|
7
|
+
defaultSeverity: "MEDIUM",
|
|
8
|
+
tags: ["halo2", "selector", "gates"],
|
|
9
|
+
analyze(context) {
|
|
10
|
+
if (!hasHalo2(context))
|
|
11
|
+
return [];
|
|
12
|
+
const graph = halo2Graph(context);
|
|
13
|
+
if (!graph)
|
|
14
|
+
return [];
|
|
15
|
+
return (context.halo2?.selectors ?? [])
|
|
16
|
+
.filter((selector) => selector.usedInGates.length > 0 && !graph.selectorEnabled(selector.name))
|
|
17
|
+
.filter((selector) => graph.selectorUsedAsGateMultiplier(selector.name) || /selector|enable|swap|range|mul|bool|flag|q_/i.test(selector.name))
|
|
18
|
+
.map((selector) => buildIssue({
|
|
19
|
+
ruleId: "NS-H2-003",
|
|
20
|
+
title: "Selector discipline risk",
|
|
21
|
+
severity: selector.usedInGates.length > 1 ? "HIGH" : "MEDIUM",
|
|
22
|
+
confidence: "MEDIUM",
|
|
23
|
+
location: selector,
|
|
24
|
+
signalName: selector.name,
|
|
25
|
+
explanation: `Selector \`${selector.name}\` is queried in a gate and appears to gate a constraint, but no matching selector enable call was found in parsed regions.`,
|
|
26
|
+
impact: "Selectors control when Halo2 gates are active. Missing or unclear selector enable discipline can disable intended constraints.",
|
|
27
|
+
suggestedFix: "Ensure the selector is enabled on every row where the gate must apply and document the selector discipline.",
|
|
28
|
+
tags: halo2SelectorRiskRule.tags,
|
|
29
|
+
metadata: {
|
|
30
|
+
involvedSelector: selector.name,
|
|
31
|
+
usedInGates: selector.usedInGates,
|
|
32
|
+
selectorMultiplier: graph.selectorUsedAsGateMultiplier(selector.name)
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=NS-H2-003-selector-risk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NS-H2-003-selector-risk.js","sourceRoot":"","sources":["../../../src/rules/halo2/NS-H2-003-selector-risk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,CAAC,MAAM,qBAAqB,GAAS;IACzC,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,0BAA0B;IACjC,WAAW,EAAE,mEAAmE;IAChF,eAAe,EAAE,QAAQ;IACzB,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC;IACpC,OAAO,CAAC,OAAO;QACb,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QACtB,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;aACpC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;aAC9F,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,4BAA4B,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,8CAA8C,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;aAC7I,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAChB,UAAU,CAAC;YACT,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,0BAA0B;YACjC,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;YAC7D,UAAU,EAAE,QAAQ;YACpB,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,QAAQ,CAAC,IAAI;YACzB,WAAW,EAAE,cAAc,QAAQ,CAAC,IAAI,6HAA6H;YACrK,MAAM,EAAE,gIAAgI;YACxI,YAAY,EAAE,6GAA6G;YAC3H,IAAI,EAAE,qBAAqB,CAAC,IAAI;YAChC,QAAQ,EAAE;gBACR,gBAAgB,EAAE,QAAQ,CAAC,IAAI;gBAC/B,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,kBAAkB,EAAE,KAAK,CAAC,4BAA4B,CAAC,QAAQ,CAAC,IAAI,CAAC;aACtE;SACF,CAAC,CACH,CAAC;IACN,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { buildIssue } from "../../core/issue-builder.js";
|
|
2
|
+
import { fileHasSafeInverseGuard, hasHalo2 } from "./halo2-rule-utils.js";
|
|
3
|
+
export const halo2UnsafeInverseRule = {
|
|
4
|
+
id: "NS-H2-004",
|
|
5
|
+
title: "Unsafe inverse or division",
|
|
6
|
+
description: "Detects Halo2 Rust inverse/division patterns without an obvious nonzero guard nearby.",
|
|
7
|
+
defaultSeverity: "HIGH",
|
|
8
|
+
tags: ["halo2", "inverse", "division", "nonzero"],
|
|
9
|
+
analyze(context) {
|
|
10
|
+
if (!hasHalo2(context))
|
|
11
|
+
return [];
|
|
12
|
+
const issues = [];
|
|
13
|
+
for (const file of context.halo2?.files ?? []) {
|
|
14
|
+
const lines = file.rawSource.split(/\r?\n/);
|
|
15
|
+
lines.forEach((lineText, index) => {
|
|
16
|
+
if (!/\.invert\s*\(|\.inverse\s*\(|\binvert\s*\(|\binverse\s*\(|\s\/\s/.test(lineText))
|
|
17
|
+
return;
|
|
18
|
+
const location = {
|
|
19
|
+
file: file.filePath,
|
|
20
|
+
line: index + 1,
|
|
21
|
+
column: Math.max(1, lineText.search(/invert|inverse|\//) + 1),
|
|
22
|
+
snippet: lineText.trim()
|
|
23
|
+
};
|
|
24
|
+
const guarded = fileHasSafeInverseGuard(file.filePath, index + 1, context);
|
|
25
|
+
issues.push(buildIssue({
|
|
26
|
+
ruleId: "NS-H2-004",
|
|
27
|
+
title: "Unsafe inverse or division",
|
|
28
|
+
severity: guarded ? "INFO" : "HIGH",
|
|
29
|
+
confidence: guarded ? "LOW" : "MEDIUM",
|
|
30
|
+
location,
|
|
31
|
+
explanation: guarded
|
|
32
|
+
? "This Halo2 Rust code computes an inverse or division near an apparent nonzero guard or inverse relation. Review the guard to ensure both zero and nonzero branches are constrained."
|
|
33
|
+
: "This Halo2 Rust code computes an inverse or division without an obvious nearby nonzero check or safe inversion gadget.",
|
|
34
|
+
impact: "Inversion requires explicit zero handling. Missing guards can leave edge cases underconstrained or incorrectly assigned.",
|
|
35
|
+
suggestedFix: "Add an explicit nonzero constraint, use a vetted IsZero/safe inversion gadget, and constrain both branches.",
|
|
36
|
+
tags: halo2UnsafeInverseRule.tags
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return issues;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=NS-H2-004-unsafe-inverse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NS-H2-004-unsafe-inverse.js","sourceRoot":"","sources":["../../../src/rules/halo2/NS-H2-004-unsafe-inverse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE1E,MAAM,CAAC,MAAM,sBAAsB,GAAS;IAC1C,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,4BAA4B;IACnC,WAAW,EAAE,uFAAuF;IACpG,eAAe,EAAE,MAAM;IACvB,IAAI,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC;IACjD,OAAO,CAAC,OAAO;QACb,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5C,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;gBAChC,IAAI,CAAC,kEAAkE,CAAC,IAAI,CAAC,QAAQ,CAAC;oBAAE,OAAO;gBAC/F,MAAM,QAAQ,GAAG;oBACf,IAAI,EAAE,IAAI,CAAC,QAAQ;oBACnB,IAAI,EAAE,KAAK,GAAG,CAAC;oBACf,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;oBAC7D,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;iBACzB,CAAC;gBACF,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC3E,MAAM,CAAC,IAAI,CACT,UAAU,CAAC;oBACT,MAAM,EAAE,WAAW;oBACnB,KAAK,EAAE,4BAA4B;oBACnC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;oBACnC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ;oBACtC,QAAQ;oBACR,WAAW,EAAE,OAAO;wBAClB,CAAC,CAAC,qLAAqL;wBACvL,CAAC,CAAC,wHAAwH;oBAC5H,MAAM,EAAE,0HAA0H;oBAClI,YAAY,EAAE,6GAA6G;oBAC3H,IAAI,EAAE,sBAAsB,CAAC,IAAI;iBAClC,CAAC,CACH,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { buildIssue } from "../../core/issue-builder.js";
|
|
2
|
+
import { unconstrainedEcAssignments } from "../../frontends/halo2/halo2-dataflow.js";
|
|
3
|
+
import { isEcLikeName } from "../../frontends/halo2/halo2-patterns.js";
|
|
4
|
+
import { halo2Graph, hasHalo2 } from "./halo2-rule-utils.js";
|
|
5
|
+
export const halo2PartialEcOperationRule = {
|
|
6
|
+
id: "NS-H2-005",
|
|
7
|
+
title: "Partial elliptic-curve operation risk",
|
|
8
|
+
description: "Detects EC-related Halo2 assignments that do not appear connected to gates or equality constraints.",
|
|
9
|
+
defaultSeverity: "HIGH",
|
|
10
|
+
tags: ["halo2", "ecc", "orchard", "underconstraint"],
|
|
11
|
+
analyze(context) {
|
|
12
|
+
if (!hasHalo2(context))
|
|
13
|
+
return [];
|
|
14
|
+
const graph = halo2Graph(context);
|
|
15
|
+
if (!graph)
|
|
16
|
+
return [];
|
|
17
|
+
return unconstrainedEcAssignments(graph)
|
|
18
|
+
.filter((flow) => isEcLikeName(`${flow.assignment.expression} ${flow.assignment.target ?? ""}`))
|
|
19
|
+
.map((flow) => {
|
|
20
|
+
const assignment = flow.assignment;
|
|
21
|
+
const node = graph.assignmentNode(assignment);
|
|
22
|
+
return buildIssue({
|
|
23
|
+
ruleId: "NS-H2-005",
|
|
24
|
+
title: "Partial elliptic-curve operation risk",
|
|
25
|
+
severity: "HIGH",
|
|
26
|
+
confidence: /base|scalar|point|accumulator|output|x|y/i.test(`${assignment.label ?? ""} ${assignment.assignedVariable ?? ""}`) ? "HIGH" : "MEDIUM",
|
|
27
|
+
location: assignment,
|
|
28
|
+
signalName: assignment.label ?? assignment.columnName ?? assignment.target,
|
|
29
|
+
explanation: `The assigned advice value \`${assignment.label ?? assignment.columnName ?? "unknown"}\` appears in an elliptic-curve-related region but was not connected to any gate expression, equality constraint, lookup, copy edge, or public instance binding. This may indicate a partially constrained EC gadget.`,
|
|
30
|
+
impact: "Partial elliptic-curve operations can be soundness-critical. Unconstrained coordinates, scalars, or intermediate points may allow invalid curve arithmetic witnesses.",
|
|
31
|
+
suggestedFix: "Ensure every EC intermediate is bound by complete gate constraints, lookups, or equality constraints for the intended group law.",
|
|
32
|
+
tags: halo2PartialEcOperationRule.tags,
|
|
33
|
+
metadata: {
|
|
34
|
+
regionName: node?.region?.name,
|
|
35
|
+
columnName: node?.columnName,
|
|
36
|
+
connectedBy: flow.connections,
|
|
37
|
+
unconnectedValue: assignment.label ?? assignment.assignedVariable ?? assignment.columnName
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=NS-H2-005-partial-ec-operation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NS-H2-005-partial-ec-operation.js","sourceRoot":"","sources":["../../../src/rules/halo2/NS-H2-005-partial-ec-operation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,CAAC,MAAM,2BAA2B,GAAS;IAC/C,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,uCAAuC;IAC9C,WAAW,EAAE,qGAAqG;IAClH,eAAe,EAAE,MAAM;IACvB,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,iBAAiB,CAAC;IACpD,OAAO,CAAC,OAAO;QACb,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QACtB,OAAO,0BAA0B,CAAC,KAAK,CAAC;aACrC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;aAC/F,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;YACnC,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAC9C,OAAO,UAAU,CAAC;gBAChB,MAAM,EAAE,WAAW;gBACnB,KAAK,EAAE,uCAAuC;gBAC9C,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,2CAA2C,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE,IAAI,UAAU,CAAC,gBAAgB,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;gBAClJ,QAAQ,EAAE,UAAU;gBACpB,UAAU,EAAE,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM;gBAC1E,WAAW,EAAE,+BAA+B,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,UAAU,IAAI,SAAS,uNAAuN;gBACzT,MAAM,EAAE,uKAAuK;gBAC/K,YAAY,EAAE,kIAAkI;gBAChJ,IAAI,EAAE,2BAA2B,CAAC,IAAI;gBACtC,QAAQ,EAAE;oBACR,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI;oBAC9B,UAAU,EAAE,IAAI,EAAE,UAAU;oBAC5B,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,gBAAgB,EAAE,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,gBAAgB,IAAI,UAAU,CAAC,UAAU;iBAC3F;aACF,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { buildIssue } from "../../core/issue-builder.js";
|
|
2
|
+
import { halo2Graph, hasHalo2 } from "./halo2-rule-utils.js";
|
|
3
|
+
export const halo2MissingEnableEqualityRule = {
|
|
4
|
+
id: "NS-H2-006",
|
|
5
|
+
title: "Missing enable_equality for copy constraints",
|
|
6
|
+
description: "Detects constrain_equal/copy-like usage on columns without an obvious enable_equality call.",
|
|
7
|
+
defaultSeverity: "MEDIUM",
|
|
8
|
+
tags: ["halo2", "equality", "copy-constraints"],
|
|
9
|
+
analyze(context) {
|
|
10
|
+
if (!hasHalo2(context))
|
|
11
|
+
return [];
|
|
12
|
+
const graph = halo2Graph(context);
|
|
13
|
+
if (!graph)
|
|
14
|
+
return [];
|
|
15
|
+
return (context.halo2?.equalityConstraints ?? [])
|
|
16
|
+
.filter((constraint) => !graph.equalityConstraintHasEnabledColumn(constraint.snippet))
|
|
17
|
+
.map((constraint) => buildIssue({
|
|
18
|
+
ruleId: "NS-H2-006",
|
|
19
|
+
title: "Missing enable_equality for copy constraints",
|
|
20
|
+
severity: "MEDIUM",
|
|
21
|
+
confidence: "MEDIUM",
|
|
22
|
+
location: constraint,
|
|
23
|
+
explanation: "A constrain_equal call was found, but no referenced parsed column has an obvious enable_equality call.",
|
|
24
|
+
impact: "Halo2 copy constraints require equality-enabled columns. Missing enable_equality can indicate broken copy-constraint assumptions or incomplete configuration.",
|
|
25
|
+
suggestedFix: "Call meta.enable_equality for every advice/instance column participating in copy constraints.",
|
|
26
|
+
tags: halo2MissingEnableEqualityRule.tags,
|
|
27
|
+
metadata: { referencedColumns: constraint.referencedColumns }
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=NS-H2-006-missing-enable-equality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NS-H2-006-missing-enable-equality.js","sourceRoot":"","sources":["../../../src/rules/halo2/NS-H2-006-missing-enable-equality.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,CAAC,MAAM,8BAA8B,GAAS;IAClD,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,8CAA8C;IACrD,WAAW,EAAE,6FAA6F;IAC1G,eAAe,EAAE,QAAQ;IACzB,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,kBAAkB,CAAC;IAC/C,OAAO,CAAC,OAAO;QACb,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QACtB,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,mBAAmB,IAAI,EAAE,CAAC;aAC9C,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,kCAAkC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;aACrF,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAClB,UAAU,CAAC;YACT,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,8CAA8C;YACrD,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,QAAQ;YACpB,QAAQ,EAAE,UAAU;YACpB,WAAW,EAAE,wGAAwG;YACrH,MAAM,EAAE,+JAA+J;YACvK,YAAY,EAAE,+FAA+F;YAC7G,IAAI,EAAE,8BAA8B,CAAC,IAAI;YACzC,QAAQ,EAAE,EAAE,iBAAiB,EAAE,UAAU,CAAC,iBAAiB,EAAE;SAC9D,CAAC,CACH,CAAC;IACN,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AuditContext } from "../../types.js";
|
|
2
|
+
import type { Halo2Assignment } from "../../frontends/halo2/halo2-types.js";
|
|
3
|
+
import { Halo2ConstraintGraph } from "../../frontends/halo2/halo2-constraint-graph.js";
|
|
4
|
+
export declare function hasHalo2(context: AuditContext): boolean;
|
|
5
|
+
export declare function assignmentIsConstrained(assignment: Halo2Assignment, context: AuditContext): boolean;
|
|
6
|
+
export declare function columnHasEqualityEnabled(columnName: string, context: AuditContext): boolean;
|
|
7
|
+
export declare function halo2Graph(context: AuditContext): Halo2ConstraintGraph | undefined;
|
|
8
|
+
export declare function fileHasSafeInverseGuard(file: string, line: number, context: AuditContext): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Halo2ConstraintGraph } from "../../frontends/halo2/halo2-constraint-graph.js";
|
|
2
|
+
export function hasHalo2(context) {
|
|
3
|
+
return Boolean(context.halo2 && context.halo2.files.length > 0);
|
|
4
|
+
}
|
|
5
|
+
export function assignmentIsConstrained(assignment, context) {
|
|
6
|
+
if (!context.halo2)
|
|
7
|
+
return false;
|
|
8
|
+
return new Halo2ConstraintGraph(context.halo2).isAssignmentConnected(assignment);
|
|
9
|
+
}
|
|
10
|
+
export function columnHasEqualityEnabled(columnName, context) {
|
|
11
|
+
if (!context.halo2)
|
|
12
|
+
return false;
|
|
13
|
+
return new Halo2ConstraintGraph(context.halo2).columnHasEqualityEnabled(columnName);
|
|
14
|
+
}
|
|
15
|
+
export function halo2Graph(context) {
|
|
16
|
+
return context.halo2 ? new Halo2ConstraintGraph(context.halo2) : undefined;
|
|
17
|
+
}
|
|
18
|
+
export function fileHasSafeInverseGuard(file, line, context) {
|
|
19
|
+
const source = context.halo2?.files.find((candidate) => candidate.filePath === file)?.rawSource ?? "";
|
|
20
|
+
const lines = source.split(/\r?\n/);
|
|
21
|
+
const window = lines.slice(Math.max(0, line - 6), Math.min(lines.length, line + 5)).join("\n");
|
|
22
|
+
return /\bis_zero\b|\bnonzero\b|\bnot_zero\b|\bassert(?:!|\s*\()|\bsafe\b|\bchecked\b|\bconstrain_equal\b|\bzero_check\b/i.test(window);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=halo2-rule-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"halo2-rule-utils.js","sourceRoot":"","sources":["../../../src/rules/halo2/halo2-rule-utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAC;AAEvF,MAAM,UAAU,QAAQ,CAAC,OAAqB;IAC5C,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,UAA2B,EAAE,OAAqB;IACxF,IAAI,CAAC,OAAO,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,IAAI,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,UAAkB,EAAE,OAAqB;IAChF,IAAI,CAAC,OAAO,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,IAAI,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAqB;IAC9C,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAE,IAAY,EAAE,OAAqB;IACvF,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;IACtG,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/F,OAAO,mHAAmH,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC1I,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { dangerousHintAssignmentRule } from "./NS-ZK-001-dangerous-hint-assignment.js";
|
|
2
|
+
import { assignedButUnconstrainedRule } from "./NS-ZK-002-assigned-but-unconstrained.js";
|
|
3
|
+
import { unboundPublicInputRule } from "./NS-ZK-003-unbound-public-input.js";
|
|
4
|
+
import { unconstrainedOutputRule } from "./NS-ZK-004-unconstrained-output.js";
|
|
5
|
+
import { missingBooleanityRule } from "./NS-ZK-005-missing-booleanity.js";
|
|
6
|
+
import { missingRangeCheckRule } from "./NS-ZK-006-missing-range-check.js";
|
|
7
|
+
import { unsafeAssertionRule } from "./NS-ZK-007-unsafe-assertion.js";
|
|
8
|
+
import { unsafeDivisionOrInverseRule } from "./NS-ZK-008-unsafe-division-or-inverse.js";
|
|
9
|
+
import { unconstrainedComponentOutputRule } from "./NS-ZK-009-unconstrained-component-output.js";
|
|
10
|
+
import { aliasOverflowRiskRule } from "./NS-ZK-010-alias-overflow-risk.js";
|
|
11
|
+
import { unusedSignalRule } from "./NS-ZK-011-unused-signal.js";
|
|
12
|
+
import { suspiciousSelectorRule } from "./NS-ZK-012-suspicious-selector.js";
|
|
13
|
+
import { halo2AssignedAdviceNotConstrainedRule } from "./halo2/NS-H2-001-assigned-advice-not-constrained.js";
|
|
14
|
+
import { halo2InstanceNotBoundRule } from "./halo2/NS-H2-002-instance-not-bound.js";
|
|
15
|
+
import { halo2SelectorRiskRule } from "./halo2/NS-H2-003-selector-risk.js";
|
|
16
|
+
import { halo2UnsafeInverseRule } from "./halo2/NS-H2-004-unsafe-inverse.js";
|
|
17
|
+
import { halo2PartialEcOperationRule } from "./halo2/NS-H2-005-partial-ec-operation.js";
|
|
18
|
+
import { halo2MissingEnableEqualityRule } from "./halo2/NS-H2-006-missing-enable-equality.js";
|
|
19
|
+
export const allRules = [
|
|
20
|
+
dangerousHintAssignmentRule,
|
|
21
|
+
assignedButUnconstrainedRule,
|
|
22
|
+
unboundPublicInputRule,
|
|
23
|
+
unconstrainedOutputRule,
|
|
24
|
+
missingBooleanityRule,
|
|
25
|
+
missingRangeCheckRule,
|
|
26
|
+
unsafeAssertionRule,
|
|
27
|
+
unsafeDivisionOrInverseRule,
|
|
28
|
+
unconstrainedComponentOutputRule,
|
|
29
|
+
aliasOverflowRiskRule,
|
|
30
|
+
unusedSignalRule,
|
|
31
|
+
suspiciousSelectorRule,
|
|
32
|
+
halo2AssignedAdviceNotConstrainedRule,
|
|
33
|
+
halo2InstanceNotBoundRule,
|
|
34
|
+
halo2SelectorRiskRule,
|
|
35
|
+
halo2UnsafeInverseRule,
|
|
36
|
+
halo2PartialEcOperationRule,
|
|
37
|
+
halo2MissingEnableEqualityRule
|
|
38
|
+
];
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EAAE,gCAAgC,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,qCAAqC,EAAE,MAAM,sDAAsD,CAAC;AAC7G,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AACpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EAAE,8BAA8B,EAAE,MAAM,8CAA8C,CAAC;AAE9F,MAAM,CAAC,MAAM,QAAQ,GAAW;IAC9B,2BAA2B;IAC3B,4BAA4B;IAC5B,sBAAsB;IACtB,uBAAuB;IACvB,qBAAqB;IACrB,qBAAqB;IACrB,mBAAmB;IACnB,2BAA2B;IAC3B,gCAAgC;IAChC,qBAAqB;IACrB,gBAAgB;IAChB,sBAAsB;IACtB,qCAAqC;IACrC,yBAAyB;IACzB,qBAAqB;IACrB,sBAAsB;IACtB,2BAA2B;IAC3B,8BAA8B;CAC/B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AuditResult, OutputFormat, ScanOptions } from "./types.js";
|
|
2
|
+
export interface ScanRunResult {
|
|
3
|
+
result: AuditResult;
|
|
4
|
+
output: string;
|
|
5
|
+
exitCode: 0 | 1;
|
|
6
|
+
}
|
|
7
|
+
export declare function scanTarget(target: string, options?: ScanOptions): Promise<ScanRunResult>;
|
|
8
|
+
export declare function renderReport(result: AuditResult, format: OutputFormat): string;
|
package/dist/scanner.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { loadConfig } from "./config.js";
|
|
3
|
+
import { auditParsedFiles } from "./core/audit-engine.js";
|
|
4
|
+
import { loadCircomFiles, loadRustFiles } from "./core/file-loader.js";
|
|
5
|
+
import { isAtOrAbove, normalizeSeverity } from "./core/severity.js";
|
|
6
|
+
import { parseCircomFile } from "./frontends/circom/circom-parser.js";
|
|
7
|
+
import { parseHalo2File } from "./frontends/halo2/halo2-parser.js";
|
|
8
|
+
import { isLikelyHalo2Source } from "./frontends/halo2/halo2-patterns.js";
|
|
9
|
+
import { renderJsonReport } from "./report/json.js";
|
|
10
|
+
import { renderMarkdownReport } from "./report/markdown.js";
|
|
11
|
+
import { renderSarifReport } from "./report/sarif.js";
|
|
12
|
+
import { renderTerminalReport } from "./report/terminal.js";
|
|
13
|
+
export async function scanTarget(target, options = {}) {
|
|
14
|
+
const config = loadConfig(process.cwd(), options.configPath);
|
|
15
|
+
const format = options.format ?? options.report ?? config.format;
|
|
16
|
+
const failOn = normalizeSeverity(options.failOn, config.failOn);
|
|
17
|
+
const circomFiles = await loadCircomFiles(target, config.ignore);
|
|
18
|
+
const rustFiles = await loadRustFiles(target, config.ignore);
|
|
19
|
+
const parsed = circomFiles.map((file) => parseCircomFile(file.filePath, file.rawSource));
|
|
20
|
+
const halo2Parsed = rustFiles.filter((file) => isLikelyHalo2Source(file.rawSource)).map((file) => parseHalo2File(file.filePath, file.rawSource));
|
|
21
|
+
const result = auditParsedFiles(target, parsed, { ...config, failOn, format }, halo2Parsed);
|
|
22
|
+
const output = renderReport(result, format);
|
|
23
|
+
if (options.out || options.report) {
|
|
24
|
+
const outPath = options.out ?? defaultReportPath(format);
|
|
25
|
+
await writeFile(outPath, output);
|
|
26
|
+
}
|
|
27
|
+
const exitCode = result.issues.some((issue) => isAtOrAbove(issue.severity, failOn)) ? 1 : 0;
|
|
28
|
+
return { result, output, exitCode };
|
|
29
|
+
}
|
|
30
|
+
export function renderReport(result, format) {
|
|
31
|
+
switch (format) {
|
|
32
|
+
case "json":
|
|
33
|
+
return renderJsonReport(result);
|
|
34
|
+
case "markdown":
|
|
35
|
+
return renderMarkdownReport(result);
|
|
36
|
+
case "sarif":
|
|
37
|
+
return renderSarifReport(result);
|
|
38
|
+
case "terminal":
|
|
39
|
+
default:
|
|
40
|
+
return renderTerminalReport(result);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function defaultReportPath(format) {
|
|
44
|
+
if (format === "markdown")
|
|
45
|
+
return "nullsec-zk-report.md";
|
|
46
|
+
if (format === "sarif")
|
|
47
|
+
return "nullsec-zk-report.sarif";
|
|
48
|
+
if (format === "json")
|
|
49
|
+
return "nullsec-zk-report.json";
|
|
50
|
+
return "nullsec-zk-report.txt";
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export type Severity = "CRITICAL" | "HIGH" | "MEDIUM" | "LOW" | "INFO";
|
|
2
|
+
export type Confidence = "HIGH" | "MEDIUM" | "LOW";
|
|
3
|
+
export type SignalKind = "input" | "output" | "internal";
|
|
4
|
+
export type SignalVisibility = "public" | "private" | "unknown";
|
|
5
|
+
export type AssignmentOperator = "<--" | "<==";
|
|
6
|
+
export type ConstraintOperator = "===" | "<==";
|
|
7
|
+
export type OutputFormat = "terminal" | "json" | "markdown" | "sarif";
|
|
8
|
+
export type FrontendName = "Circom" | "Halo2" | "Mixed";
|
|
9
|
+
export interface SourceLocation {
|
|
10
|
+
file: string;
|
|
11
|
+
line: number;
|
|
12
|
+
column?: number;
|
|
13
|
+
snippet?: string;
|
|
14
|
+
templateName?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface Issue {
|
|
17
|
+
id: string;
|
|
18
|
+
ruleId: string;
|
|
19
|
+
title: string;
|
|
20
|
+
severity: Severity;
|
|
21
|
+
confidence: Confidence;
|
|
22
|
+
file: string;
|
|
23
|
+
line: number;
|
|
24
|
+
column?: number;
|
|
25
|
+
snippet?: string;
|
|
26
|
+
templateName?: string;
|
|
27
|
+
signalName?: string;
|
|
28
|
+
explanation: string;
|
|
29
|
+
impact: string;
|
|
30
|
+
suggestedFix: string;
|
|
31
|
+
references?: string[];
|
|
32
|
+
tags: string[];
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
export interface ParserWarning extends SourceLocation {
|
|
36
|
+
message: string;
|
|
37
|
+
}
|
|
38
|
+
export interface TemplateDeclaration extends SourceLocation {
|
|
39
|
+
name: string;
|
|
40
|
+
params: string[];
|
|
41
|
+
startLine: number;
|
|
42
|
+
endLine?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface SignalDeclaration extends SourceLocation {
|
|
45
|
+
name: string;
|
|
46
|
+
baseName: string;
|
|
47
|
+
kind: SignalKind;
|
|
48
|
+
visibility: SignalVisibility;
|
|
49
|
+
arrayDimensions: string[];
|
|
50
|
+
typeInfo?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface Assignment extends SourceLocation {
|
|
53
|
+
lhs: string;
|
|
54
|
+
rhs: string;
|
|
55
|
+
operator: AssignmentOperator;
|
|
56
|
+
referencedSignals: string[];
|
|
57
|
+
}
|
|
58
|
+
export interface Constraint extends SourceLocation {
|
|
59
|
+
expression: string;
|
|
60
|
+
lhs?: string;
|
|
61
|
+
rhs?: string;
|
|
62
|
+
operator: ConstraintOperator;
|
|
63
|
+
referencedSignals: string[];
|
|
64
|
+
}
|
|
65
|
+
export interface Assertion extends SourceLocation {
|
|
66
|
+
expression: string;
|
|
67
|
+
referencedSignals: string[];
|
|
68
|
+
}
|
|
69
|
+
export interface ComponentDeclaration extends SourceLocation {
|
|
70
|
+
name: string;
|
|
71
|
+
templateType?: string;
|
|
72
|
+
params?: string;
|
|
73
|
+
inputs: string[];
|
|
74
|
+
outputs: string[];
|
|
75
|
+
}
|
|
76
|
+
export interface IncludeStatement extends SourceLocation {
|
|
77
|
+
path: string;
|
|
78
|
+
}
|
|
79
|
+
export interface ParsedCircuitFile {
|
|
80
|
+
filePath: string;
|
|
81
|
+
rawSource: string;
|
|
82
|
+
templates: TemplateDeclaration[];
|
|
83
|
+
signals: SignalDeclaration[];
|
|
84
|
+
components: ComponentDeclaration[];
|
|
85
|
+
assignments: Assignment[];
|
|
86
|
+
constraints: Constraint[];
|
|
87
|
+
assertions: Assertion[];
|
|
88
|
+
includes: IncludeStatement[];
|
|
89
|
+
parserWarnings: ParserWarning[];
|
|
90
|
+
}
|
|
91
|
+
export interface CircuitIR {
|
|
92
|
+
files: ParsedCircuitFile[];
|
|
93
|
+
signals: SignalDeclaration[];
|
|
94
|
+
components: ComponentDeclaration[];
|
|
95
|
+
assignments: Assignment[];
|
|
96
|
+
constraints: Constraint[];
|
|
97
|
+
assertions: Assertion[];
|
|
98
|
+
parserWarnings: ParserWarning[];
|
|
99
|
+
}
|
|
100
|
+
export interface Rule {
|
|
101
|
+
id: string;
|
|
102
|
+
title: string;
|
|
103
|
+
description: string;
|
|
104
|
+
defaultSeverity: Severity;
|
|
105
|
+
tags: string[];
|
|
106
|
+
analyze(context: AuditContext): Issue[];
|
|
107
|
+
}
|
|
108
|
+
export interface RuleConfig {
|
|
109
|
+
[ruleId: string]: "off" | "critical" | "high" | "medium" | "low" | "info" | Severity;
|
|
110
|
+
}
|
|
111
|
+
export interface NullsecConfig {
|
|
112
|
+
rules: RuleConfig;
|
|
113
|
+
ignore: string[];
|
|
114
|
+
failOn: Severity;
|
|
115
|
+
format: OutputFormat;
|
|
116
|
+
field: "BN254" | string;
|
|
117
|
+
}
|
|
118
|
+
export interface AuditContext {
|
|
119
|
+
target: string;
|
|
120
|
+
ir: CircuitIR;
|
|
121
|
+
graph: ConstraintGraphLike;
|
|
122
|
+
config: NullsecConfig;
|
|
123
|
+
halo2?: import("./frontends/halo2/halo2-types.js").Halo2IR;
|
|
124
|
+
}
|
|
125
|
+
export interface ConstraintGraphLike {
|
|
126
|
+
declaredSignals(): SignalDeclaration[];
|
|
127
|
+
inputSignals(): SignalDeclaration[];
|
|
128
|
+
publicInputSignals(): SignalDeclaration[];
|
|
129
|
+
outputSignals(): SignalDeclaration[];
|
|
130
|
+
assignedByHint(): Assignment[];
|
|
131
|
+
assignedByConstraint(): Assignment[];
|
|
132
|
+
constraintsForSignal(signalName: string): Constraint[];
|
|
133
|
+
assignmentsForSignal(signalName: string): Assignment[];
|
|
134
|
+
appearsInAnyConstraint(signalName: string): boolean;
|
|
135
|
+
appearsInEqualityConstraint(signalName: string): boolean;
|
|
136
|
+
onlyAssignedButNeverConstrained(): Assignment[];
|
|
137
|
+
unboundInputs(): SignalDeclaration[];
|
|
138
|
+
unconstrainedOutputs(): SignalDeclaration[];
|
|
139
|
+
hasBooleanityConstraint(signalName: string): boolean;
|
|
140
|
+
hasRangeCheck(signalName: string, templateName?: string): boolean;
|
|
141
|
+
isComponentOutputReference(reference: string): boolean;
|
|
142
|
+
isComponentOutputConstrained(reference: string): boolean;
|
|
143
|
+
signalReferences(signalName: string): SourceLocation[];
|
|
144
|
+
}
|
|
145
|
+
export interface AuditSummary {
|
|
146
|
+
CRITICAL: number;
|
|
147
|
+
HIGH: number;
|
|
148
|
+
MEDIUM: number;
|
|
149
|
+
LOW: number;
|
|
150
|
+
INFO: number;
|
|
151
|
+
}
|
|
152
|
+
export interface AuditResult {
|
|
153
|
+
tool: {
|
|
154
|
+
name: "Nullsec S1-ZK";
|
|
155
|
+
version: string;
|
|
156
|
+
};
|
|
157
|
+
target: string;
|
|
158
|
+
frontend: FrontendName;
|
|
159
|
+
filesScanned: number;
|
|
160
|
+
rulesExecuted: number;
|
|
161
|
+
summary: AuditSummary;
|
|
162
|
+
issues: Issue[];
|
|
163
|
+
parserWarnings: ParserWarning[];
|
|
164
|
+
}
|
|
165
|
+
export interface ScanOptions {
|
|
166
|
+
format?: OutputFormat;
|
|
167
|
+
report?: OutputFormat;
|
|
168
|
+
out?: string;
|
|
169
|
+
failOn?: Severity;
|
|
170
|
+
configPath?: string;
|
|
171
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Instance};
|
|
2
|
+
|
|
3
|
+
struct Config {
|
|
4
|
+
advice: Column<Advice>,
|
|
5
|
+
instance: Column<Instance>,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
|
|
9
|
+
let advice = meta.advice_column();
|
|
10
|
+
let instance = meta.instance_column();
|
|
11
|
+
meta.enable_equality(advice);
|
|
12
|
+
meta.enable_equality(instance);
|
|
13
|
+
meta.create_gate("public input relation", |meta| {
|
|
14
|
+
let a = meta.query_advice(advice, Rotation::cur());
|
|
15
|
+
let public = meta.query_instance(instance, Rotation::cur());
|
|
16
|
+
vec![a - public]
|
|
17
|
+
});
|
|
18
|
+
Config { advice, instance }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fn expose_public(layouter: &mut impl Layouter<Fp>, config: Config, cell: AssignedCell<Fp, Fp>) {
|
|
22
|
+
layouter.constrain_instance(cell.cell(), config.instance, 0)?;
|
|
23
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
use halo2_proofs::plonk::{Advice, Column, ConstraintSystem, Selector};
|
|
2
|
+
|
|
3
|
+
struct Config {
|
|
4
|
+
value: Column<Advice>,
|
|
5
|
+
q_enable: Selector,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
fn configure(meta: &mut ConstraintSystem<Fp>) -> Config {
|
|
9
|
+
let value = meta.advice_column();
|
|
10
|
+
meta.enable_equality(value);
|
|
11
|
+
let q_enable = meta.selector();
|
|
12
|
+
meta.create_gate("value is constrained", |meta| {
|
|
13
|
+
let s = meta.query_selector(q_enable);
|
|
14
|
+
let v = meta.query_advice(value, Rotation::cur());
|
|
15
|
+
vec![s * v]
|
|
16
|
+
});
|
|
17
|
+
Config { value, q_enable }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fn synthesize(config: Config, mut layouter: impl Layouter<Fp>) {
|
|
21
|
+
layouter.assign_region(|| "constrained witness", |mut region| {
|
|
22
|
+
config.q_enable.enable(&mut region, 0)?;
|
|
23
|
+
let cell = region.assign_advice(|| "value", config.value, 0, || Value::known(value))?;
|
|
24
|
+
region.constrain_equal(cell.cell(), cell.cell())?;
|
|
25
|
+
Ok(())
|
|
26
|
+
});
|
|
27
|
+
}
|