tests not in `test/no-validate-leaksan.txt` will run with leaksanitizer
in CI
leaks documented in `test/leaksan.supp` will not cause a test failure
-- notes about leaksanitizer
- will not catch garbage collected objects accumulated during
long-running processes
- will not catch js objects (eg a strong held to a promise)
- will catch native calls to `malloc` not `free`d
- will catch allocations made in C, Zig, C++, libc, dependencies,
dlopen'd
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## What does this PR do?
Fixes https://github.com/oven-sh/bun/issues/22650
Fixes https://github.com/oven-sh/bun/issues/22615
Fixes https://github.com/oven-sh/bun/issues/22603
Fixes https://github.com/oven-sh/bun/issues/22602
Fixes a crash that occurred when running shell commands through `bun
run` (package.json scripts) on Windows that use the `&&` operator
followed by an external command.
### The Problem
The minimal reproduction was:
```bash
bun exec 'echo && node --version'
```
This would crash with: `panic(main thread): attempt to use null value`
### Root Causes
Two issues were causing the crash:
1. **Missing top_level_dir**: When `runPackageScriptForeground` creates
a MiniEventLoop for running package scripts, it wasn't setting the
`top_level_dir` field. This caused a null pointer dereference when the
shell tried to access it.
2. **MovableIfWindowsFd handling**: After PR #21800 introduced
`MovableIfWindowsFd` to handle file descriptor ownership on Windows, the
`IOWriter.fd` could be moved to libuv, leaving it null. When the shell
tried to spawn an external command after a `&&` operator, it would crash
trying to access this null fd.
### The Fix
1. Set `mini.top_level_dir = cwd` after initializing the MiniEventLoop
in `run_command.zig`
2. In `IO.zig`, when the fd has been moved to libuv (is null), use
`.inherit` for stdio instead of trying to pass the null fd
### How did you verify your code works?
- Added a regression test that reproduces the issue
- Verified the test fails without the fix and passes with it
- Tested the minimal reproduction command directly
- The fix correctly allows both commands in the `&&` chain to execute
```bash
# Before fix: crashes
> bun exec 'echo test && node --version'
panic(main thread): attempt to use null value
# After fix: works correctly
> bun exec 'echo test && node --version'
test
v22.4.1
```
<sub>
also probably fixes#22615 and fixes#22603 and fixes#22602
</sub>
---------
Co-authored-by: Zack Radisic <zack@theradisic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This PR adds `Bun.secrets`, a new API for securely storing and
retrieving credentials using the operating system's native credential
storage locally. This helps developers avoid storing sensitive data in
plaintext config files.
```javascript
// Store a GitHub token securely
await Bun.secrets.set({
service: "my-cli-tool",
name: "github-token",
value: "ghp_xxxxxxxxxxxxxxxxxxxx"
});
// Retrieve it when needed
const token = await Bun.secrets.get({
service: "my-cli-tool",
name: "github-token"
});
// Use with fallback to environment variable
const apiKey = await Bun.secrets.get({
service: "my-app",
name: "api-key"
}) || process.env.API_KEY;
```
Marking this as a draft because Linux and Windows have not been manually
tested yet. This API is only really meant for local development usecases
right now, but it would be nice if in the future to support adapters for
production or CI usecases.
### Core API
- `Bun.secrets.get({ service, name })` - Retrieve a stored credential
- `Bun.secrets.set({ service, name, value })` - Store or update a
credential
- `Bun.secrets.delete({ service, name })` - Delete a stored credential
### Platform Support
- **macOS**: Uses Keychain Services via Security.framework
- **Linux**: Uses libsecret (works with GNOME Keyring, KWallet, etc.)
- **Windows**: Uses Windows Credential Manager via advapi32.dll
### Implementation Highlights
- Non-blocking - all operations run on the threadpool
- Dynamic loading - no hard dependencies on system libraries
- Sensitive data is zeroed after use
- Consistent API across all platforms
## Use Cases
This API is particularly useful for:
- CLI tools that need to store authentication tokens
- Development tools that manage API keys
- Any tool that currently stores credentials in `~/.npmrc`,
`~/.aws/credentials` or in environment variables that're globally loaded
## Testing
Comprehensive test suite included with coverage for:
- Basic CRUD operations
- Empty strings and special characters
- Unicode support
- Concurrent operations
- Error handling
All tests pass on macOS. Linux and Windows implementations are complete
but would benefit from additional platform testing.
## Documentation
- Complete API documentation in `docs/api/secrets.md`
- TypeScript definitions with detailed JSDoc comments and examples
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
* Move `DebugThreadLock` to `bun.safety`
* Enable in `ci_assert` builds, but store stack traces only in debug
builds
* Reduce size of struct by making optional field non-optional
* Add `initLockedIfNonComptime` as a workaround for not being able to
call `initLocked` in comptime contexts
* Add `lockOrAssert` method to acquire the lock if unlocked, or else
assert that the current thread acquired the lock
* Add stack traces to `CriticalSection` and `AllocPtr` in debug builds
* Make `MimallocArena.init` infallible
* Make `MimallocArena.heap` non-nullable
* Rename `RefCount.active_counts` to `raw_count` and provide read-only
`get` method
* Add `bun.safety.alloc.assertEq` to assert that two allocators are
equal (avoiding comparison of undefined `ptr`s)
(For internal tracking: fixes STAB-917, STAB-918, STAB-962, STAB-963,
STAB-964, STAB-965)
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
### How did you verify your code works?
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>