* fix(security): harden project settings trust boundary + MCP sanitization
- Sanitize MCP tool result text with recursivelySanitizeUnicode() to prevent
Unicode injection via malicious MCP servers (tool definitions and prompts
were already sanitized, but tool call results were not)
- Read sandbox.enabled only from trusted settings sources (user, local, flag,
policy) — exclude projectSettings to prevent malicious repos from silently
disabling the sandbox via .claude/settings.json
- Disable git hooks in plugin marketplace clone/pull/submodule operations
with core.hooksPath=/dev/null to prevent code execution from cloned repos
- Remove ANTHROPIC_FOUNDRY_API_KEY from SAFE_ENV_VARS to prevent credential
injection from project-scoped settings without trust verification
- Add ssrfGuardedLookup to WebFetch HTTP requests to block DNS rebinding
attacks that could reach cloud metadata or internal services
Security: closes trust boundary gap where project settings could override
security-critical configuration. Follows the existing pattern established
by hasAllowBypassPermissionsMode() which already excludes projectSettings.
Co-authored-by: auriti <auriti@users.noreply.github.com>
* fix(security): remove unauthenticated file-based permission polling
Remove the legacy file-based permission polling from useSwarmPermissionPoller
that read from ~/.claude/teams/{name}/permissions/resolved/ — an unauthenticated
directory where any local process could forge approval files to auto-approve
tool uses for swarm teammates.
The file polling was dead code:
- The useSwarmPermissionPoller() hook was never mounted by any component
- resolvePermission() (the file writer) was never imported outside its module
- Permission responses are delivered exclusively via the mailbox system:
Leader: sendPermissionResponseViaMailbox() → writeToMailbox()
Worker: useInboxPoller → processMailboxPermissionResponse()
Changes:
- Remove file polling loop, processResponse(), and React hook imports from
useSwarmPermissionPoller.ts (now a pure callback registry module)
- Mark 7 file-based functions as @deprecated in permissionSync.ts
- Add 4 regression tests verifying the removal
No exported functions removed — only deprecated. All 5 consumer modules
verified: they import only mailbox-based functions that remain unchanged.
---------
Co-authored-by: auriti <auriti@users.noreply.github.com>
* fix: rename .claude.json to .openclaude.json with legacy fallback
Rename the global config file from ~/.claude.json to ~/.openclaude.json,
following the same migration pattern as the config directory
(~/.claude → ~/.openclaude).
- getGlobalClaudeFile() now prefers .openclaude.json; falls back to
.claude.json only if the legacy file exists and the new one does not
- Add .openclaude.json to filesystem permissions allowlist (keep
.claude.json for legacy file protection)
- Update all comment/string references from ~/.claude.json to
~/.openclaude.json across 12 files
New installs get .openclaude.json from the start. Existing users
continue using .claude.json until they rename it (or a future explicit
migration).
* test: add unit tests for getGlobalClaudeFile migration branches
Covers the three cases:
- new install (neither file exists) → .openclaude.json
- existing user (only legacy .claude.json exists) → .claude.json
- migrated user (both files exist) → .openclaude.json
---------
Co-authored-by: Zartris <14197299+Zartris@users.noreply.github.com>
* feat: add allowBypassPermissionsMode setting
Allow bypass permissions mode to appear in the mode list via
settings.json without requiring the --allow-dangerously-skip-permissions
CLI flag. The disableBypassPermissionsMode setting retains priority.
* fix: address Copilot review feedback on allowBypassPermissionsMode
- Security: read allowBypassPermissionsMode only from trusted settings
sources (user/local/flag/policy), excluding projectSettings to prevent
a malicious repo from enabling bypass mode
- UX: update error messages to reference the correct CLI flag
(--allow-dangerously-skip-permissions) and the new settings option
- Tests: add schema validation tests for the new field
This pass rewrites comment-only ANT-ONLY markers to neutral internal-only
language across the source tree without changing runtime strings, flags,
commands, or protocol identifiers. The goal is to lower obvious internal
prose leakage while keeping the diff mechanically safe and easy to review.
Constraint: Phase B is limited to comments/prose only; runtime strings and user-facing labels remain deferred
Rejected: Broad search-and-replace across strings and command descriptions | too risky for a prose-only pass
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Remaining ANT-ONLY hits are mostly runtime/user-facing strings and should be handled separately from comment cleanup
Tested: bun run build
Tested: bun run smoke
Tested: bun run verify:privacy
Tested: bun run test:provider
Tested: bun run test:provider-recommendation
Not-tested: Full repo typecheck (upstream baseline remains noisy)
Co-authored-by: anandh8x <test@example.com>
Inline base64 source maps had been checked into tracked src files. This strips those comments from the repository without changing runtime behavior or adding ongoing guardrails, per the requested one-time cleanup scope.
Constraint: Keep this change limited to tracked source cleanup only
Rejected: Add CI/source verification guard | user requested one-time cleanup only
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If these directives reappear, fix the producing transform instead of reintroducing repo-side cleanup code
Tested: rg -n "sourceMappingURL" ., bun run smoke, bun run verify:privacy, bun run test:provider, npm run test:provider-recommendation
Not-tested: bun run typecheck (repository has many pre-existing unrelated failures)
Co-authored-by: anandh8x <test@example.com>
React 19 requires `supportsMicrotasks: true` in the reconciler host
config so it can flush state updates from passive effects via
queueMicrotask. Without this, state updates triggered inside
useMcpConnectivityStatus were silently dropped, corrupting React's
internal executionContext and causing all keyboard input to freeze
after the "N MCP server(s) need auth" notification appeared.
Root cause (three-part fix):
1. reconciler.ts: declare supportsMicrotasks + scheduleMicrotask so
React 19 schedules passive-effect flushes correctly.
2. useMcpConnectivityStatus.tsx: wrap the MCP auth notification effect
in try/catch so any unexpected throw does not propagate into
flushPassiveEffects and permanently corrupt executionContext.
3. notifications.tsx: wrap addNotification, removeNotification, and
processQueue in try/catch for the same reason — these are called
from 12+ notification hooks across passive effects.
Also fixes a pre-existing test isolation bug in context.test.ts where
assigning `undefined` to process.env produced the string "undefined",
polluting the env for subsequent test files.
Resolves: #169, #205, #77
Squash the current repository state back into one baseline commit while
preserving the README reframing and repository contents.
Constraint: User explicitly requested a single squashed commit with subject "asdf"
Confidence: high
Scope-risk: broad
Reversibility: clean
Directive: This commit intentionally rewrites published history; coordinate before future force-pushes
Tested: git status clean; local history rewritten to one commit; force-pushed main to origin and instructkr
Not-tested: Fresh clone verification after push