Rúnar is a compiler that emits on-chain Bitcoin SV Script — the locking scripts it produces directly control real funds. We take security reports seriously and appreciate responsible disclosure.
| Version | Supported |
|---|---|
| 1.0.x | ✅ Yes |
| < 1.0 | ❌ No (pre-release / release-candidate builds) |
Once 1.0.0 ships, security fixes land on the 1.0.x line.
Please report security issues privately — do not open a public GitHub issue.
- Preferred: GitHub Security Advisories (Security → Advisories → "Report a vulnerability").
- Email: siggi.oskarsson@gmail.com
If you can, include a minimal reproduction (source contract + the offending output) and the affected tier(s) and version.
Because the output of this project controls money, the following are in scope and especially valued:
- Compiler miscompilations — any case where a frontend/codegen pass emits
Bitcoin Script that does not faithfully implement the source contract
(e.g. a spending path that should be guarded but isn't, stack
underflow/overflow, an
assert/checkSig/checkPreimagethat can be bypassed). This includes divergence between the seven compiler tiers (TypeScript, Go, Rust, Python, Zig, Ruby, Java) for the same source. - SDK signing / wire-protocol bugs — flaws in transaction construction,
BIP-143 sighash computation,
canonicalJsonserialization, or thesignEnvelope/verifyEnvelopesigned-broadcast protocol that could produce invalid signatures, accept a forged envelope, or diverge across the seven deployment SDKs. - Cryptographic-primitive flaws — incorrect codegen for hash, EC (secp256k1 / NIST P-256 / P-384), WOTS+, SLH-DSA, BLAKE3, or related primitives that weakens or breaks the on-chain check.
Out of scope: anything behind asm(). A contract extending
UnsafeSmartContract may call asm({ body, in_arity, out_arity }) to splice
verbatim opcode bytes into its script. The compiler does not interpret those
bytes: it emits them as written and trusts the declared stack effect. A wrong
in_arity / out_arity, or a byte sequence that misbehaves, is an author
defect, not a compiler defect — there is no analysis that could have caught it.
A miscompile of the surrounding contract, or of the splice mechanism itself, IS
in scope. See docs/language-reference.md for the construct and
spec/ir-format.md §4.19 for the IR node.
Compiled contracts depend on the Chronicle opcode policy (SV Node v1.2.0),
which activated on BSV mainnet at block 943,816 on 7 April 2026. Every
stateful contract carries OP_2MUL in its checkPreimage binding blob; the EC,
NIST P-256/P-384 and Merkle primitives also emit OP_2DIV and OP_RSHIFTNUM.
This is a known and intended property of the compiler, not a vulnerability, and we are not looking for reports that simply restate it. Two consequences are worth knowing when assessing anything in this repo:
- A validator still on the pre-Chronicle policy hard-fails on
OP_2MUL/OP_2DIVwith adisabled opcodeerror, but treats0xb3–0xb7as upgradable NOPs. In the second case it does not abort — it computes a wrong result and reports success. Do not treat a pass from a pre-Chronicle tool as evidence of correctness. - The regtest configuration in
integration/regtest.shsetschronicleactivationheight=1so a local node enforces the same rules mainnet does. A green integration run therefore says nothing about pre-Chronicle behaviour, by design.
Details, and the list of affected contract shapes, are in
docs/chronicle-opcode-policy.md. A case
where the emitted policy does not match what the documentation claims is in
scope and we would like to hear about it.
Rúnar carries a Lean formal-verification effort (runar-verification/), but it
is deliberately scoped. It proves observational (accept/reject) agreement
for the back half of the pipeline — ANF IR → Stack IR → peephole → emit →
bytes → parse → execute — modulo 70 codegen axioms (textbook crypto
semantics and per-primitive codegen→runtime bridges). The frontends (the nine
source-format parsers, validation, typecheck, and ANF lowering) are out of
scope of the proof.
Rúnar is not "formally verified end to end." For the precise, machine-
checked trust boundary — what is proven, what is axiomatized, and what is
deferred — see
runar-verification/TRUST_MANIFEST.md.
A vulnerability inside the verified back half, or in a relied-upon axiom, is
very much in scope.
- We aim to acknowledge a report within 5 business days.
- We will keep you informed of our assessment and remediation timeline, and coordinate disclosure timing with you.
- With your consent, we are happy to credit you in the advisory and release notes.