Skip to content

Security

Finn Bear edited this page Sep 24, 2024 · 28 revisions

Introduction

bitcode is designed to decode arbitrary, possibly corrupt or malicious, input without misbehaving.

Panics

bitcode should only panic due to programmer error or resource exhaustion, for example:

Undefined Behavior

bitcode should not trigger exploitable undefined behavior, regardless of the input, OS, or architecture.

While bitcode does intentionally invoke undefined behavior on certain architectures, it is for measurable performance benefit and precautions have been taken to make it safe (in the colloquial sense). We're looking into replacing it with assembly or waiting until Rust adds a new intrinsic.

Out of Memory

bitcode avoids allocating memory without consuming part of the input, so the total memory used is proportional to the input size. Consider imposing a size limit on messages before decoding.

However, you need to avoid enum's with variants of very unbalanced sizes:

#[derive(Decode)]
enum Message {
    Smol,
    Chonk([u8; 1_000_000_000]),
}

In this case, an small input buffer could contain many instances of Message::Smol, each of which would need to allocate 1GB, the size of Message.

bitcode does not handle allocation errors that do occur.

Non-termination

bitcode functions should always terminate, provided PartialEq, Ord, etc. terminate

Fuzzing

bitcode has a fuzzer that runs in CI.

Reporting vulnerabilities

Please report confirmed/suspected vulnerabilities here :)

Clone this wiki locally