Skip to content

Commit 4139031

Browse files
Merge pull request #1290 from Queenode/fix-issues-1192-1191-1188-1189
Fix issues #1192, #1191, #1188, #1189
2 parents b5fedef + 16b4c86 commit 4139031

7 files changed

Lines changed: 116 additions & 2 deletions

File tree

.github/workflows/release.yml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,41 @@ on:
33
push:
44
tags:
55
- "v*"
6+
workflow_dispatch:
7+
inputs:
8+
override_mainnet_gate:
9+
description: "Justification to override mainnet readiness gate"
10+
required: false
11+
type: string
612

7-
permissions: {}
13+
permissions:
14+
contents: write
15+
issues: read
816

917
env:
1018
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
1119

1220
jobs:
21+
mainnet-readiness-gate:
22+
name: Check Mainnet Readiness
23+
runs-on: ubuntu-latest
24+
if: startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-mainnet') && github.event.inputs.override_mainnet_gate == ''
25+
steps:
26+
- name: Check open milestone issues
27+
env:
28+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
run: |
30+
OPEN_ISSUES=$(gh issue list --repo ${{ github.repository }} --milestone "Mainnet Launch Readiness" --state open --json number,title --jq length)
31+
if [ "$OPEN_ISSUES" -gt 0 ]; then
32+
echo "::error::There are $OPEN_ISSUES open issues in the 'Mainnet Launch Readiness' milestone."
33+
gh issue list --repo ${{ github.repository }} --milestone "Mainnet Launch Readiness" --state open
34+
exit 1
35+
fi
36+
1337
build-and-release:
1438
name: Build (${{ matrix.target }})
39+
needs: mainnet-readiness-gate
40+
if: always() && needs.mainnet-readiness-gate.result != 'failure'
1541
runs-on: ${{ matrix.os }}
1642
permissions:
1743
contents: write

data/sarif/severity-map.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
# Severity mapping for standard S-rules
12
severity_mapping:
23
info: low
34
warning: medium
45
error: high
56
blocker: critical
7+
8+
# ZK specific mapping guidelines (Z0xx namespace):
9+
# ZK rules follow the same severity levels as S-rules but have distinct vulnerability classes:
10+
# - missing-nullifier: blocker (critical)
11+
# - weak-fiat-shamir: error (high)
12+
# - constraint-under-specification: warning (medium)
13+
# - unused-public-input: info (low)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# ADR 012: ZK Toolchain Integration Path
2+
3+
## Status
4+
5+
Accepted
6+
7+
## Context
8+
9+
Zero-Knowledge (ZK) vulnerabilities require parsers and a static analysis model to detect issues like missing nullifier checks and weak Fiat-Shamir implementations. There are several ZK toolchains in the ecosystem (e.g., circom, arkworks, halo2, Noir). We need to decide which toolchains Sanctifier will support as a first-class citizen in v1, and which will be deferred to the future roadmap. This choice directly impacts the source languages our parsers need to support and the verifier contract patterns we prioritize. (See spike #1190 for research details).
10+
11+
## Decision
12+
13+
We will prioritize **circom + snarkjs** and **arkworks (Rust)** for v1 support.
14+
15+
- **circom + snarkjs:** Has mature ecosystem tooling and is widely used across the industry for ZK rollups and application circuits.
16+
- **arkworks:** Given our existing Rust infrastructure and Soroban's native Rust environment, supporting arkworks aligns well with our current tech stack and ecosystem.
17+
18+
Other toolchains, such as **Noir** and **halo2**, will be deferred to the future roadmap.
19+
20+
## Consequences
21+
22+
1. **Parser Scope (#1227, #1228, #1229):** The parsers must be designed to parse Circom source files and Rust (for arkworks). We will not build parser support for Noir at this time.
23+
2. **Example Contracts (#1216):** The first verifier contract patterns and test suites built will target Circom/snarkjs Groth16/Plonk verifiers and arkworks-based verifiers.
24+
3. **Roadmap:** We must explicitly communicate to users that Noir and halo2 are not supported in the initial ZK ruleset release, managing expectations.

docs/error-codes.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Sanctifier Error Code Mapping
22

3+
## CLI Exit Codes
4+
5+
When running `sanctifier-cli`, the process will exit with one of the following codes:
6+
- **`0` (SUCCESS)**: Analysis succeeded with no triggered findings.
7+
- **`1` (FINDINGS_FOUND)**: Findings were detected and the active profile triggered on them.
8+
- **`2` (ERROR)**: Unrecoverable error (e.g., invalid path, config parse failure, I/O error).
9+
10+
---
311
Sanctifier uses a unified finding code system across `sanctifier-core` and `sanctifier-cli` outputs.
412

513
| Code | Category | Meaning |

docs/rule-authoring-guide.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,14 @@ fn collect_pat_idents(pat: &Pat, out: &mut HashSet<String>) {
212212
Not handling `Pat::Tuple` / `Pat::Struct` is the most common source of false negatives
213213
in taint passes — taint silently disappears at the destructure boundary.
214214

215+
## 8. ZK Rules (Z-series) Namespace
216+
217+
Sanctifier introduces a dedicated `Z001-Z0NN` numbering convention for Zero-Knowledge (ZK) specific vulnerability rules, functioning alongside the existing `S0xx` static-rule namespace.
218+
219+
When authoring ZK rules:
220+
- **Namespace:** All ZK rules MUST use the `Z` prefix (e.g., `Z001`, `Z002`).
221+
- **Severity Mapping:** ZK vulnerabilities often have different blast-radius characteristics than typical Soroban bugs. Explicit severity mapping guidance is required to ensure consistent rating by reviewers. Refer to `schemas/severity-taxonomy.schema.json` and `data/sarif/severity-map.yaml` for specific vulnerability classes (e.g., missing nullifier checks, weak fiat-shamir).
222+
215223
---
216224

217225
## Further Reading

schemas/severity-taxonomy.schema.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"additionalProperties": {
99
"type": "string",
1010
"enum": ["low", "medium", "high", "critical"]
11-
}
11+
},
12+
"description": "Maps generic severities (info, warning, error, blocker) to standard SARIF severity levels. For ZK vulnerabilities (Z-series), map severity explicitly based on blast-radius (e.g. missing nullifier checks -> critical, weak fiat-shamir -> high, constraint under-specification -> medium, unused public input -> low)."
1213
}
1314
}
1415
}

tooling/sanctifier-cli/tests/cli_tests.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,3 +1434,42 @@ fn test_no_profile_no_exit_code_exits_zero_with_findings() {
14341434
.assert()
14351435
.success();
14361436
}
1437+
1438+
/// Verify documented CLI exit codes (0 = SUCCESS, 1 = FINDINGS_FOUND, 2 = ERROR).
1439+
#[test]
1440+
fn test_documented_exit_codes() {
1441+
let valid_fixture = env::current_dir()
1442+
.unwrap()
1443+
.join("tests/fixtures/valid_contract.rs");
1444+
let vulnerable_fixture = env::current_dir()
1445+
.unwrap()
1446+
.join("tests/fixtures/vulnerable_contract.rs");
1447+
1448+
// Code 0: SUCCESS (no findings)
1449+
Command::cargo_bin("sanctifier")
1450+
.unwrap()
1451+
.arg("analyze")
1452+
.arg(&valid_fixture)
1453+
.arg("--profile")
1454+
.arg("ci")
1455+
.assert()
1456+
.code(0);
1457+
1458+
// Code 1: FINDINGS_FOUND (has findings with strict profile)
1459+
Command::cargo_bin("sanctifier")
1460+
.unwrap()
1461+
.arg("analyze")
1462+
.arg(&vulnerable_fixture)
1463+
.arg("--profile")
1464+
.arg("ci")
1465+
.assert()
1466+
.code(1);
1467+
1468+
// Code 2: ERROR (e.g., invalid path)
1469+
Command::cargo_bin("sanctifier")
1470+
.unwrap()
1471+
.arg("analyze")
1472+
.arg("path/that/does/not/exist.rs")
1473+
.assert()
1474+
.code(2);
1475+
}

0 commit comments

Comments
 (0)