Skip to content

Releases: kldzj/sigillo

sigillo@0.17.2

Choose a tag to compare

@github-actions github-actions released this 30 Sep 10:30

This release fixes security issues. Update your instance:

npm i -g @kldzj/sigillo
npx @kldzj/sigillo@latest self-host

Fixes

  • Server actions and API routes check the types of their inputs before they reach a database query, so a value from the browser can only ever be looked up by its exact ID. This closes a security issue in accepting invitations.
  • The login provider's sign-out sends the browser only back to its own app, never to an address a registered client names.
  • Only a login from signing in with Google approves a CLI login, so a CLI login can no longer approve the next one and outlive its 30 days. A browser login from before sign-ins were told apart needs signing in again for it.
  • Deleting a secret takes only a name the set routes accept, or the name of a secret that already has one from before names had rules.
  • A passkey approval looks a passkey up only by an ID that is a string.

A security advisory with details follows.

sigillo@0.17.1

Choose a tag to compare

@github-actions github-actions released this 29 Sep 15:23

The Linux x64 CLI runs on every x86-64 CPU again.

Upgrading

npm i -g @kldzj/sigillo

Only the CLI changed: your instance doesn't need an update.

Fixes

  • The Linux x64 binary crashed on CPUs without AVX-512, such as AMD Ryzen 5000 and most Intel desktop CPUs. CI built it for its own machine's CPU, so it died with an illegal instruction: exit code 132, or exit code 1 without a message through npm and npx. Every binary is now built for its architecture's baseline CPU. 0.16.0 and 0.17.0 have this problem on Linux x64, since whether a build used AVX-512 depended on which CI machine made it; npx @kldzj/sigillo self-host wasn't affected, since it runs in Node.
  • The npm launcher names a crash of the native binary, such as error: sigillo was killed by SIGILL, and exits with 128 plus the signal's number, as a shell does.

sigillo@0.17.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 15:00

Workload identity for GitHub Actions and Kubernetes, warnings before tokens and trust rules expire, key rotation and encrypted backups. The docs are rewritten, and a project's tabs are simpler.

Upgrading

npm i -g @kldzj/sigillo
npx @kldzj/sigillo@latest self-host
  1. A project's tabs changed. Tokens is now Machines, Event Log and Read Log are one History tab, and the organization's Members, which was the Access tab in every project, is in the sidebar. Bookmarks to the old pages stop working.
  2. New values are encrypted in a new format from the update on, bound to their environment and name. Existing values stay readable as they are; a key rotation moves them over.
  3. On Cloudflare's free plan, a dashboard page fails now and then with error 1102: a page often needs more than the free plan's 10 ms of CPU. Everything else works. Workers Paid, $5 a month, avoids it. self-host now says so on a new deployment.
  4. ENCRYPTION_KEY must be 32 bytes. Keys made by self-host always are. If you set a shorter one by hand in the Cloudflare dashboard, the instance stops decrypting after the update until you replace it.
  5. sigillo audit verify on a protected environment asks for your passkey, like reading its values, and the export shows in its read log.
  6. The update applies three database migrations to the app. They only add tables and columns.

Highlights

Workload identity

GitHub Actions jobs and Kubernetes pods read secrets without a stored token. An org admin adds a trust rule on a project's Machines tab, with their passkey: the issuer, the audience, the exact subject and claims, and the environments it grants. The job exchanges the JWT its platform issues for a token of one hour, and the CLI does that on its own when no token is set:

permissions:
  id-token: write
steps:
  - run: npx @kldzj/sigillo run -- ./deploy.sh
    env:
      SIGILLO_API_URL: ${{ vars.SIGILLO_API_URL }}
      SIGILLO_PROJECT: ${{ vars.SIGILLO_PROJECT }}   # the project's ID
      SIGILLO_ENVIRONMENT: prod

In Kubernetes, the pod reads a projected service account token from SIGILLO_OIDC_TOKEN_FILE. External Secrets Operator works through its Doppler provider, with the controller's DOPPLER_BASE_URL set to your instance. The read log names the job or pod behind each read. See workload identity.

Warnings before tokens and trust rules expire

A token or trust rule warns in the last quarter of its lifetime, and at most its last 14 days: on the Machines tab, in a banner on the dashboard, in two response headers, and as one line on stderr from the CLI, so it shows in CI logs:

warning: this API token expires on 2026-10-13 (in 3 days). Regenerate it on the project's Machines tab; the old value then keeps working for up to 7 days.
  • Regenerate a token to give it a new value and expiry. It stays the same token, with its name, scope and history, and the old value keeps working for the grace period you pick, up to 7 days but never past its own expiry. The tab shows whether anything still uses the old value, and Stop ends it early.
  • Renew a trust rule to give it a new expiry. It keeps its ID, so nothing changes in your workflows or in External Secrets Operator. The renewal first shows how the rule was used, and the admin who renews it becomes the admin its tokens act for.

See before a token expires and expiry headers.

Key rotation, and purging old values

npx @kldzj/sigillo self-host --rotate-key

gives your instance a new encryption key. It re-encrypts every stored value on your machine, through the D1 API, then removes the old key from the worker and ~/.sigillo/selfhost.json. Stopped halfway, the next run finishes it.

New values name their key and are bound to their environment and name, so a value copied elsewhere in the database no longer decrypts; a rotation moves the older ones over. Org admins can purge an environment's old values on its History tab, with their passkey; sigillo audit verify still finds the history intact afterwards.

Encrypted backups

npx @kldzj/sigillo self-host --backup
npx @kldzj/sigillo self-host --restore sigillo-2026-10-01T08-00-00Z.backup.age

A backup holds both databases in one file, encrypted with a backup key kept in selfhost.json, and no encryption key. A restore imports into new databases, checks every row of their history, and only then switches both workers to them. See backups.

Rewritten docs

The docs at sigillo.kldzj.dev have a quick start, pages for running an instance (updating, backups, key rotation), a security section (how Sigillo protects your secrets, protected environments, the signed history, a hardening checklist and what to do when someone leaves), and reference pages for configuration and the REST API.

Smaller changes

  • The History tab lives at …/history: the old /event-log URL matched a rule of EasyPrivacy, on by default in uBlock Origin Lite, which blocked revealing old values and purging them.
  • self-host checks that a new worker's keys decrypt a stored value under every key in use before it recreates one, so a missing ENCRYPTION_KEY can't make stored secrets unreadable.
  • The Manage access dialog could open with Full access checked for a restricted member, so saving without changes removed the restriction.
  • The device login page returns to code entry when approving fails.
  • A value removed from the database without a purge now breaks the history: sigillo audit verify, a restore and the History tab all report it.
  • self-host --restore says exactly what it checked, compares the history with what sigillo audit verify saw on your machine, needs --yes without a terminal, and stays unfinished until both workers use the restored databases. Backups no longer hold sign-in ID tokens.
  • sigillo run exits 128 + N when its command is killed by signal N (143 for SIGTERM, 130 for Ctrl+C), so Docker, turbo and make don't report a failure.

The key check, the access dialog, the device login page and the exit codes come from upstream Sigillo by Tommy D. Rossi, which this fork is based on.

sigillo@0.16.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 06:22

Passkeys for production: reading or changing a protected environment now takes a passkey, and so do admin actions in an organization that has one. A stolen browser session or CLI login alone can no longer read production, change it, or invite someone. The docs moved to sigillo.kldzj.dev.

Upgrading

npm i -g @kldzj/sigillo
npx @kldzj/sigillo@latest self-host
  1. self-host deploys the release of its own version, and only the exact bundle that version was released with: CI records the bundle's SHA-256 in the npm package, and self-host refuses anything else. Use @latest to update to the newest release. It also refuses to deploy a version older than the one your instance runs, unless you pass --allow-downgrade.
  2. Add your passkeys under user menu → Passkeys before you mark an environment Protected.
  3. API tokens stop reading protected environments as soon as the update is live: only machine tokens can (see below). If CI or a server reads one, sign out and in again, add a passkey, create a machine token on the Tokens tab and switch the job to it. An instance without protected environments isn't affected.
  4. Logins end 30 days after their sign-in, however often they're used. The CLI then asks you to run sigillo login again.
  5. sigillo run skips secrets named like PATH, NODE_OPTIONS, LD_PRELOAD, GIT_PAGER or npm_config_registry, in any case, and says so. Pass --allow-env NAME for one you need.
  6. Scripts that run sigillo projects delete or environments delete without a terminal need --yes: in a terminal, both now ask you to type the project's name or the environment's slug.
  7. The update applies four database migrations to the app and one to the login provider. They only add tables and columns.

Highlights

Passkeys guard protected environments

Add passkeys under user menu → Passkeys: a laptop's fingerprint reader, a phone, or a security key. In an environment marked Protected:

  • In the browser, revealing, copying, downloading, saving or deleting a value asks for your passkey on the spot. One approval covers that browser for 15 minutes.

  • In the CLI, reads such as sigillo run and secrets get, and changes such as secrets set, print a link and a code, and wait while you approve on /approve with your passkey:

    This environment is protected: approve with your passkey.
      Open https://secrets.acme.com/approve and enter BCDF-GHJK
    Waiting for your approval...
    ✔ Approved for 15 minutes
    

    The code is typed, never part of the link, so a link someone sends you approves nothing.

  • Deleting or renaming a protected environment, or its project, is up to an org admin with their passkey.

The first passkey takes a Google sign-in from the last 5 minutes. Once your organization has an admin with a passkey, an admin also approves each member's first passkey on the Access tab; a member of several organizations with protected environments needs an approval from each. Leaving an organization doesn't get around its admins: they still approve the first passkey of someone who left, and an invite link made before doesn't bring them back. After that, adding or removing a passkey takes one you already have, in the same browser or with a code on /approve from another device. Admins see every passkey added or removed, and can reset a member's passkeys, which signs them out. A sole admin who lost theirs:

npx @kldzj/sigillo self-host --reset-passkeys you@acme.com

Admin actions, CLI logins and tokens

  • In an organization with a protected environment, every admin action takes a passkey, covering 5 minutes: invites, roles, a member's projects, removing members, auto-join, an environment's min role or protection, resetting passkeys, machine tokens and deleting the organization.
  • Once you have a passkey, approving a CLI login on /device and creating an API token take it too, since both outlive the session that makes them.

Machine tokens

CI and servers can't use a passkey. An org admin creates a Machine token on the Tokens tab with their passkey: it reads and changes protected environments without one, expires after 90 days at most, and stops working when its creator is no longer an admin. Making one takes the passkey even before anything is protected, so a stolen admin session can't leave one behind for later. Other API tokens can't use protected environments. The Tokens tab also shows the IP each token was last used from.

Docs at sigillo.kldzj.dev

The docs are a static site of their own now, with a new home page. Instances serve only the app: / opens the dashboard, and every page asks search engines not to list it.

Deleting takes the name, typed out

Deleting an organization, a project, or an environment that has secrets now asks you to type its name or slug, and says what goes with it: its projects, environments and how many secrets. The server checks the typed name too. An organization's settings moved out of the project tabs into the sidebar, under Organization settings, and a project's Settings tab now renames or deletes that project.

Security

  • No page of an instance or its login provider can be embedded in another site, responses are never cached, and browsers are told to use https only.
  • A page or button that fails in the database says something went wrong instead of showing the query, its parameters and a stack trace.
  • The API refuses a change sent with your browser's session from a page on another origin.
  • An API token acts with its creator's current access: it stops when they're taken off the sign-in list, or can no longer open its project. Only a token's creator or an org admin can delete it.
  • Someone removed from an organization stays removed: auto-join doesn't add them back, nor does an invite link made before. A demoted admin's invite links stop working. Anyone can leave an organization under Organization settings.
  • Sign-in and login endpoints of the app and its login provider are rate limited per IP. A CLI login's device code is stored as a hash, so reading the database during a login doesn't hand out the session.
  • The login provider shows its consent screen the first time an app asks, instead of skipping it for clients picked by their redirect address, and its error page links only to your instance.
  • A member who can open only some projects doesn't learn the others' names, and no longer ends up in a redirect loop. Names of organizations, projects and environments can't hold control characters.
  • A link to /logout on another site asks before signing you out.
  • better-auth endpoints the app never uses are off, so nobody can rename themselves to appear under someone else's name.
  • The history marks changes from before it existed as adopted, and sigillo audit verify counts them. A value starting with a byte order mark no longer breaks the history, and pages name authors as the history records them. The Hardening page says what the history can't prove.
  • sigillo run masks a secret that contains another one, such as a database URL with its password. sigillo login says which account it logged in as, no longer lets SIGILLO_API_URL replace your saved server, keeps ~/.sigillo/config.json readable only by you, and opens only plain web addresses. Messages and names from the server print without terminal control characters.
  • The release workflow pins its GitHub Actions to commits and npm to one version, and a new push no longer cancels a release halfway.

Also

  • Git worktrees pick up the right project and env, also in subfolders: a worktree uses its main checkout's setup at the same relative path, and a setup saved inside the worktree wins. From a worktree, save it for every worktree at once:

    sigillo setup --scope ~/code/repo --project website --env dev
  • Each project remembers the environment you last opened.

  • The Sessions page asks a login older than a day to sign in again instead of failing.

  • Login and approval codes read XXXX-XXXX everywhere, with or without the dash when you type them.

  • IPv6 addresses fit their columns, selects size to their content, and select lists are readable in dark mode.

  • On a phone, the menus in the navigation drawer open their links again.

  • The CLI banner on the secrets page shows npm install -g @kldzj/sigillo and your instance's URL.

  • New environment slugs are lowercase letters, digits and dashes.

sigillo@0.15.0

Choose a tag to compare

@github-actions github-actions released this 27 Sep 20:58

Hardening for self-hosted instances: signed sessions, a sign-in allowlist, a recorded and verifiable history of who read which secret, and an encrypted deploy file. The new Hardening page in your instance's docs (/docs/hardening) walks through all of it.

Upgrading

npm i -g @kldzj/sigillo
npx @kldzj/sigillo self-host
  1. Everyone runs sigillo login once. Session tokens are signed now, and CLI logins from before are refused with not signed in, or the session expired: run sigillo login. API tokens keep working.
  2. self-host offers to encrypt ~/.sigillo/selfhost.json with a passphrase, and asks for it on every run after that. Runs without a terminal, such as CI, read it from SIGILLO_SELFHOST_PASSPHRASE.
  3. The update applies two database migrations to the app and one to the login provider.

Highlights

Protected environments and the Read Log

Mark an environment Protected on the Environments tab. Every read of its values is then recorded before they leave the server: who, when, which secrets, how, and from which IP. A read that can't be recorded fails. Org admins see the reads on the new Read Log tab, and turning protection off is recorded too.

The secrets page and the event log no longer load values up front. A value reaches the browser when someone reveals, downloads or copies it, so the Read Log shows who looked at which value, not who opened a page.

A history you can verify

Each environment's secret changes and reads form hash chains, signed by your instance. Editing, removing or adding a row in the database breaks the chain at that row. Org admins check it with:

sigillo audit verify -c prod
✔ changes: 42 rows, intact
✔ reads: 7 rows, intact

The CLI keeps the newest row of each chain in ~/.sigillo/audit.json, so the next check also notices rows removed or rewritten since. Changes from before the upgrade join the chain on their environment's next change or check.

Limit who can sign in

npx @kldzj/sigillo self-host --allowed-users acme.com,ops@partner.io

Only people whose verified email is on the list, or at a listed domain (not its subdomains), can sign up or sign in, in the browser and with the CLI. The app and its login provider both check it, and someone taken off the list is signed out on their next request. A refused sign-in explains why and leads back to your sign-in page.

Sessions

User menu → Sessions lists every browser and CLI login signed in as you, with its device, IP address and sign-in time. End one you don't recognize, or all but the current one. An ended session stops working on its next request. The CLI now identifies itself as sigillo-cli/<version>.

API tokens expire

New tokens last 7, 30, 90 or 365 days (90 by default), and the Tokens tab shows when each was last used. Tokens made before keep working and are marked Never, so you can replace them.

Encrypted deploy file

~/.sigillo/selfhost.json holds the keys to your deployment, so self-host now encrypts it with a passphrase (scrypt and AES-256-GCM). Keep the passphrase in your password manager and the file where it is. Change it with:

npx @kldzj/sigillo self-host --change-passphrase

Security

  • Session tokens stored in the database no longer work on their own: the CLI and API only accept the signed form, which needs your instance's secret.
  • The login provider's OAuth tokens are encrypted in the database.
  • Signing in with a raw id_token is refused; sign-in always goes through the redirect.
  • better-auth and its OAuth provider plugin are on 1.7.6.

Fixes

  • sigillo login starts a new login even when a token is already saved, so a login that stopped working can be replaced.
  • A failed or refused sign-in no longer ends on the login provider's health check.

Published to npm through trusted publishing, with provenance.

sigillo@0.14.1

Choose a tag to compare

@github-actions github-actions released this 27 Sep 14:42

The first release of kldzj/sigillo, a maintained fork of remorses/sigillo. There is no hosted service: every instance runs on your own Cloudflare account, including its own Google login.

It contains everything on upstream's main, including security fixes upstream has not released yet (its latest release is 0.13.0), plus the fixes listed below that are only in this fork so far.

Install

npm i -g @kldzj/sigillo

or the native binary:

curl -fsSL https://raw.githubusercontent.com/kldzj/sigillo/main/app/public/install.sh | bash

If you installed 0.14.0, update: it lacks the CLI token protection described under security fixes.

Highlights

Your own instance, with its own login

npx @kldzj/sigillo self-host
  • Deploys two Workers with their D1 databases: the Sigillo app and its own login provider (<name>-auth), so nothing depends on sigillo.dev or auth.sigillo.dev.

  • People sign in with Google through your provider. A new deployment asks for a Google OAuth client and prints the redirect URI to register. Pass --google-client-id and --google-client-secret for non-interactive runs.

  • New deployments get their own random ENCRYPTION_KEY, separate from the secret that signs sessions. To choose it yourself, set SIGILLO_ENCRYPTION_KEY on the first deploy:

    SIGILLO_ENCRYPTION_KEY="$(openssl rand -base64 32)" npx @kldzj/sigillo self-host

    Back up ~/.sigillo/selfhost.json: a database backup can't be decrypted without it.

  • Re-runs update both Workers and never rotate a secret. A deployment made with upstream's self-host keeps its provider, so nobody gets a new login.

No default server

The CLI never falls back to sigillo.dev. Log in to your instance once:

sigillo login --api-url https://sigillo.<your-subdomain>.workers.dev

API tokens for several environments

A token can cover dev and preview without also granting prod. Project-wide tokens still mean every environment.

Project names

--project accepts a name as well as an ID, and a wrong one is reported as a missing project instead of a missing env:

sigillo run --project website --env dev -- npm start
sigillo setup --project website --env dev

Security fixes

From upstream's main, not in an upstream release yet:

  • Device login needs an explicit Approve, so a /device link someone sends you can no longer sign them in as you.
  • .env downloads single-quote every value, so source .env can't run a command hidden in a secret. Secret names are validated.
  • The CLI never sends your saved token to a server other than the one it was saved for, and never follows a redirect with it. run --mount writes the file owner-only and removes it on SIGTERM and SIGHUP.
  • Project access and admin-only environments are enforced everywhere, not only on the secrets API, and changes apply on the next request (remorses/sigillo#12, #14).
  • Deleting a project no longer unlocks every project for members limited to it, and the secrets list no longer shows names from environments you can't read.
  • An API token used on an admin-only environment needs its creator to still be an org admin.

Fixes

  • Deleting an API token or a user no longer deletes the secrets they wrote (remorses/sigillo#10).
  • Signing in no longer fails with Unable to parse URL when the login provider still has a session but hasn't been allowed for the instance yet (remorses/sigillo#16).
  • Changing a member's role in the access table saves again.

Only in this fork so far:

  • Only one organization can claim an auto-join email domain.
  • Removing a member also revokes the API tokens and invite links they created, and sigillo logout signs the session out on the server.
  • sigillo environments rename works with only --name or only --slug (remorses/sigillo#21).
  • self-host exits with status 1 when a deploy fails, so CI notices.

Published to npm through trusted publishing, with provenance.