A posture pass against dejima's, which turned up one thing worth fixing and three worth stating.
The ntfy token was in argv
/proc/<pid>/cmdline is world-readable, so -H "Authorization: Bearer $tok" hands the token to every local account for the length of the call. On the systemd path this runs as root on a machine that may well have other people on it. The heartbeat URL has the same problem and is easy to miss, because an Uptime Kuma push URL carries its token in the path — the URL is the credential.
Both now go to curl through a config on stdin, which no other process can read. Verified against a local listener: the header arrives and the token is absent from the command line. The body and title stay in argv, being counts and a hostname.
A token containing a quote or backslash is refused. A curl config is not shell, but it is still a parser being handed a value from a file, and check_url already closed that door for URLs.
The test stub now records argv and stdin separately, since which one a secret travels in is the entire difference. It caught the change immediately — the existing heartbeat assertions were reading argv — which is what a suite that stubs the thing under discussion is for.
SECURITY.md
This did not have one; both sister projects do. It states what the guard holds and what taking it would get, because that is the risk running it introduces rather than the one it addresses: an SSH key restricted to two read-only commands, an ntfy token that can publish but not read, and the baseline, which tells an intruder exactly what they would have to preserve.
Where this is weaker than dejima
Named rather than left to be discovered by someone who has read both:
No egress bound. dejima's central claim is a deny-by-default allowlist covering DNS as well as IP. This has none. Its real needs are three destinations, so an allowlist is cheap — but it belongs to the host or the container network. Doing it inside the container would mean granting NET_ADMIN to something that currently drops every capability, which is a worse trade than the gap. Left open deliberately, and the page says so.
The credential is in the container. dejima keeps the model credential out entirely behind a proxy. Here the private key is mounted. An SSH_AUTH_SOCK from the host would give the same use-without-possession and is not documented today.
No request logging. dejima logs egress verdicts; this logs findings and failures, not connections.
Where it is stronger, also stated: every capability dropped, read-only root filesystem, no-new-privileges, non-root uid, no published port, no inbound connection at all.
Tested: 87 passing. The three argv tests were run against the previous version and fail on it.
**Summary generated by LLM agent**
A posture pass against dejima's, which turned up one thing worth fixing and three worth stating.
## The ntfy token was in argv
`/proc/<pid>/cmdline` is world-readable, so `-H "Authorization: Bearer $tok"` hands the token to every local account for the length of the call. On the systemd path this runs as root on a machine that may well have other people on it. The heartbeat URL has the same problem and is easy to miss, because an Uptime Kuma push URL carries its token in the path — the URL *is* the credential.
Both now go to curl through a config on stdin, which no other process can read. Verified against a local listener: the header arrives and the token is absent from the command line. The body and title stay in argv, being counts and a hostname.
A token containing a quote or backslash is refused. A curl config is not shell, but it is still a parser being handed a value from a file, and `check_url` already closed that door for URLs.
The test stub now records argv and stdin separately, since which one a secret travels in is the entire difference. It caught the change immediately — the existing heartbeat assertions were reading argv — which is what a suite that stubs the thing under discussion is for.
## SECURITY.md
This did not have one; both sister projects do. It states what the guard holds and what taking it would get, because that is the risk running it *introduces* rather than the one it addresses: an SSH key restricted to two read-only commands, an ntfy token that can publish but not read, and the baseline, which tells an intruder exactly what they would have to preserve.
## Where this is weaker than dejima
Named rather than left to be discovered by someone who has read both:
- **No egress bound.** dejima's central claim is a deny-by-default allowlist covering DNS as well as IP. This has none. Its real needs are three destinations, so an allowlist is cheap — but it belongs to the host or the container network. Doing it inside the container would mean granting `NET_ADMIN` to something that currently drops every capability, which is a worse trade than the gap. Left open deliberately, and the page says so.
- **The credential is in the container.** dejima keeps the model credential out entirely behind a proxy. Here the private key is mounted. An `SSH_AUTH_SOCK` from the host would give the same use-without-possession and is not documented today.
- **No request logging.** dejima logs egress verdicts; this logs findings and failures, not connections.
Where it is stronger, also stated: every capability dropped, read-only root filesystem, `no-new-privileges`, non-root uid, no published port, no inbound connection at all.
Tested: 87 passing. The three argv tests were run against the previous version and fail on it.
/proc/<pid>/cmdline is world-readable, so `-H "Authorization: Bearer $tok"`
hands the ntfy token to every local account for the length of the call. On the
systemd path this runs as root on a machine that may have other people on it.
The same is true of the heartbeat URL, which is a credential rather than a
destination: an Uptime Kuma push URL carries its token in the path.
Both move to a curl config on stdin, which no other process can read. The body
and the title stay in argv, being counts and a hostname. A token containing a
quote or a backslash is refused, since a curl config is still a parser being
handed a value from a file, and check_url already closed that door for URLs.
The test stub records argv and stdin separately, because which of the two a
secret travels in is the whole difference. It caught the change immediately -
the heartbeat assertions were reading argv - which is the behaviour wanted from
a suite that stubs the thing under discussion.
SECURITY.md, which this did not have and both sister projects do. It states
what the guard holds and what taking it would get, which is the risk running it
introduces rather than the one it addresses; and where the posture is weaker
than dejima's, since that comparison is the one a reader of both will make.
Three gaps, named rather than left to be found: no egress bound where dejima's
central claim is an allowlist, the private key inside the container where
dejima keeps its credential out entirely, and no logging of connections.
The egress gap is left open on purpose and says so. Closing it inside the
container would mean granting NET_ADMIN to something that currently drops every
capability, which is a worse trade than the gap.
branderson
approved these changes 2026-08-29 01:28:16 -07:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary generated by LLM agent
A posture pass against dejima's, which turned up one thing worth fixing and three worth stating.
The ntfy token was in argv
/proc/<pid>/cmdlineis world-readable, so-H "Authorization: Bearer $tok"hands the token to every local account for the length of the call. On the systemd path this runs as root on a machine that may well have other people on it. The heartbeat URL has the same problem and is easy to miss, because an Uptime Kuma push URL carries its token in the path — the URL is the credential.Both now go to curl through a config on stdin, which no other process can read. Verified against a local listener: the header arrives and the token is absent from the command line. The body and title stay in argv, being counts and a hostname.
A token containing a quote or backslash is refused. A curl config is not shell, but it is still a parser being handed a value from a file, and
check_urlalready closed that door for URLs.The test stub now records argv and stdin separately, since which one a secret travels in is the entire difference. It caught the change immediately — the existing heartbeat assertions were reading argv — which is what a suite that stubs the thing under discussion is for.
SECURITY.md
This did not have one; both sister projects do. It states what the guard holds and what taking it would get, because that is the risk running it introduces rather than the one it addresses: an SSH key restricted to two read-only commands, an ntfy token that can publish but not read, and the baseline, which tells an intruder exactly what they would have to preserve.
Where this is weaker than dejima
Named rather than left to be discovered by someone who has read both:
NET_ADMINto something that currently drops every capability, which is a worse trade than the gap. Left open deliberately, and the page says so.SSH_AUTH_SOCKfrom the host would give the same use-without-possession and is not documented today.Where it is stronger, also stated: every capability dropped, read-only root filesystem,
no-new-privileges, non-root uid, no published port, no inbound connection at all.Tested: 87 passing. The three argv tests were run against the previous version and fail on it.