PR #391 #1106
codeql
on: dynamic
Matrix: analyze
Annotations
1 error and 11 warnings
|
Daemon socket directory in shared tmpdir is vulnerable to local pre-creation/hijacking:
src/daemon/socket-path.ts#L29
daemonDirForWorkspaceKey now places the daemon socket under os.tmpdir() (e.g. /tmp/xcodebuildmcp-<hash>/d.sock) using a hash derived from the non-secret workspace path. The path is fully predictable to any local user. ensureSocketDir only calls mkdirSync with mode 0o700 when the directory does not already exist, so a local attacker who pre-creates /tmp/xcodebuildmcp-<hash>/ with permissive permissions (or places a symlink/socket there) can intercept or block IPC between the MCP client and daemon. The previous location under ~/.xcodebuildmcp/daemons/<key>/ inherited the user's home directory permissions and did not have this exposure.
|
|
Analyze (actions)
Starting April 2026, the CodeQL Action will skip computing file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses.
To opt out of this change, create a custom repository property with the name `github-codeql-file-coverage-on-prs` and the type "True/false", then set this property to `true` in the repository's settings.
|
|
Analyze (python)
Starting April 2026, the CodeQL Action will skip computing file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses.
To opt out of this change, create a custom repository property with the name `github-codeql-file-coverage-on-prs` and the type "True/false", then set this property to `true` in the repository's settings.
|
|
Analyze (javascript-typescript)
Starting April 2026, the CodeQL Action will skip computing file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses.
To opt out of this change, create a custom repository property with the name `github-codeql-file-coverage-on-prs` and the type "True/false", then set this property to `true` in the repository's settings.
|
|
Build Logs path not updated to workspace-scoped location:
src/snapshot-tests/__fixtures__/cli/device/build--error-wrong-scheme.txt#L8
The Derived Data path on line 8 has been updated to the new workspace-scoped path (`workspaces/XcodeBuildMCP-<HASH>/DerivedData/...`), but the Build Logs path in the Context After (line 15) still points to the old top-level `logs/` directory. Per the PR description, logs are now also workspace-keyed under the shared application support location, so this fixture appears to be only partially updated. If the underlying code now emits workspace-scoped log paths, this fixture would not match actual output and snapshot tests would fail; if the code still emits the old path for logs, then MCP/CLI/JSON fixtures may have drifted out of alignment.
|
|
[MUR-JQD] Build Logs path not updated to workspace-scoped location (additional location):
src/snapshot-tests/__fixtures__/mcp/simulator/test--failure.txt#L36
The Derived Data path on line 8 has been updated to the new workspace-scoped path (`workspaces/XcodeBuildMCP-<HASH>/DerivedData/...`), but the Build Logs path in the Context After (line 15) still points to the old top-level `logs/` directory. Per the PR description, logs are now also workspace-keyed under the shared application support location, so this fixture appears to be only partially updated. If the underlying code now emits workspace-scoped log paths, this fixture would not match actual output and snapshot tests would fail; if the code still emits the old path for logs, then MCP/CLI/JSON fixtures may have drifted out of alignment.
|
|
New JSON fixture entry has empty test name and a sentence-style suite:
src/snapshot-tests/__fixtures__/json/simulator/test--failure.json#L368
The added entry uses 'Decimal point at start creates 0' as the suite and an empty string as the test. This breaks the stable structured output envelope shape used elsewhere in the fixture (suite=test class, test=test method) and likely indicates a normalization gap rather than an intentional behavior change. Consumers parsing the JSON envelope will see a malformed/unidentified test record.
|
|
Startup registry lock leaks for up to 30s if daemon initialization throws:
src/daemon.ts#L186
After acquiring the registry mutation lock at line 186, the daemon performs significant async/sync work (loadManifest, buildDaemonToolCatalogFromManifest, etc.) before reaching the server.listen callback that releases the lock. If any of this work throws, main() rejects and the catch handler at line 470 calls process.exit(1) without releasing the lock. server.on('error', releaseStartupRegistryLock) only handles server-level errors, not exceptions thrown during setup. Since the lock has a 30s lease (DAEMON_REGISTRY_LOCK_LEASE_MS) and acquisition only waits 1s (DAEMON_REGISTRY_LOCK_WAIT_MS), subsequent daemon start attempts within that window will fail with 'Unable to acquire daemon registry lock' until the lease expires.
|
|
cleanupWorkspaceDaemonFiles silently leaks socket when registry socketPath differs:
src/daemon/daemon-registry.ts#L336
When the registry entry's recorded socketPath does not match the resolved socketPath (default `d.sock` under the workspace daemon dir, or the explicitly passed `options.socketPath`), the function returns without unlinking either path. If the registry was written with a different socket location (e.g. legacy `daemon.sock` or a relocated socket), the stale socket file is left on disk after registry removal, which can prevent future daemon starts that bind to that path or accumulate stale Unix sockets across upgrades.
|
|
[CUB-R4Y] cleanupWorkspaceDaemonFiles silently leaks socket when registry socketPath differs (additional location):
src/daemon/daemon-registry.ts#L292
When the registry entry's recorded socketPath does not match the resolved socketPath (default `d.sock` under the workspace daemon dir, or the explicitly passed `options.socketPath`), the function returns without unlinking either path. If the registry was written with a different socket location (e.g. legacy `daemon.sock` or a relocated socket), the stale socket file is left on disk after registry removal, which can prevent future daemon starts that bind to that path or accumulate stale Unix sockets across upgrades.
|
|
isPidAlive returns true for invalid pids (0, negative):
src/utils/process-liveness.ts#L1
`process.kill(pid, 0)` with pid `0` signals the entire process group of the caller, and negative pids signal a process group. Both can succeed (or fail with EPERM) without indicating that a specific process is alive. Callers using this to detect 'live owners' for cleanup may treat group signaling as proof of liveness, preserving stale artifacts indefinitely or, worse, mis-targeting cleanup decisions on stored zero/negative pids.
|
|
[M39-ZYH] isPidAlive returns true for invalid pids (0, negative) (additional location):
src/utils/process-liveness.ts#L5
`process.kill(pid, 0)` with pid `0` signals the entire process group of the caller, and negative pids signal a process group. Both can succeed (or fail with EPERM) without indicating that a specific process is alive. Callers using this to detect 'live owners' for cleanup may treat group signaling as proof of liveness, preserving stale artifacts indefinitely or, worse, mis-targeting cleanup decisions on stored zero/negative pids.
|