
Obel Mono Masked: A typeface that keeps a secret
Paste an API key while you’re sharing your screen, and everyone on the call has it. So does the recording, the screenshot in the bug report, and any agent that works by looking at your screen.
以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。
Paste an API key while you’re sharing your screen, and everyone on the call has it. So does the recording, the screenshot in the bug report, and any agent that works by looking at your screen.
You could fix that inside one app. But there’s one thing nearly every app on your screen already uses: a font. So I put the fix there. Paste a key in here:
No plugin, no extension, nothing for the app to know about. Here’s how a font can do that.
We think of a font as a set of drawings. It’s also a set of rules. Each time text appears, a piece of your system called a shaper reads the font’s rules and may swap one glyph for another. It’s how a font joins f and i into a ligature.
Nothing says a rule has to be about typography.
The font’s rulesSwap glyphs
The screen showsghp_aB3dEFGHiJ7kLm
It can’t look ahead
The obvious plan is to wait for the whole key, then hide it. But text arrives one character at a time, typed by you or written by a model. Waiting means the key sits there readable, then flickers away.
So every rule looks only backward. The moment a character is drawn, it’s final, and nothing on screen ever changes. Stop the stream anywhere, and what you see is already right.
Looking only backward creates a problem. A shaper has no memory. All a rule can read is the glyphs behind it. So how does a character further along know it’s inside a key?
The font leaves itself a note, and hides it in plain sight.
=underscoreunderscore.sec.alnum.loweran underscore“a key starts here”Two different glyphs with the same drawing. You can’t tell them apart. The rules can.
When the font sees ghp_, GitHub’s prefix, it swaps that underscore for its twin. From then on, the note does the work:
The prefixes are the start of a key itself, like ghp_ or sk-ant-. The rest are the words around a secret, whatever it looks like: GITHUB_TOKEN=, "password": ", Authorization: Bearer , --api-key=.
Nothing here, so the font leaves it alone.
A font that hid your code would be worse than none, so most of the craft is in the restraint. Code is full of names that begin like a key. If the window looks like an ordinary word, nothing happens. Public keys are left alone on purpose. And a mask ends at the first character that couldn’t be in a key, so it never swallows the rest of the line.
It’s the mark a password field draws, and it looks like nothing you’d find in a key. An asterisk would suggest the key contains asterisks. So the dot is larger and lower than a bullet, and solid where o, 0 and ° are hollow.
periodbulletozerodegreeasteriskthe maskWhat it can’t do
It changes pixels, not text. That’s the deal, and it’s worth being clear about.
It also works one line at a time. If a key wraps onto a second line, there’s nothing behind it on that line to go on, so it shows. And if a key has already been seen, rotate it. No font can take that back.
Obel Mono Masked is always on, for apps with no font settings, like iTerm2, where you also turn on Use ligatures. It’s meant for Terminal.app and Warp too, but we haven’t tested those yet. Obel Mono has it as a switch, ss01, for apps that let you set one, like Ghostty, VS Code and Zed. The download page has the setting for each app.
To check, run this in your terminal. With masking on, you’ll see dots:
printf 'OBEL_TOKEN=masked-when-on\n'
Apps that don’t shape text at all, like Alacritty, can’t run any font rules, so they show keys as typed.
These are chained contextual substitutions in OpenType’s GSUB table, with a backtrack context only. Simplified, the rules for ghp_ read:
the note: the _ that ends GitHub's prefix
sub g h p underscore' by underscore.sec.alnum.lower;
the dots: a note and four characters behind, or a dot behind
sub underscore.sec.alnum.lower @alnum @alnum @alnum @alnum @alnum' by secret.mask.alnum; sub secret.mask.alnum @alnum' by secret.mask.alnum;
The quote mark sits on the glyph being replaced; everything before it has already been drawn. The real rules are generated from a data file and compiled into the font.
In Obel Mono Masked they live in ccmp, which every shaping renderer applies and no editor setting turns off. In Obel Mono they live under ss01.
Before release, the rules ran through the three engines that shape nearly all text on screen, HarfBuzz, CoreText and DirectWrite, on thousands of keys and near-misses. All three drew the same glyphs.
I make things like this. I’ll share the next one on at @codycollier.
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。