Skip to content

🛡️ Sentinel: [Hardening] Refactor synchronous FS and exec calls to async in pipeline handlers#347

Merged
ChiR24 merged 5 commits into
mainfrom
sentinel-hardening-async-pipeline-5414201795584645671
Apr 10, 2026
Merged

🛡️ Sentinel: [Hardening] Refactor synchronous FS and exec calls to async in pipeline handlers#347
ChiR24 merged 5 commits into
mainfrom
sentinel-hardening-async-pipeline-5414201795584645671

Conversation

@google-labs-jules

@google-labs-jules google-labs-jules Bot commented Apr 9, 2026

Copy link
Copy Markdown
Contributor
  • 🚨 Severity: LOW / HARDENING
  • 💡 Issue: Pipeline handlers (src/tools/handlers/pipeline-handlers.ts) used blocking, synchronous operations like fs.readdirSync, fs.readFileSync, fs.accessSync, and execSync to locate the UnrealBuildTool.
  • 🎯 Impact: These operations block the Node.js event loop, preventing the MCP server from processing concurrent requests or heartbeats, which could lead to unresponsiveness or Denial of Service (DoS) if directories are large or drives are slow.
  • 🔧 Fix: Refactored tryUbtpath and findUbtExecutable to use their asynchronous equivalents (fs.promises.access, fs.promises.readdir, fs.promises.readFile, and util.promisify(exec)).
  • ✅ Verification: npm run lint, npm run type-check, npm run test:unit, and npm run build pass without issue.
  • 📝 Pattern Used: Used fs.promises and util.promisify consistent with asynchronous event loop best practices in Node.js.

PR created automatically by Jules for task 5414201795584645671 started by @ChiR24


Open with Devin

…ync in pipeline handlers

- **🚨 Severity:** LOW / HARDENING
- **💡 Issue:** Pipeline handlers (`src/tools/handlers/pipeline-handlers.ts`) used blocking, synchronous operations like `fs.readdirSync`, `fs.readFileSync`, `fs.accessSync`, and `execSync` to locate the UnrealBuildTool.
- **🎯 Impact:** These operations block the Node.js event loop, preventing the MCP server from processing concurrent requests or heartbeats, which could lead to unresponsiveness or Denial of Service (DoS) if directories are large or drives are slow.
- **🔧 Fix:** Refactored `tryUbtpath` and `findUbtExecutable` to use their asynchronous equivalents (`fs.promises.access`, `fs.promises.readdir`, `fs.promises.readFile`, and `util.promisify(exec)`).
- **✅ Verification:** `npm run lint`, `npm run type-check`, `npm run test:unit`, and `npm run build` pass without issue.
- **📝 Pattern Used:** Used `fs.promises` and `util.promisify` consistent with asynchronous event loop best practices in Node.js.
@google-labs-jules

Copy link
Copy Markdown
Contributor Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@ChiR24 ChiR24 marked this pull request as ready for review April 10, 2026 05:46
Copilot AI review requested due to automatic review settings April 10, 2026 05:46

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors UnrealBuildTool (UBT) discovery in pipeline handlers to use asynchronous filesystem and process execution APIs to avoid blocking the Node.js event loop.

Changes:

  • Converted UBT probing/discovery helpers (tryUbtpath, findUbtExecutable) from sync (*Sync, execSync) to async (fs.promises.*, promisified exec).
  • Updated run_ubt flow to await async UBT discovery and switched remaining directory reads to async equivalents.
  • Added a new Sentinel knowledge-base entry documenting the event-loop blocking risk from synchronous I/O in handlers.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/tools/handlers/pipeline-handlers.ts Replaces synchronous UBT discovery and directory/file checks with async equivalents and updates call sites accordingly.
.jules/sentinel.md Documents the event-loop blocking vulnerability pattern and its prevention guidance.
Comments suppressed due to low confidence (1)

src/tools/handlers/pipeline-handlers.ts:103

  • The UBT discovery logic was substantially refactored to async (fs.promises + exec promisified), but there are no unit tests covering the discovery paths (env var, .uproject EngineAssociation/DefaultEngine.ini, PATH fallback). Adding targeted tests (mocking fs.promises and child_process.exec/spawn) would help prevent regressions across platforms.
async function findUbtExecutable(): Promise<string> {
  // ─── Strategy 1: Explicit environment variable ────────────────────────
  // UE_ENGINE_PATH is the convention in this project (see AGENTS.md / README).
  // The path may point to either:
  //   • .../UE_5.x/Engine    (already includes "Engine" suffix)
  //   • .../UE_5.x           (root directory without "Engine")
  const enginePath =
    process.env.UE_ENGINE_PATH ??
    process.env.UNREAL_ENGINE_PATH ??
    undefined;

Comment on lines +77 to 85
async function tryUbtpath(candidate: string): Promise<string | undefined> {
// On Windows F_OK is sufficient for executability; X_OK is a no-op on fs.access
const mode = process.platform === 'win32'
? fs.constants.F_OK
: fs.constants.F_OK | fs.constants.X_OK;
try {
fs.accessSync(candidate, mode);
await fs.promises.access(candidate, mode);
return candidate;
} catch { /* not usable */ }

Copilot AI Apr 10, 2026

Copy link

Choose a reason for hiding this comment

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

On non-Windows platforms, tryUbtpath() requires X_OK for all candidates. That will likely reject UnrealBuildTool.dll (typically not marked executable) even though the code later supports running a .dll via dotnet. Consider relaxing the access mode for .dll candidates (e.g., check F_OK/readability) while still requiring X_OK for true executables.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@copilot apply changes based on this feedback
(#347 (review))
And mention today's date in sentinel.md file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have addressed the feedback by relaxing the X_OK requirement on Windows and non-Windows dlls, testing via fs.constants.F_OK. I have also updated the date in the sentinel.md file as requested.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Done in commit 1e83ccc.

  • tryUbtpath() now uses F_OK for .dll candidates on non-Windows (since dlls are not executable — they're invoked via dotnet), while still requiring F_OK | X_OK for true executables like .exe or bare binaries.
  • Updated the sentinel.md entry date to 2026-04-10.

Copilot AI and others added 2 commits April 10, 2026 06:03
…e sentinel.md date

Agent-Logs-Url: https://github.com/ChiR24/Unreal_mcp/sessions/50f83e4e-aea5-489f-aa86-dfbe1b87be29

Co-authored-by: ChiR24 <125826529+ChiR24@users.noreply.github.com>
…ync in pipeline handlers

- **🚨 Severity:** LOW / HARDENING
- **💡 Issue:** Pipeline handlers (`src/tools/handlers/pipeline-handlers.ts`) used blocking, synchronous operations like `fs.readdirSync`, `fs.readFileSync`, `fs.accessSync`, and `execSync` to locate the UnrealBuildTool.
- **🎯 Impact:** These operations block the Node.js event loop, preventing the MCP server from processing concurrent requests or heartbeats, which could lead to unresponsiveness or Denial of Service (DoS) if directories are large or drives are slow.
- **🔧 Fix:** Refactored `tryUbtpath` and `findUbtExecutable` to use their asynchronous equivalents (`fs.promises.access`, `fs.promises.readdir`, `fs.promises.readFile`, and `util.promisify(exec)`). Fixed bug where `tryUbtpath` was incorrectly returning an error on Linux machines by rejecting .dlls with `fs.constants.X_OK`.
- **✅ Verification:** `npm run lint`, `npm run type-check`, `npm run test:unit`, and `npm run build` pass without issue.
- **📝 Pattern Used:** Used `fs.promises` and `util.promisify` consistent with asynchronous event loop best practices in Node.js.
@github-actions github-actions Bot added size/l and removed size/m labels Apr 10, 2026
Copilot AI requested a review from ChiR24 April 10, 2026 06:06
@github-actions github-actions Bot added size/m and removed size/l labels Apr 10, 2026
@ChiR24 ChiR24 merged commit f61817a into main Apr 10, 2026
8 of 9 checks passed
@ChiR24 ChiR24 deleted the sentinel-hardening-async-pipeline-5414201795584645671 branch May 14, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants