Repository navigation
Releases
erssi Shellter Edition 2026.11.4
A security fix leads this release: an off-by-one in OTR message
reassembly could write one byte past a heap buffer, and a peer in an OTR
session could trigger it. With it come two smaller correctness fixes and
a dead-code cleanup, and the secure DCC (SDCC) added since 2026.11.3 -
DCC chat and file transfer over TLS 1.3 - has its certificate handling
hardened.
erssi Shellter Edition 2026.11.3
Fixes from a security review of the code erssi adds to irssi: /e2e
decline now holds against everything the declined peer sends afterwards,
two erssi on one keyring no longer overwrite each other's changes, and
the web frontend, the image preview, /UPGRADE, the installer and the
release tools are hardened.
erssi Shellter Edition 2026.11.2
A fix for the disk space warning of 2026.11.1: under a seccomp filter
that kills on the quota calls, as systemd's
SystemCallFilter=@System-service does, erssi was killed at its first
look at the disk.
erssi Shellter Edition 2026.11.1
Backups can be encrypted with a passphrase (erssi --backup --encrypt),
erssi warns when the disk or the quota is nearly full, and a review of
2026.11.0 brought fixes for the mouse, E2E, the first-run setup and
backups.
erssi Shellter Edition 2026.11.0
An erssi installed for the whole system is updated by its administrator:
erssi never runs the installer of another user.
erssi Shellter Edition 2026.10.9
Update from inside erssi with /UPDATE INSTALL, a short summary of each
new release in the update notice, and automatic backups. Release tools,
and tests that hold under load.
erssi Shellter Edition 2026.10.8
erssi Shellter Edition 2026.10.8
The FreeBSD packages, which 2026.10.7 does not have. erssi itself is
the same as in 2026.10.7.
+ Tests
- the live backup case that checks /UPGRADE no longer reads the
arguments of the new process: on FreeBSD, with the long paths of
a package build, ps showed only the program name there, the case
failed, and with it the FreeBSD 14 and 15 packages of 2026.10.7.
It now looks for <home>/session, which /UPGRADE writes and the new
erssi removes, with the same process still running
- in the installer's lock cases the process that stands in for a
running installer lived 30 seconds, less than a slow run of
stale-lock takes; it now lives until the case ends
For what is new since 2026.10.6 (more ready-made binaries, packages you can build again, the update notice, clickable links, backup and restore) see 2026.10.7.
Binary packages: erssi-2026.10.8-debian12-amd64.tar.xz, erssi-2026.10.8-debian13-amd64.tar.xz, erssi-2026.10.8-ubuntu24-amd64.tar.xz, erssi-2026.10.8-freebsd14-amd64.tar.xz and erssi-2026.10.8-freebsd15-amd64.tar.xz, each built twice from the signed tag and compared (identical byte for byte; FreeBSD 14.5 and 15.1), listed in SHA256SUMS, which the release key signs (SHA256SUMS.sig, namespace erssi-release). The installer checks all of it; to check by hand see install.md. erssi --update takes it from any earlier release.
erssi Shellter Edition 2026.10.7
erssi Shellter Edition 2026.10.7
Ready-made binaries for more systems, packages that can be built
again and compared, a notice of new releases, clickable links, and
backup and restore of the whole setup. Every change went through an
independent review before the release.
+ Install and update
- ready-made binaries also for Debian 12 and Ubuntu 24.04 (amd64),
next to Debian 13, FreeBSD 14 and FreeBSD 15
- a source install runs the tests of erssi only: the tests of the
release tools (the installer, the packager, the release hook)
are in the meson suite 'tooling', which the installer leaves out
(meson test --no-suite tooling) and CI and the release builds
run. Two of them stopped installs on AlmaLinux 10 and other
boxes: the pre-push interrupt case where /bin/sh is bash, and
the hostile-package cases where perl has no Archive::Tar (both
fixed too)
- when a test fails, the installer names the failed tests, where
the full results are, where to report it, and how to install the
build anyway (--no-test)
- a box where only one tool keeps the ready-made package out
(ssh-keygen, perl, sha256sum, xz, curl) is told which package
gives it, instead of only building from source
- the library packages to install are named right on Debian 12
(libssl3, libchafa0, libutf8proc2) and Ubuntu 24.04
(libperl5.38t64)
- erssi --check-update downloads only the signed tag and its
commit, about 6 KB instead of 3 MB
- shellter-install.sh --update --check --porcelain prints one line
for programs: update, current, error or unmanaged (exit codes 0,
0, 1 and 3)
- a GIT_DIR (and the like) in the environment no longer sends the
installer's git into the caller's repository
+ Packages you can build again
- utils/build-binary.sh --verify PACKAGE builds a package again
from the signed tag its MANIFEST names, with that tag's own
packager and the full test suite, and compares: exit 0 when it
is the same byte for byte, 3 when it differs (with the files and
the MANIFEST lines that differ), 1 when it cannot compare
- the MANIFEST also records the build's tools and libraries (cc,
meson, ninja, strip, xz, libs), so two builds that differ say why
- every package of this release was built twice and compared
+ Update notice
- /SET update_check ON (off by default: it contacts the erssi
repository) checks once a day, in the background, whether a
newer signed release is out, and says so once per release in the
Notices window; the new "update" statusbar item shows it
(/STATUSBAR ADDITEM -after lag update info). It runs the
installer installed with erssi, which checks the signature as
erssi --update does; nothing is installed. /UPDATE shows what the
last check found, /UPDATE CHECK checks now. The first-run setup
asks whether to turn it on. An erssi the installer did not
install, one of another user and one in Capsicum capability mode
do not check, and say why
+ Look and feel
- addresses in messages (http, https, ftp, gopher, gemini, irc,
ircs) are clickable OSC 8 links, also when they wrap over several
lines. The link is always the text that is shown; a colour change
ends an address. /SET term_hyperlinks auto|on|off; auto turns them
on in kitty, WezTerm, iTerm2, Ghostty, foot, Alacritty, Contour,
Windows Terminal, Konsole, VS Code, VTE terminals and inside tmux,
and off under GNU Screen, on a console and in terminals it does
not know (over ssh, set it on yourself)
+ Backup and restore
- erssi --backup [FILE] puts the erssi home into one file of mode
0600: config, themes, startup, scripts and their autorun links,
the E2E keyring, OTR and fe-web keys, credentials and the
Mentions log; the IRC logs only with --with-logs. It holds private
keys and passwords: keep it private. An existing file is never
overwritten, and the backup checks its own file as a restore would
- erssi --restore FILE checks every entry before it unpacks
anything (files and directories only, no absolute name, no ..,
links only inside the home), moves the old home aside to
<home>.before-restore-<time> and the backup into its place, under
the lock of erssi.lock; --dry-run lists what it would restore.
Refused while an erssi runs on the home. Works in any locale and
with non-ASCII names, and on a minimal system without cmp, diff
or ps
- also as shellter-install.sh --backup / --restore, so a new box
can restore before erssi is installed
- a running erssi holds a shared lock on <home>/erssi.lock
+ Tests
- the E2E keyring cache test no longer fails when a second ends
between its save and its load (about 1 run in 40 under load)
Binary packages: erssi-2026.10.7-debian12-amd64.tar.xz, erssi-2026.10.7-debian13-amd64.tar.xz and erssi-2026.10.7-ubuntu24-amd64.tar.xz, each built twice from the signed tag and compared (identical byte for byte), listed in SHA256SUMS, which the release key signs (SHA256SUMS.sig, namespace erssi-release). The installer checks all of it; to check by hand see install.md.
FreeBSD: this release has no FreeBSD packages: one test of the package build failed there (the test, not erssi). 2026.10.8 is the same erssi with the FreeBSD 14 and 15 packages.
erssi Shellter Edition 2026.10.6
erssi Shellter Edition 2026.10.6
Fixes from a full review of 2026.10.5.
+ Core
- /UPGRADE goes ahead only when the session file can be written:
with a full disk or quota, or a directory erssi cannot write to,
it says why and keeps its connections (before, they were all
lost and the new process started with no session); only when the
final write is what fails, the TLS connections, already quit for
the upgrade, connect again
- a script that handles the MONITOR replies (730/731) no longer
sees them printed a second time by erssi; the built-in keepnick
hides only its own targets from erssi's own print of them
- with credentials in the old external file, reading the
networks (at start, /RELOAD) no longer leaks their settings
- /HELP CAPSICUM says that in capability mode erssi waits while a
server name is looked up (a slow DNS server holds it)
+ End-to-end encryption
- docs/shellter/security.md says that the server can drop whole
messages or parts of a long one, or reorder them, unnoticed
- the keyring is read from disk again only when the file changed,
and a handshake that changed nothing writes nothing: a stranger's
handshake NOTICE costs a fraction of what it did with a large
keyring. One sender's requests are limited to 16 in 10 seconds
whatever context they name (its answers and new keys to 64)
- a peer whose ident holds '|' is no longer taken for a damaged
entry (which skipped its acceptance and rotated the key), and
/e2e export and /e2e list show its address and channel right
- the plaintext pieces of a long message are wiped before they are
freed
+ Web frontend (fe-web)
- a key fe-web makes for TLS is ECDSA P-256: a handshake, which
anyone who reaches the port can start, costs about an 18th of
one with the RSA key of older versions. A stored pair is kept
until its certificate comes within 30 days of its end or its
files are removed (see below)
- a new certificate has a random serial (a reused serial is what
Firefox refuses after a new pair), says it is for a TLS server
(serverAuth, keyUsage digitalSignature, no CA) and is valid for
825 days. A stored one is kept; to get a new one, remove
~/.erssi/fe-web-key.pem and ~/.erssi/fe-web-cert.pem: the next
start makes a new pair (pin it again in the web client)
- a stored certificate ending within 30 days is replaced when the
server starts (also at /SET fe_web_enabled OFF, then ON), and a
replaced pair is said with the new certificate's SHA-256
fingerprint; while the server runs, a daily look warns in those
30 days
- a remote address, or another local user known by uid, may open
at most 8 new connections in 10 seconds, and all of them together
200 a second (a peer that logged in before is not held by the
200); more are closed before their TLS handshake. Your own uid
is not counted. A loopback peer whose uid is not known (the BSDs,
or Linux without an answer from the kernel), which every local
user then shares, is not refused: its handshakes are spaced out
to 50 a second, oldest first. There another local user can still
delay your connection or close it while it waits, as in
2026.10.5; fe_web_socket avoids that. A connection its peer
already reset or closed is closed at once
- the web client's nicklists lose a nick that quits only in the
channels it was in, not in every channel, and joins, parts,
kicks, quits and nick changes reach them also when they are
hidden (/IGNORE, netsplit hiding)
- text the server sends in another charset (a WHOIS realname in
ISO-8859-2) reaches web clients as valid UTF-8: WHOIS text is
read in the charset /RECODE gives the network or nick, else in
recode_fallback
- the startup notices, /FE_WEB STATUS and /HELP FE_WEB no longer
present the AES-256-GCM layer over the messages as protection:
its key comes from the password, which travels inside the same
TLS connection
- /HELP FE_WEB explains the login and connection limits, what
they mean behind a proxy, and that on the BSDs and macOS every
local user is one peer on a loopback port, so fe_web_socket is
what keeps users apart there; fe-web says so when it listens on
TCP on those systems
- the copies of a login's password that fe-web and its libraries
keep (the read buffers, OpenSSL's record buffer, a refused
request, the digests of the password and the guess) are wiped;
the configured password itself stays in the settings
+ Screen
- no control character from the network reaches the terminal any
more, on any terminal type: the side panels drew the low byte of
each character of a channel name or nick on a terminal that is not
UTF-8, so a name with a Cyrillic letter could send ESC (and with it
a clipboard write by OSC 52, a new window title, ...). C0, DEL and
C1 are now drawn as '?' by the terminal output itself, also in
UTF-8 mode, and an 8-bit name is shown as its bytes there, as the
text view shows it. What now shows as '?': on an 8-bit terminal
the bytes 0x80-0x9F (ISO-8859-x is not affected, but CP125x
letters there are, such as CP1250 ś Ś ź Ź); on a Big5 terminal
the lead bytes 0x81-0xA0 (HKSCS, user-defined area); on a UTF-8
terminal bytes that are not valid UTF-8 in the text view and the
status bar (the side panels show U+FFFD for them)
- with term_notify on, a focus report the terminal sends in two
pieces (over a slow ssh link) is still read as one: it used to
become the keys ESC [ I or ESC [ O, and the focus change was
missed
+ Image preview
- a preview no longer outlives its line: after /CLEAR or closing a
window, a new line could get the address of a freed one and a
click on its link showed the picture of the old link. The
records go with their lines, and a record is only used for the
link it was made for
- a picture downloaded from a direct link with a query string (or
an extension other than jpg, jpeg, png, gif and webp) is found in
the cache again: it was saved under another name than the one
looked for, and downloaded again for every line with the link
- a download is written as <name>.part and gets the cache's name
only when complete: a download that failed or was cancelled
after /CLEAR or closing its window left its partial file in the
cache, shown as a broken picture on the next click
- the picture of a page (og:image) is found when the page writes
its address with & or relative to the page ("/img.png",
"//cdn.example.net/x.png"): it is decoded and resolved against
the page's address before it is downloaded; it must still be an
http or https address
- typing and drawing no longer lag while a picture downloads: curl
waited up to 50 ms at a time (up to half a second while data
came in) inside erssi's main loop; it is now only called when
one of its sockets is ready or its timer is due
+ Install and update
- --uninstall removes only what the installer put into the prefix:
the files its source installs recorded, the release trees of a
binary install, its links and its settings. Libraries, headers,
configuration and man pages that other software built into the
same prefix (~/local) stay, and the installer names what it left;
it used to remove the whole prefix with them. A source install by
an older installer is uninstalled from its build directory's
install log, or after one more install
- a source install takes the lock of the prefix as well, so it
cannot run at the same time as --rollback, --uninstall or another
install into the same prefix
- a lock left behind by an installer that was killed (kill -9, the
OOM killer) or by a reboot is taken over once that process is
gone; it used to stop every later erssi --update until removed by
hand. A lock of another host or PID namespace (a container) is
left alone, and the message says why, as is one made in or seen
from a FreeBSD jail, or one with no pid in it (installers before
2026.10.6 write none)
- the prefix is checked like the source directory: it must be yours
and only you may write to it and to the directory that holds it,
before its erssi is run or anything in it is changed
- a binary install stopped half-way leaves a working prefix that
says what is in it: the settings name the new release right
after the switch, a release of the same version moved aside goes
back, and old releases are renamed before they are removed, so a
half-removed one is never used again. A source install over a
binary one puts the bin/erssi link back when it is stopped; a
source install stopped inside its install step can still leave
old and new files mixed (install again to repair it)
- --keep with a number too large for the shell is refused (it used
to become --keep 1 and remove old releases)
- erssi --update on a box without git says that git is missing
instead of blaming the signature check
- a variable in the environment named like one of the installer's
own (STAGE, say, common in CI and deploy scripts) no longer makes
it remove that directory, or drop another installer's lock, when
it exits early, as an erssi --update with nothing new does
- the installer checks for the same GLib as the build (2.70, see
below) and names the version it found: an older GLib used to
pass its check and fail later in meson setup
- man erssi works for an install in the home: beside
~/.local/bin/erssi the installer links
~/.local/share/man/man1/erssi.1 to the manual of the release in
use (a file of yours there is kept), --uninstall removes the link,
and the irssi.1 an older install left is removed
+ Build and documentation
- erssi has a manual page of its own, erssi(1), installed into the
prefix's sh...
erssi Shellter Edition 2026.10.5
erssi Shellter Edition 2026.10.5
A fix from another review of 2026.10.4.
+ End-to-end encryption
- reading the keyring or a /e2e import file reserves room for each
string as long as that string, not for the rest of the file: a
keyring near its limit of 64 MB used to ask for about 256 MB at
every string, so on a box with little memory erssi could be
stopped while loading it
Binary packages: erssi-2026.10.5-debian13-amd64.tar.xz and erssi-2026.10.5-freebsd14-amd64.tar.xz, listed in SHA256SUMS, which the release key signs (SHA256SUMS.sig, namespace erssi-release). The installer checks all of it; to check by hand see install.md. A 2026.10.4 install from a package takes it with erssi --update.