Spark Program | ckb-lint: A Static Security Linter for CKB Lock and Type Scripts
0. Project Overview
Project Name: ckb-lint
One-line Summary: A static analysis tool that scans CKB lock and type scripts before deployment and flags a defined set of documented, real vulnerability classes, with a paired vulnerable and fixed sample script proving each check actually catches its bug.
Project Type: Developer tool, delivered as an open-source command-line application.
1. Team Profile
Core member: Gabriel_Temsten (Applicant)
-
Team / Individual Profile and Contact Information
-
Name: temsten
-
Role: Sole developer and maintainer
-
Background: Full-stack engineer with deep experience in TypeScript, React, Next.js, and the CKB ecosystem.
-
Github: gabrieltemtsen (Gabriel Temtsen) · GitHub
email : [email protected]
2. Project Background
CKB has no persistent contract state. Every unit of value lives inside a Cell, and every lock or type script attached to that Cell has to independently verify a whole transaction is valid, every time, with no framework enforcing that a developer checked everything they needed to. So the most dangerous CKB bugs are usually not “this function’s logic is wrong,” they’re “this script forgot to check something across the full set of inputs and outputs.”
This is not hypothetical. CKB has a published security advisory, GHSA-mcmr-49x3-4jqm, for exactly this category of bug in its own Type ID system script. More strikingly, in February 2026 Nervos’s own official testing library, ckb-testtool, shipped a bug where its simulator silently reported success even when a script actually failed — meaning a developer testing their contract during that window had no way of knowing their test was lying to them.
If CKB’s own official tooling has shipped these bug classes this year, individual developers hand-writing scripts without that level of institutional review are exposed to the same and worse. No tool in the CKB ecosystem currently scans a script for these documented failure patterns before deployment. That absence is what this project addresses.
3. Solution
ckb-lint reads a CKB script’s Rust source, without running it, and checks it against four rules, each tied to a real vulnerability class described above:
-
Rule 1 — Missing owner-mode check. Flags a type script that increases output amount over input amount (a mint) without verifying an owner lock hash is present in the transaction’s inputs. Without this, anyone can mint unlimited value.
-
Rule 2 — Incomplete script-group iteration. Flags a script that reads only cell index 0 instead of iterating its full script group — the same bug class behind the real Type ID advisory above. An attacker can smuggle unchecked cells past a script that skips this.
-
Rule 3 — Unchecked capacity/amount arithmetic. Flags capacity or token-amount math that doesn’t use Rust’s checked or saturating operations, which can silently underflow or overflow.
-
Rule 4 — Missing minimum-capacity check. Flags output cell construction that doesn’t verify CKB’s minimum occupied-capacity requirement.
Every rule ships with a vulnerable sample script and its fixed counterpart. Nobody has to trust ckb-lint’s internal logic: read the two plain Rust files, confirm the bug and its fix yourself, then run the linter against both and confirm it agrees.
Here is how a single scan flows through the tool:
4. Technical Approach
Written in Rust, since that’s the language most CKB scripts are written in and lets the tool parse real script source directly. It works at the source level using syn (the standard Rust source-parsing crate), not compiled bytecode — reimplementing CKB-VM’s execution semantics is out of scope for one grant round. This makes ckb-lint a pattern-based linter, like Slither for Solidity, not a formal prover.
The CLI exposes one command, ckb-lint scan, which prints a human-readable report by default and supports --json for CI pipelines. All sample scripts live in samples/, one subfolder per rule, each with a vulnerable/ and fixed/ version — this same directory is both the automated test suite and the material a reviewer checks by hand.
5. To-Do List
Week 1: Build the CLI entry point and the syn-based parsing pipeline. Write the first vulnerable/fixed sample pair and implement Rule 1 (missing owner-mode check) against it.
Week 2: Implement Rule 2 (incomplete script-group iteration) and Rule 3 (unchecked capacity/amount arithmetic), each with its own vulnerable/fixed sample pair.
Week 3: Implement Rule 4 (missing minimum-capacity check) with its sample pair. Add --json output. Build the automated test harness that runs all four rules against all eight samples in one pass. Core technical work is done by the end of this week.
Week 4: Package a one-command reproducible verification script, write the README and rule reference docs, and record a short demo video.
Week 5 (buffer): Fix anything found in self-testing, publish the v0.1.0 release, write the final report. This buffer exists deliberately: ckb-probe, one of the committee’s own model examples, had to renegotiate scope mid-project after an initial plan left no slack, and this project would rather build that room in from the start.
Milestone at end of Week 3: all four rules passing the full sample test suite. Milestone at end of Week 5: public release, documentation, and demo video complete.
6. Required Funding and Breakdown
Total requested: $1,000 USD — a single-category technical project, within the Spark Program’s standard cap.
-
$700 — core development (Weeks 1–3): rule engine, CLI, all four detection rules, all four sample pairs.
-
$200 — testing, packaging, docs (Week 4): test harness, one-command verification flow, README and rule reference.
-
$100 — release and buffer (Week 5): demo video, GitHub release, fixes from final self-testing.
Payment preference: [please specify 100% CKB or 100% USDI before submitting].
7. Deliverables and How to Verify
Five deliverables: the ckb-lint CLI as an open-source v0.1.0 release; the four detection rules, each with its vulnerable/fixed sample pair; the automated test harness running all four rules against all eight samples; documentation (README, install instructions, rule reference); and a short demo video as a fallback verification path.
Here’s exactly what running ckb-lint scan prints against the Rule 1 vulnerable sample, then the fixed one:
$ ckb-lint scan samples/rule1-missing-owner-check/vulnerable/
FAIL - 1 issue found
samples/rule1-missing-owner-check/vulnerable/src/main.rs, line 34
RULE-1: Missing owner-mode check
This script increases the total output amount beyond the total input
amount without verifying that an owner lock hash is present among the
transaction’s input locks. This allows unrestricted minting by any
caller who constructs a transaction of this shape.
See the rule reference documentation, section RULE-1, for the full
explanation and the corrected version of this script.
Exit code: 1
Against the fixed sample:
$ ckb-lint scan samples/rule1-missing-owner-check/fixed/
PASS - 0 issues found
Exit code: 0
A reviewer verifies this without trusting the tool’s internals or reading its source:
A reviewer can also open any of the eight sample scripts directly and confirm the vulnerability, or its fix, is real without taking the linter’s word for it. ckb-lint scan --json confirms valid, CI-ready structured output.
This only requires a Rust toolchain — no CKB node, no testnet, no special setup, keeping review cost low.
8. Current State vs. Funded Work
Nothing has been built yet — this starts from zero code. What exists already is the research grounding this proposal: the four target vulnerability classes and the evidence tying them to real problems (GHSA-mcmr-49x3-4jqm, the February 2026 ckb-testtool bugs). Everything in Sections 3–7 is new work to be completed within this grant.
9. Post-Completion Maintenance Plan
ckb-lint analyzes Rust syntax, not a specific CKB node version, so it’s largely insulated from CKB’s own release churn. If script-writing conventions shift, rules get updated to match, and any new rule must ship with its own vulnerable/fixed sample pair, same as the ones in this grant.
The repo is open source from the first commit (MIT or Apache-2.0), with a documented process for proposing rules or reporting false positives or misses. CI runs the full test suite on every change, so nothing merges without still correctly flagging every vulnerable sample and passing every fixed one.
10. Relevance to the CKB Ecosystem
All four rules are built around concepts specific to CKB’s Cell model and script-group execution — none of them map onto account-based-chain tooling, which is why no off-the-shelf analyzer already covers them. This serves any developer writing CKB lock or type scripts, filling a gap made concrete by real, documented bugs already found in CKB’s own official tooling.