debug bundle is staged at a predictable path and published world-readable
- Dominant language
- TypeScript
- Stars
- 22.5k
- Forks
- 3.1k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 715
Description
### What happens
`src/lib/diagnostics/tarball.ts:28` stages the debug bundle at a path other local users can
predict, and lets `tar` create it:
```
const partial = `${output}.partial.${process.pid}`;
```
Nothing creates that file first, so the `spawnSync("tar", ...)` at
`src/lib/diagnostics/tarball.ts:29` chooses its mode and the success path renames it to `output`
at `src/lib/diagnostics/tarball.ts:51`. Two things follow, both observed on `main` (`337c1eed5`)
with the default `umask 022`:
**The bundle is published group- and world-readable** — `bundle mode: 644`. That is the file the
command tells users to attach to a GitHub issue
(`src/lib/diagnostics/debug.ts:514-517`).
**`tar` follows a symlink planted at the staging path.** After planting one and letting `tar`
write, the symlink target began `037 213` — the gzip magic number, i.e. it was overwritten with
tarball content.
Both are reachable because the command's own example writes into a world-writable directory
(`src/commands/debug.ts:88`):
```
nemoclaw debug --output /tmp/nemoclaw-debug.tar.gz
```
There, any local user can read the bundle, or pre-plant a symlink at
`/tmp/nemoclaw-debug.tar.gz.partial.` — a small, enumerable space — to have a file of their
choosing overwritten with the tool's privileges.
### Why this looks like drift
The repository already stages temp files safely: `src/lib/shields/timer.ts:167` uses
`fs.openSync(tempPath, "wx", 0o600)`, `src/lib/share-command.ts:233` uses
`{ mode: 0o600, flag: "wx" }`, and `src/lib/shields/index.ts:393` uses `O_EXCL | O_NOFOLLOW`.
The staging path here arrived in #4506 (`f8c85f37e`), whose stated goal was to leave no partial
tarball and rename atomically. Permissions and predictability were not in that change's scope.
### Environment
macOS 26.5.1 (25F80), Node v26.7.0, `main` at `337c1eed5`.
Contributor guide
Research direction
Start in src/lib/diagnostics/tarball.ts at the partial-path creation and tar invocation, then compare the safe temporary-file patterns in src/lib/shields/timer.ts, src/lib/share-command.ts, and src/lib/shields/index.ts. Check the debug output path in src/lib/diagnostics/debug.ts:514-517 and the example in src/commands/debug.ts:88; done means the bundle is not world-readable and a planted staging symlink cannot redirect tar output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100