Skip to content

🛡️ Sentinel: [CRITICAL] Fix command injection in docker logs API#74

Open
bobdivx wants to merge 1 commit into
devfrom
jules-12882890723391972388-c844a712
Open

🛡️ Sentinel: [CRITICAL] Fix command injection in docker logs API#74
bobdivx wants to merge 1 commit into
devfrom
jules-12882890723391972388-c844a712

Conversation

@bobdivx
Copy link
Copy Markdown
Owner

@bobdivx bobdivx commented May 29, 2026

🚨 Severity: CRITICAL
💡 Vulnerability: Command injection in src/pages/api/docker-logs.ts. User input for id and tail were passed unvalidated to execSync via string interpolation.
🎯 Impact: High. An attacker could run arbitrary shell commands on the system by crafting malicious input in the id parameter.
🔧 Fix: Switched from execSync to execFileSync using an argument array to bypass shell interpretation. Added robust input validation to ensure the id matches an alphanumeric/dash regex and tail is an integer. Appended -- before the container ID to prevent argument/flag injection. Sanitized the returned error string.
✅ Verification: Ran pnpm run check and pnpm test. Executed a local injection test script to verify that shell commands embedded in id are now correctly passed as a single string to the docker logs process rather than evaluated.


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

Co-authored-by: bobdivx <6737167+bobdivx@users.noreply.github.com>
@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.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

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

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

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 API by replacing execSync with execFileSync, adding strict input validation for the container ID and tail parameters, and sanitizing error messages. The review feedback recommends replacing the synchronous process execution with an asynchronous execFile to avoid blocking the Node.js event loop, and updating the container ID validation regex to allow dots, which are valid characters in Docker container names.

Comment on lines +1 to +2
import type { APIRoute } from "astro";
import { execFileSync } from "child_process";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Using synchronous process execution (execFileSync) in an API route blocks the Node.js event loop. This can lead to severe performance degradation or Denial of Service (DoS) when multiple requests are handled concurrently, especially since container logs can be large or slow to retrieve. Switch to the asynchronous execFile wrapped in a Promise instead.

import type { APIRoute } from "astro";
import { execFile } from "child_process";
import { promisify } from "util";

const execFileAsync = promisify(execFile);

Comment on lines 52 to 68
let logs = [];
try {
const output = execSync(command, { stdio: ['pipe', 'pipe', 'pipe'] }).toString();
logs = output.trim().split('\n');
// Using execFileSync with an argument array to prevent shell injection
const output = execFileSync(
"docker",
["logs", "--tail", String(tail), "--", containerId],
{ stdio: ["pipe", "pipe", "pipe"] },
).toString();
logs = output.trim().split("\n");
} 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;
}
// 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;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Replace execFileSync with the asynchronous execFileAsync to avoid blocking the Node.js event loop during process execution.

    let logs = [];
    try {
      // Using execFileAsync with an argument array to prevent shell injection and avoid blocking the event loop
      const { stdout } = await execFileAsync(
        "docker",
        ["logs", "--tail", String(tail), "--", containerId]
      );
      logs = stdout.toString().trim().split("\n");
    } 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;
      }
    }

}

// Input validation: prevent command argument injection (no flags/unsupported chars)
if (!/^[a-zA-Z0-9_-]+$/.test(containerId)) {
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

Docker container names can contain dots (.) (e.g., my.container.name or reverse-DNS style names). The current regex /^[a-zA-Z0-9_-]+$/ will reject these valid container names. Update the regex to allow dots.

Suggested change
if (!/^[a-zA-Z0-9_-]+$/.test(containerId)) {
if (!/^[a-zA-Z0-9_.-]+$/.test(containerId)) {

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