Skip to content

🛡️ Sentinel: [CRITICAL] Fix command injection in docker logs endpoint#58

Open
bobdivx wants to merge 1 commit into
devfrom
sentinel-fix-docker-logs-injection-16260930353450927475
Open

🛡️ Sentinel: [CRITICAL] Fix command injection in docker logs endpoint#58
bobdivx wants to merge 1 commit into
devfrom
sentinel-fix-docker-logs-injection-16260930353450927475

Conversation

@bobdivx
Copy link
Copy Markdown
Owner

@bobdivx bobdivx commented May 23, 2026

🚨 Severity: CRITICAL
💡 Vulnerability: The src/pages/api/docker-logs.ts endpoint was vulnerable to Remote Code Execution (RCE) via command injection. The containerId and tail query parameters were interpolated directly into a shell string passed to execSync().
🎯 Impact: An attacker could execute arbitrary commands on the host by supplying a malicious id (e.g., id=123; rm -rf /;).
🔧 Fix: Refactored the endpoint to use execFileAsync (with util.promisify), passing arguments as a strictly formatted array, eliminating shell evaluation entirely. Added validation to prevent argument/flag injection (rejecting containerId starting with -). Sanitized error outputs to avoid exposing internals.
✅ Verification: Ran pnpm run check and vitest. Validated code format with Prettier.

Additionally, recorded this critical vulnerability, the learning, and prevention strategies in .jules/sentinel.md.


PR created automatically by Jules for task 16260930353450927475 started by @bobdivx

- Replaced vulnerable `execSync` with `execFileAsync` to prevent shell evaluation.
- Added explicit parameter validation against flag injection (`-`).
- Sanitized `error.message` in catch block to prevent data leakage.
- Logged critical learning in `.jules/sentinel.md`.

Co-authored-by: bobdivx <6737167+bobdivx@users.noreply.github.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
forge Ready Ready Preview, Comment May 23, 2026 5:25pm

@google-labs-jules
Copy link
Copy Markdown

👋 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.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a command injection vulnerability in the Docker logs endpoint by replacing execSync with execFileAsync and implementing input validation for the container ID. It also adds a sentinel file documenting the vulnerability and prevention strategies. Feedback focuses on further hardening the tail parameter validation, refining the concatenation of stdout and stderr to avoid empty lines, and improving error handling to return appropriate HTTP status codes when the Docker command fails.

const containerId = url.searchParams.get('id');
const tail = url.searchParams.get('tail') || '100';
const containerId = url.searchParams.get("id");
const tail = url.searchParams.get("tail") || "100";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-medium medium

While execFileAsync prevents shell injection, the tail parameter should still be validated to ensure it is either a positive integer or the string 'all'. This prevents potential argument injection or unexpected behavior if a malicious flag is passed as the value for the --tail argument.

    const tail = url.searchParams.get("tail") || "100";
    if (tail !== "all" && !/^\d+$/.test(tail)) {
      return new Response(
        JSON.stringify({ error: "Paramètre tail invalide" }),
        {
          status: 400,
          headers: { "Content-Type": "application/json" },
        },
      );
    }

Comment on lines +52 to +54
const output =
stdout.toString() + (stderr ? "\n" + stderr.toString() : "");
logs = output.trim() ? output.trim().split("\n") : [];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current logic for combining stdout and stderr manually adds a newline, which can result in empty lines in the output if both streams already contain trailing newlines (which is common for Docker logs). Simply concatenating the outputs and trimming the result is more robust.

Suggested change
const output =
stdout.toString() + (stderr ? "\n" + stderr.toString() : "");
logs = output.trim() ? output.trim().split("\n") : [];
const output = stdout.toString() + stderr.toString();
logs = output.trim() ? output.trim().split("\n") : [];

Comment on lines 55 to 61
} catch (err: any) {
// Certains logs sortent sur stderr, checkons stderr si stdout est vide ou si erreur
if (err.stderr) {
logs = err.stderr.toString().trim().split('\n');
} else {
throw err;
}
if (err.stderr) {
logs = err.stderr.toString().trim().split("\n");
} else {
throw new Error("Erreur d'exécution Docker");
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current error handling returns a 200 OK status even when the Docker command fails (e.g., if the container does not exist), including the error message in the logs array. It would be more appropriate to return a proper error status code (e.g., 404 or 400) when the command fails to execute correctly.

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.

1 participant