Got a heads-up from OpenAI that they'd invalidated my token because I'd exposed it publicly! Oops. This isn't the first time I've done it, but this will be the first time I take a computational approach towards avoiding it.
(tl;dr use the code and brief instructions in this gist.)
I shared three secret tokens actually, about 24 hours ago when I pushed
an update of my .bashrc
to a public repo. This repo was
there for a long time, but I guess I'd been careful about pushing
anything sensitive to it: Specifically, I've been using this code block
to separate sensitive environment variables out from others:
But I guess I mistakenly moved towards keeping everything in a single "run control" (.bashrc) file.
To their credit, OpenAI alerted me before anyone else, and in fact Netlify and GitHub hadn't detected it after the first 24 hours. Not that it's their job! But kudos in any case to OpenAI.
I removed all the tokens from the other two providers, and made the
.bashrc
repo private for now.
I'd first heard of keeping secrets in public repos by encrypting them in this section of ThePrimeagen's "Developer Productivity" course, but I clearly haven't put that into action. The command he uses for encrypting or decrypting is
after having installed ansible. Easy enough! As a bonus, the algorithm it uses is probably quantum-safe. 🤖
There are several other viable options for two-way encryption of secrets, Mozilla's SOPS being one, FYI.
Now, how to abort and alert when committing code which contains
unencrypted secrets?
This DevOps StackExchange question
seems to be a good start. Let's see if I can get a
pre-commit
hook to do this for my
.bashrc
file:
If I pop that in the repo where .bashrc
is and try to
commit it without encrypting it first, it stops me and displays:
That's pretty awesome! Let's make it a little more foolproof by making this pre-commit run for all commits to local repos:
How to automate the encryption of these secret files, though? There's no
such automation in
the StackExchange answer, but there is a bash script provided to encrypt or decrypt manually.
What's more, there's an improved version of that script in
this blog post, the improvement being that it skips any already encrypted files which
match the FILE_PATTERN
instead of breaking out of the
while
loop.
Let's incorporate the relevant logic into our globally installed pre-commit hook:
I've also put the vault password in a new file
~/.vault_password
so I don't have to enter it for every
ansible-vault
command. This works beautifully on commit,
and won't try to encrypt files which are already encrypted:
The pre-commit hook will work for making sure the secrets are encrypted,
but I actually want to immediately decrypt those secrets once the commit
is completed, so I can use them locally, modify them, etc. If I copy
pre-commit
to a file post-commit
and make
these changes, this should accomplish it:
Now, when .bashrc
is unencrypted, this is what happens on
commit:
The secret file is unencrypted and there's an unstaged change to it. This is as expected, since the post-commit hook decrypted it. Not a 100% perfect solution since I'll constantly have unstaged changes showing for my secret files, but I'm willing to live with it.
One flaw I can't live with is that if I check out a different branch or commit of this repo, the secrets-containing files will be encrypted. This will also happen when pulling from a remote repo.
I'm pretty sure the quick solution for this is:
It works perfectly for checkout, but I haven't tested it for pull/merge yet.
I think this will suffice for automatically encrypting secrets on
commit. The biggest point of failure is FILE_PATTERN
, which
I'll have to be mindful of and modify as needed.