As soon as I saw the announcement for a new Binary Golf Grand Prix challenge, I knew this was the time I’d finally commit to entering.
Binary Golf Grand Prix 4 begins now!#BGGP4 Theme: "Replicate"
— Binary Golf Association (@binarygolf) June 23, 2023
Challenge Announcement:https://t.co/AX83D5e4xz pic.twitter.com/eRLnUsYXhC
Creating a self-replicating file under size constraints just seemed like such a cool idea, and I knew it would give me an excuse to research something I’d been curious about.
I thought trying a VSCode Workspace file would be fun because it’s a spin on the idea and fits in the “this file isn’t supposed to be executable…” category. Plus after seeing VSCode’s workspace trust warning so often, I was curious if I could make it happen.
My submission is a single json file named x.code-workspace
, where if you open it in VSCode, it will create a copy of itself named “4” and print the number “4”. Contents follow, repo is here.
{"folders":[{"path":"."}],"tasks":{"tasks":[{"label":"x","type":"shell","command":"cp x* 4;ls 4","runOptions":{"runOn":"folderOpen"}}]}}
How VSCode Workspace files work#
Starting off, I knew there were ways to run tasks in the background with VSCode… and I knew it was associated with workspaces, but I didn’t know how the two concepts were related.
So I started by reading up on Workspaces, Workspace files, and tasks.
The upshot is that workspace files are like a single-file version of the workspace folder, a directory named .vscode/
at the root of the workspace.
After a bit of reading and experimenting, I figured out the basic structure of a workspace file. And soon after I figured out how to run a task as soon as the Workspace was opened to get an initial proof-of-concept:
{
"folders": [
{
"path": "."
}
],
"settings": {},
"tasks": {
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "cp x.* 4 && echo 4",
"runOptions": {
"runOn": "folderOpen"
},
"presentation": {
"reveal": "always",
}
}
]
}
}
Self-Replication#
The trick is the runOn: "folderOpen"
bit, which allows us to run a shell command, but getting execution on opening usually requires a dialog asking the user if they want to trust the workspace:
The warning does say that doing so may automatically execute commands, so people should know that’s what’s going to happen, right?
But I figured that was still acceptable for the purposes of the challenge because there are some circumstances where a user doesn’t see a warning at all.
Since the extension .code-workspace
is required for the file to be treated as a workspace file, I named the file x.code-workspace
, and then copy by globbing on the name in the shell command.
The rules didn’t specify whether the filename mattered, so I think this is fair because you could really run any shell command; this is just to reduce size.
Size golfing#
At this point, the only remaining goal is to reduce size while maintaining functionality.
So clearly I went through several iterations, but the basic steps were:
- Removed all optional fields
- Tried removing “non-optional” fields, though
version
was really the only one that VSCode’s linter said was mandatory but actually wasn’t - Read the parsing code to see if I could take any other shortcuts (none that I saw)
- Removed all unnecessary whitespace
- Golfed down the copy command itself based on another BGGP writeup: https://rap.sh/Shell_Script_Golf
In the end I got it down to 136 bytes, not bad for a JSON file that puppets a behemoth Electron app into copying itself!
Too much magic (and trust)#
Workspace trust has been on my mind for a while because I’ve seen this warning a ton, and I always felt that the binary decision on “Do you trust the authors of these files” is insufficient and kinda unactionable.
As a user, I’d like to see a few more data points and maybe have more than just a binary decision of “yup, run arbitrary commands on my machine” or “no, please fall back to just being a text editor”. I understand that there’s a ton of things other than just running shell commands on open that could be abused, but I still don’t like it.
Also it turns out that there is an Allow Automatic Tasks
setting that can control whether tasks can automatically run (mentioned in this GitHub issue), but it’s always been on
in my testing, so trusting the workspace is the only hurdle I found from a default install.
Further, one of the specific scenarios where no trust windows are shown are if a user is working in an already-trusted workspace and opens the workspace file.
When you do this, VSCode will tell you it is a workspace file, and even helpfully give you a button to treat it as such… which in this case triggers the file to copy itself.
One of my complaints about a lot of modern dev work is there’s “too much magic”, meaning there’s a lot going on behind the scenes that devs “shouldn’t need to worry about.”
I don’t know about you, but I don’t like being told “don’t worry about the man behind the green curtain” when I’m developing. I want to see what’s going on under the hood.
All in all, it is a tricky situation because the automatic background task stuff is working as intended and is super helpful for development… but it could also be risky.
Shout-outs#
Thanks to netspooky, tmp.out, and everyone else that helped with BGGP; I had a lot of fun!
Also thanks to the VSCode team, this isn’t meant to be a dig at them at all. I think VSCode is awesome, and I love the open-source approach they’ve taken.
Follow me on Twitter or Mastodon for more occasional random hacks!