basecamp / basecamp/once-campfire

Bot key is still written to the log in the clear — Thruster's access log isn't covered by #269

Open
#272 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Ruby
Stars
4.6k
Forks
791
Avg merge
11h 8m
Merged PRs (30d)
13

Description

#269 added `LogScrubbingFormatter` and wired it into `config.logger`, which redacts the bot-key path segment out of Rails' log lines. But Rails isn't the only thing logging the request path in that container.

`Procfile` runs the web process as `web: bundle exec thrust bin/start-app`, so Thruster fronts Rails and writes its own JSON access log to the same stdout. That log is untouched by a Rails log formatter, and it contains the full path:

```json
{"time":"2026-09-09T18:23:28.032553851Z","level":"INFO","msg":"Request",
"path":"/rooms/2//messages","status":201,"dur":287,
"method":"POST","req_content_length":178,"req_content_type":"text/html; charset=utf-8",
"resp_content_length":20,"resp_content_type":"application/json",
"remote_addr":"172.18.0.1:39662","user_agent":"Ruby","cache":"bypass",
"query":"","proto":"HTTP/1.1"}
```

Same request, both loggers, on a node running `ef147d1`:

```
$ docker logs campfire | grep -cE '/rooms/[0-9]+/\[FILTERED\]' # Rails, redacted
1
$ docker logs campfire | grep -cE '/rooms/[0-9]+/[0-9]+-[A-Za-z0-9]{6,}' # Thruster, in the clear
2
```

**Why it matters:** the bot key is the entire credential for that room — anyone holding the URL can post as the bot, and there's no separate auth header to rotate independently. Container logs are routinely shipped to a log aggregator, read by anyone with `docker logs` access, and retained long after the request. In our deployment the alert relay posts through the bot API, so every alert delivery writes a live credential into the log; the only reason it's contained is that nothing ships that node's logs.

**Reproduce:** POST to a bot endpoint on a production-mode container and read the container log — the Rails `Started POST` line is redacted, the Thruster `"msg":"Request"` line above it is not.

**Possible directions** (I don't have a view on which you'd prefer):

1. Redact the path in Thruster itself — it's basecamp/thruster, and a path-redaction pattern would help any app that puts a secret in a path segment.
2. Take the key out of the URL path — accept it as a header (or a query parameter, which `filter_parameters` already covers), keeping the path form as a deprecated alias.
3. Document it, so operators know `docker logs` on a Campfire container is secret-bearing and shouldn't be shipped.

Happy to send a PR for whichever direction you'd take.

Versions: once-campfire `ef147d1`, image `ghcr.io/basecamp/once-campfire@sha256:d5e55bd8eb56…`, thruster 0.1.23.

Contributor guide

Open the contributing guide

Research direction

The issue names Procfile, LogScrubbingFormatter, config.logger, and Thruster 0.1.23; start by reproducing the POST in a production-mode container and comparing docker logs for Rails and Thruster entries. Done means the bot key is not exposed in either access log, with the chosen direction and any compatibility or documentation impact settled.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, rails, ruby
Domain
backend, observability, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.