Encryption
OpenPGP to a key you supply, applied on your machine for local backups.
View as MarkdownArtifacts are encrypted with OpenPGP (RFC 4880) to a public key you provide. We never hold the private half.
There is no proprietary scheme here, and that is the point: the artifact is readable by any OpenPGP implementation, on any platform, with no software of ours.
Where it happens
This is the difference that matters, and it follows from the backup's kind.
| Kind | Encrypted by | Plaintext exists on | We could read it |
|---|---|---|---|
local | Your worker, before upload | Your host only | No |
cloud | Us, after we take the dump | Our infrastructure | During the run, yes |
manual | Us, after your upload | Our infrastructure | Between upload and encrypt, yes |
For a local backup, ciphertext is all we ever receive. For the other two we necessarily handle plaintext, because we produced it or you sent it to us. Encryption there protects the archive at rest, not the pipeline that made it.
If "they cannot read it even in principle" is the requirement, that is a local backup, or a manual backup you encrypted yourself before uploading. A cloud backup cannot offer it, and we would rather say so than blur the two.
The scheme
| Property | Value |
|---|---|
| Standard | OpenPGP, RFC 4880 |
| Key type | Whatever your public key is. RSA and ECC both work |
| Session key | Generated per message by the OpenPGP implementation |
| Compression | zlib, inside the PGP message, when compression is enabled |
| Integrity | SHA-256 over the uploaded bytes, recorded on the artifact |
| Implementation | A maintained Go OpenPGP library, on the worker and on our side |
The artifact is a single OpenPGP message. gpg --decrypt opens it, and so does anything
else that speaks the standard.
What it defends, and what it does not
| Defends against | Does not defend against |
|---|---|
| Us reading your local backups | Anyone holding your private key |
| Our storage provider reading them | Someone with root on your worker, before encryption |
| A leaked archive credential exposing contents | An artifact already downloaded and decrypted |
| A stolen backup file being readable | A cloud backup's plaintext during the run |
Encryption is a confidentiality control. It does nothing about deletion, which is retention and locking, and nothing about access, which is permissions.
What happens without a key
Encryption is optional.
A backup with no public key configured produces plaintext artifacts, and nothing refuses to run, warns at run time, or flags it afterwards. The worker simply skips the encrypt step and uploads what came out of the dump.
There is no server-side encryption standing behind that as a fallback, and we do not offer one as a substitute. Server-side encryption protects against a stolen disk and nothing else, because whoever can read the bucket reads through it. Claiming it as a security feature would be misleading, so it is not claimed.
Check what you actually have:
sctl artifact get <artifact-id>Encrypted: no on an artifact you assumed was encrypted is the single most valuable output
of a rehearsal.
Key identity
Each artifact records the fingerprint of the public key it was encrypted to, so you never have to guess which key opens which file. The artifact itself carries it too, independently of us:
gpg --list-packets artifact | head -3:pubkey enc packet: version 3, algo 1, keyid 3AA5C34371567BD2This is what makes key rotation survivable: after a rotation, artifacts of the same backup need different keys, and each one says which.
Transport
Everything is TLS in addition to the above.
| Hop | Protection |
|---|---|
| Worker to our API | TLS |
| Worker to the orchestration hub | TLS, on by default |
| Worker to object storage | TLS, presigned URL scoped to one run |
| Browser and CLI to our API | TLS |
Transport encryption is table stakes and is not the interesting control here. The interesting control is that the payload is already ciphertext before it enters any of those hops on the local path.
Verifying it for yourself
The claim "encrypted before it leaves your network" is checkable without trusting this page.
Watch the bytes. The worker stages the dump and then the encrypted copy as separate
files under local_temp_path. The second one starts with an OpenPGP packet header, and the
uploaded object is that file.
Read the code. The worker is open source, and it is the one component that runs on your machine holding your credentials. The encrypt step is a few dozen lines.
Try to read an artifact without the key. Download one, and run gpg --decrypt on a
machine that does not have the private key. It fails, and it fails for us in exactly the same
way.