Security model
Walis executes arbitrary shell. That single fact drives every decision below.
Who can run what
| Layer | Control |
|---|---|
| Sign-in | off by default; turn it on before exposing the service |
| Roles | admin, operator, viewer |
| Per job | each job has a view role and a run role |
| Plugins | installing requires admin — a plugin is code |
A job you cannot view returns 404, not 403, so its existence is not disclosed.
Build isolation
Builds run as the service account, which means they could otherwise read Walis's own database — where password hashes, API key hashes and cloud credentials live. So by default every step is wrapped in sandbox-exec denying reads and writes to the data directory, and ConnectionStrings__* is stripped from the build environment.
You can add more denied paths, and restrict jobs to an allow-list of working directories.
This is not full isolation — same user, same machine. It stops the realistic problem (a build script casually reading the database) rather than a determined attacker who already runs code as you.
Plugins
Plugins return a string; Walis runs it. The sandbox (Jint, no I/O, four resource limits) matters, but the real control is that you can read the produced script before installing, and that capabilities must be declared and approved.
Backups
Archives contain password hashes and cloud keys, so a passphrase is mandatory as soon as any remote target is configured. Encryption is OpenSSL-compatible so restoring never depends on Walis.