Integrate in a coffee break.
Mark the one function that matters, pick how hard it should be to recover, and build. For per-language walkthroughs see Languages; for every flag and endpoint, CLI & API.
Quickstart
Protect a binary from the CLI. The pass runs server-side against your API key, so your protection IP never ships inside the artifact.
# 1. build your object as usual clang -O2 -c app.c -o app.o # 2. seal the marked functions (key from your dashboard) veil protect --level seal app.o -o app.sealed.o # 3. link exactly as before, nothing else changes clang -O2 app.sealed.o -o app
The output is a drop-in replacement object. Your link step, your flags, your toolchain, untouched.
Mark the crown jewel
VeilCC protects the functions you point it at, a license check, an attestation routine, a proprietary kernel, and leaves everything else native. Mark them in source, or name them at build time.
__attribute__((annotate("veil:seal")))
uint32_t check_license(const char *key) {
/* … */
} // Rust, export with the C ABI
#[no_mangle]
pub extern "C" fn check_license(/* … */) -> u32 { … }
// Swift
@_cdecl("check_license")
func checkLicense(/* … */) -> UInt32 { … } No annotation in source? Pass a symbol list at build time, the sealer works on the compiled object, so it's language-agnostic.
Security levels
The same annotation, three strengths. Pick per function; hot paths are refused automatically.
- obfuscate
- Mixed-boolean arithmetic, control-flow flattening and decoys across the whole function, with a fresh moving-target seed every build. Zero cost on hot paths. The deterrence layer, it slows analysis, it doesn't stop an attacker who runs the code.
- seal
- The function ships as ciphertext (ChaCha20) and is decrypted into a W^X page only at call time, then scrubbed. A decompiler finds data, not logic. Right for cold, high-value functions.
- device-bound
- As
seal, but the key is never in the binary, it's unwrapped at runtime by the device's secure enclave (or TPM), provisioned on first run. A copied binary cannot decrypt. The near-zero tier for extraction and off-device analysis.
GitHub Action
Two lines in your release workflow. The Action uploads the object to the Protection API, runs the passes with a per-build seed, and returns the protected artifact with a signed receipt.
- uses: veilcc/protect@v1
with:
level: seal # obfuscate | seal | device-bound
symbols: check_license,attest_device
api-key: ${{ secrets.VEILCC_KEY }}
# → writes the protected object + build-receipt.json On-prem customers point api-url at their own Protection API; the object never leaves the network.
How protection runs
The passes and the sealer run server-side, so your protection IP never ships inside the artifact. The CLI, the GitHub Action and the console are thin clients of one Protection API.
client (CLI · Action · console)
└─ upload object + options ─────────────▶ API gateway (Cloudflare Worker)
· authenticate key, enforce quota
· validate, store, meter
└─ run ──▶ protection runner (container)
· LLVM toolchain + veil-seal
· seals / obfuscates, returns
◀─────────── protected object + signed receipt ◀──────────┘ A Worker can't run the native toolchain itself, so protection runs in a container the Worker calls (Cloudflare Containers, or an external runner). The sealing algorithm stays in that image, never on the client.
Regulated and air-gapped teams run the identical runner on-prem and point the Action's api-url at it, so objects never leave the network.
Supported targets
Anything that lowers through LLVM. Verified end-to-end in our test suite today:
language C C++ Rust Swift verified in CI os macOS Linux Windows verified in CI arch arm64 x86-64 verified in CI expected Zig · TinyGo · Unity IL2CPP same object path
We list a language as shipped only once the suite proves it end-to-end, not before.
What it does & doesn't
- Defeats static analysis, sandboxed and automated AI reversing, off-device key recovery, naive patching, and cross-release crack reuse.
- Raises a determined local attacker from minutes to measured hours or days, with a per-build cost-to-break number you can verify.
- Does not make locally-run code mathematically unrecoverable: someone who executes your binary and dumps RAM during a call can still recover a sealed function. No pure-software scheme escapes that. For near-zero against a copy, use device-bound keys.
Security & privacy
The passes run on compiled objects, never source, and on the hosted API they run in memory with zero retention, we keep the build receipt, not your code. Regulated, air-gapped and defense teams run the identical Protection API on-prem. Only scan or protect binaries you own or are authorized to test.