cccc runs code while it compiles. This page says what runs, who can allow what, and how to compile code you do not trust.
| Phase | Default | To widen it |
|---|---|---|
| Running your program | Unrestricted | --disable-ffi, --ffi-allow, --ffi-deny narrow it |
[[cccc::comptime]] code |
Safe libc only (strings, math, allocation) | --comptime-allow=<classes> |
Network downloads (#include <https://…>) |
Off | --allow-url |
| The whole process | Unconfined | --sandbox narrows it |
Grants come from the command line or from a config you approved. Source code, attributes and comments cannot grant anything, so a cloned project cannot widen its own permissions.
| Path | Needs | Notes |
|---|---|---|
Comptime fopen, system, socket, getenv, dlopen, … |
--comptime-allow=fs,exec,net,env,dlopen |
See COMPTIME_POLICY.md |
asm statements under --asm-passthru |
--comptime-allow=all at comptime |
Thunks run host assembly |
#include/#embed <https://…> |
--allow-url |
A URL already in the cache resolves without it; __has_include never downloads without it |
dlopen in the running program |
Not being under --disable-ffi |
--disable-ffi makes it return NULL |
#pragma cccc link(lib), -l |
Nothing | Loaded when the program runs, never while compiling (-c=native, -m, -E) |
#embed "file" |
Nothing | A plain file read, like #include |
--watch |
Nothing extra | Restarts cccc with the same arguments, so the same policy applies |
cccc --build build.c |
Nothing | The script is a program: RunCustom runs commands by design |
The allowlist prevents accidents. It is not a sandbox:
- Comptime loads, stores, the safe libc calls and function returns (saved frame pointer and return address) are confined to VM memory. Compiler builtins check their handle, string and buffer arguments. Libc calls you grant with
--comptime-allow(fs,exec, ...) are trusted. --buildscripts run with your full permissions.- A cloned repository's code can run when you compile it, so use
--sandboxfor code you did not write.
--sandbox confines the whole cccc process with the operating system's own sandbox:
| Allowed | Denied |
|---|---|
Reading the inputs and their directories, the working directory, -I/-isystem/-F/-L/--sysroot paths, --sandbox-read paths, the cccc config, and the system and toolchain directories |
Reading anything else, such as ~/.ssh |
| Network access | |
Writing the -o directory (or the working directory when -o is omitted in a compile mode), --deps-file, --url-cache-dir, --build-out-dir, --build-cache, /tmp and $TMPDIR |
Writing anywhere else |
Running cccc itself, the --sandbox-exec programs and, in -c=native, --build and --asm-passthru runs, the exact programs the host C compiler runs |
Running anything else, including the C compiler in every other run |
cccc --sandbox prog.c # compile and run, confined
cccc --sandbox -c=native -o prog prog.c # compile with the host cc, confined
cccc --sandbox --comptime-allow=all prog.c # comptime still cannot escape
cccc --sandbox --sandbox-read=/data prog.c # also let the run read /data-
Running from
$HOMEmakes all of$HOMEreadable, because the working directory is always readable. Run from the project directory. -
--sandbox-read=<path>(repeatable) adds a readable file or directory. It is a trust option, so a project.cccc.tomlneeds approval to use it. -
A
--buildrun probes--build-cc=(elseCCCC_BUILD_CC, elsecc). A compiler a build script sets per target withSetToolchainis only known after the sandbox closes, so name it with--sandbox-exec=<cc>and its install directory with--sandbox-read=<dir>. -
--sandbox-exec=<path>(repeatable) adds a program, or a directory of programs, the run may start. It is a trust option too. Use it for a toolchain the automatic grants miss. -
The program a sandboxed
cccc prog.cruns is confined too. Use-c=nativeand run the result outside the sandbox when it needs the network or other files. -
Child cccc processes started by
--buildand--watchinherit the sandbox. -
A
--buildscript under--sandboxcan only write its output directory, so steps that write elsewhere or run other commands fail. -
--sandboxcannot be combined with--allow-url. -
If the platform cannot enforce the sandbox, cccc stops with
error: --sandbox unavailable: …rather than running unconfined.1
Put sandbox = true in ~/.config/cccc/config.toml to confine every run. A project config can turn it on but cannot turn it off. See CONFIG.md.
cccc --sandbox prog.crather than a plaincccc prog.c.- Leave
--comptime-allow,--allow-urland the config trust prompt (.cccc.toml;--trust-hashmakes any later edit ask again) unapproved until you have read what they ask for. - Do not run
cccc --build build.con it without--sandbox: the script runs as a program.
Footnotes
-
macOS uses
sandbox_init; Linux uses landlock (kernel 5.13 or newer) for files and exec, plus a seccomp filter that refuses inet sockets. Reads usefile-read-datarules on macOS and landlock read rights on Linux; file names and metadata stay visible. The programs allowed to run come fromcc -###and-print-prog-name, and the compiler's own directories from-print-search-dirs; a run that never reaches the compiler skips this probe. When the probe finds no programs, cccc warns and allows the toolchain directories instead. When an allowed program is a script (Xcode'sasis a zsh script), its#!interpreter andrealpath,dirnameandbasenameare allowed too: macOS lets the interpreter start only as a script's interpreter, while Linux allows it as an ordinary program. On Linux the readable part of/etcisld.so.cache, theld.so.conftree,nsswitch.conf,localtime,passwdandgroup. ↩