Passing the Gitea token as -H "Authorization: token $GITEA_TOKEN" puts it in curl argv, and /proc makes argv world-readable. For the life of every request, any other process on the box can read the credential straight out of ps.
That matters more here than it would in most repos. This tool ships inside the sandbox image, on PATH, next to agents that are running with --dangerously-skip-permissions and are explicitly not trusted with host credentials. Reading a process listing is not an exploit; it is one command.
This was found by accident, while debugging an unrelated gitea-pr create hang: a routine ps to see whether the process was still alive printed the live token to the terminal, and from there into an agent transcript on a bind-mounted volume.
Change
All six call sites now go through one gitea_api helper that feeds the auth header to curl as a config on stdin (-K -) instead of as an argument. printf is a bash builtin, so the token is never an argument to any process. As a side effect the six duplicated curl -sS -w invocations collapse into one.
Everything else is unchanged: same endpoints, same error handling, same output.
Testing
Verified functionally by running gitea-pr comments 8 against the live server, before and after: byte-identical output.
Verified for the actual security property by polling ps at 20Hz for the duration of a real run:
unpatched: 4 sightings of Authorization: token 3e03...
patched: 0 sightings
Added a static test pinning it, and mutation-tested that test by reverting the helper to the -H form: not ok 36, then restored and green again.
Suites: static 68/68, audit 25/25, proxy 15/15. Runtime needs a Docker daemon and was not run in the sandbox.
Note on the token itself
The token that was exposed during that debugging session should be rotated; it reached a terminal and a transcript. Rotating it is not blocked on this PR, and this PR does not rotate it.
**Summary generated by LLM agent**
Passing the Gitea token as `-H "Authorization: token $GITEA_TOKEN"` puts it in curl argv, and /proc makes argv world-readable. For the life of every request, any other process on the box can read the credential straight out of `ps`.
That matters more here than it would in most repos. This tool ships inside the sandbox image, on PATH, next to agents that are running with `--dangerously-skip-permissions` and are explicitly not trusted with host credentials. Reading a process listing is not an exploit; it is one command.
This was found by accident, while debugging an unrelated `gitea-pr create` hang: a routine `ps` to see whether the process was still alive printed the live token to the terminal, and from there into an agent transcript on a bind-mounted volume.
## Change
All six call sites now go through one `gitea_api` helper that feeds the auth header to curl as a config on stdin (`-K -`) instead of as an argument. `printf` is a bash builtin, so the token is never an argument to any process. As a side effect the six duplicated `curl -sS -w` invocations collapse into one.
Everything else is unchanged: same endpoints, same error handling, same output.
## Testing
Verified functionally by running `gitea-pr comments 8` against the live server, before and after: byte-identical output.
Verified for the actual security property by polling `ps` at 20Hz for the duration of a real run:
- unpatched: 4 sightings of `Authorization: token 3e03...`
- patched: 0 sightings
Added a static test pinning it, and mutation-tested that test by reverting the helper to the `-H` form: `not ok 36`, then restored and green again.
Suites: static 68/68, audit 25/25, proxy 15/15. Runtime needs a Docker daemon and was not run in the sandbox.
## Note on the token itself
The token that was exposed during that debugging session should be rotated; it reached a terminal and a transcript. Rotating it is not blocked on this PR, and this PR does not rotate it.
Passing the token as `-H "Authorization: token $GITEA_TOKEN"` puts it in
curl's argv, and /proc makes argv world-readable: for the life of every
request, any other process could read the credential straight out of `ps`.
That matters more here than in most repos, since this tool ships inside a
sandbox image whose whole purpose is running agents that read process
listings and are not fully trusted with host credentials.
curl reads the header from a config on stdin instead. printf is a bash
builtin, so the token is never an argument to anything.
Verified by polling `ps` during a real `gitea-pr comments` run: four
sightings before, zero after.
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
Passing the Gitea token as
-H "Authorization: token $GITEA_TOKEN"puts it in curl argv, and /proc makes argv world-readable. For the life of every request, any other process on the box can read the credential straight out ofps.That matters more here than it would in most repos. This tool ships inside the sandbox image, on PATH, next to agents that are running with
--dangerously-skip-permissionsand are explicitly not trusted with host credentials. Reading a process listing is not an exploit; it is one command.This was found by accident, while debugging an unrelated
gitea-pr createhang: a routinepsto see whether the process was still alive printed the live token to the terminal, and from there into an agent transcript on a bind-mounted volume.Change
All six call sites now go through one
gitea_apihelper that feeds the auth header to curl as a config on stdin (-K -) instead of as an argument.printfis a bash builtin, so the token is never an argument to any process. As a side effect the six duplicatedcurl -sS -winvocations collapse into one.Everything else is unchanged: same endpoints, same error handling, same output.
Testing
Verified functionally by running
gitea-pr comments 8against the live server, before and after: byte-identical output.Verified for the actual security property by polling
psat 20Hz for the duration of a real run:Authorization: token 3e03...Added a static test pinning it, and mutation-tested that test by reverting the helper to the
-Hform:not ok 36, then restored and green again.Suites: static 68/68, audit 25/25, proxy 15/15. Runtime needs a Docker daemon and was not run in the sandbox.
Note on the token itself
The token that was exposed during that debugging session should be rotated; it reached a terminal and a transcript. Rotating it is not blocked on this PR, and this PR does not rotate it.