Skip to content

fix: harden telemetry flush against arbitrary file upload#235

Open
bukinoshita wants to merge 3 commits intomainfrom
fix/telemetry-flush-security-cef6
Open

fix: harden telemetry flush against arbitrary file upload#235
bukinoshita wants to merge 3 commits intomainfrom
fix/telemetry-flush-security-cef6

Conversation

@bukinoshita
Copy link
Copy Markdown
Member

@bukinoshita bukinoshita commented Apr 9, 2026

Summary by cubic

Hardens the hidden telemetry flush to prevent arbitrary file uploads and local file injection.

  • Bug Fixes
    • Move spool files to per-user ~/.config/resend/telemetry-spool/ (0700) instead of system tmpdir().
    • Add _nonce (UUID) to each payload; verify on flush and strip before sending.
    • Validate payload against the expected telemetry schema; reject arbitrary JSON.
    • Reject files with multiple hard links (nlink !== 1).
    • Restrict filenames to ^resend-telemetry-\d+-\d+\.json$ and require the spool directory path.
    • Tests cover schema rejection, nonce stripping, hardlink and filename checks.

Written for commit 74f2c95. Summary will update on new commits.

- Move telemetry spool files from shared tmpdir() to a private
  per-user directory (~/.config/resend/telemetry-spool) created with
  0700 permissions
- Add nonce (crypto.randomUUID) to telemetry payload and strip it
  before sending to PostHog
- Validate payload against expected telemetry schema (api_key,
  distinct_id, event='cli.used', properties, _nonce) instead of
  accepting arbitrary JSON
- Reject files with hardlink count != 1 (stat.nlink check)
- Tighten filename regex to only allow pid-timestamp pattern
- Update tests to cover schema validation, hardlink rejection,
  loose filename rejection, and nonce stripping

Fixes BU-621

Co-authored-by: Bu Kinoshita <bukinoshita@users.noreply.github.com>
@bukinoshita
Copy link
Copy Markdown
Member Author

@cursor fix conflicts

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 13, 2026

The PR is fine as-is since the description will be auto-updated by cubic on the new commit. No need to force an update.

Merge conflicts resolved. I merged origin/main into the feature branch, adapting the security hardening to work with the upstream changes:

  • UUID filenames: Main switched from pid-timestamp to crypto.randomUUID() filenames — updated the spool filename regex to validate UUID format instead of \d+-\d+
  • Safe file creation: Main added O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW for writing temp files — kept this improvement alongside the spool directory change
  • Symlink write test: Main added a test for symlink write protection — updated it to use the spool directory path
  • it convention: Main switched from test() to it() — adopted throughout

All 794 tests pass, lint and typecheck are clean.

Open in Web Open in Cursor 

Merge upstream changes from main, adapting the security hardening
to use UUID-based filenames (from main), O_CREAT|O_EXCL|O_WRONLY
for safe file creation, and 'it' test convention while preserving
all security fixes (spool dir, nonce, schema validation, hardlink
rejection).

Co-authored-by: Bu Kinoshita <bukinoshita@users.noreply.github.com>
@bukinoshita
Copy link
Copy Markdown
Member Author

@cubic-dev-ai can you review?

@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai bot commented Apr 13, 2026

@cubic-dev-ai can you review?

@bukinoshita I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@bukinoshita bukinoshita marked this pull request as ready for review April 14, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants