Skip to content

🔒 fix(services): sanitize unit names to prevent command injection - #165

Merged
jackby03 merged 2 commits into
mainfrom
fix/sanitize-service-unit-names-17949466509601655490
Aug 29, 2026
Merged

jackby03 merged 2 commits into
mainfrom
fix/sanitize-service-unit-names-17949466509601655490

Conversation

@jackby03

Copy link
Copy Markdown
Owner

🎯 What:
Validates user-configured service/unit names in internal/modules/services/module.go against a strict systemd unit name pattern (^[a-zA-Z0-9_.:@-]+$) and disallows leading hyphens.

⚠️ Risk:
Without unit name validation, unsanitized strings supplied via user configuration could lead to command or flag injection when passed directly to systemctl disable --now <unit>.

🛡️ Solution:

  • Added isValidUnitName helper to validate unit names.
  • Updated Audit to return a Finding with StatusError if an invalid unit name is encountered.
  • Updated Plan to skip creating Change objects for invalid unit names.
  • Added comprehensive unit tests in internal/modules/services/module_test.go.

PR created automatically by Jules for task 17949466509601655490 started by @jackby03

Validate systemd unit names against an allowlist pattern (`^[a-zA-Z0-9_.:@-]+$`)
and ensure they do not start with a leading hyphen before executing systemctl commands.
Invalid unit names produce a StatusError finding during Audit and are skipped during Plan.

Co-authored-by: jackby03 <70082129+jackby03@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

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

@jackby03

Copy link
Copy Markdown
Owner Author

I'll help you find a solution for this failing job. Let me first get the job logs to understand what's going wrong.Now let me get the failing file to see the issue:## Solution

The golangci-lint linter detected an empty branch (SA9003 staticcheck error) at line 305 in internal/modules/services/module_test.go.

The Issue:
Lines 305-307 contain an if statement with an empty body and only a comment:

if runnerCalled {
    // Note: runnerCalled would be true for the second item (valid.service), but for the first item it shouldn't be called.
}

This is flagged as code smell because the conditional does nothing.

The Fix:

Remove the empty if block entirely and move the comment above it as a standalone comment:

// Note: runnerCalled would be true for the second item (valid.service), but for the first item it shouldn't be called.

changes, err := m.Plan(context.Background(), cfg)

Alternative (if the check is intentional):

If you want to keep an assertion to verify the runner wasn't called for invalid unit names, add actual logic:

if runnerCalled {
    t.Error("runner should not be called for invalid unit names")
}

Either approach will resolve the staticcheck SA9003 error and allow the CI to pass.

@google-labs-jules

Copy link
Copy Markdown
Contributor

I'll help you find a solution for this failing job. Let me first get the job logs to understand what's going wrong.Now let me get the failing file to see the issue:## Solution

The golangci-lint linter detected an empty branch (SA9003 staticcheck error) at line 305 in internal/modules/services/module_test.go.

The Issue:
Lines 305-307 contain an if statement with an empty body and only a comment:

if runnerCalled {
    // Note: runnerCalled would be true for the second item (valid.service), but for the first item it shouldn't be called.
}

This is flagged as code smell because the conditional does nothing.

The Fix:

Remove the empty if block entirely and move the comment above it as a standalone comment:

// Note: runnerCalled would be true for the second item (valid.service), but for the first item it shouldn't be called.

changes, err := m.Plan(context.Background(), cfg)

Alternative (if the check is intentional):

If you want to keep an assertion to verify the runner wasn't called for invalid unit names, add actual logic:

if runnerCalled {
    t.Error("runner should not be called for invalid unit names")
}

Either approach will resolve the staticcheck SA9003 error and allow the CI to pass.

Thank you. The empty if branch in module_test.go has been fixed with an assertion check, and the validation order in Plan() has also been corrected.

Validate systemd unit names against an allowlist pattern (`^[a-zA-Z0-9_.:@-]+$`)
and ensure they do not start with a leading hyphen before executing systemctl commands.
Invalid unit names produce a StatusError finding during Audit and are skipped during Plan.
Also fix staticcheck SA9003 warning in test assertion.

Co-authored-by: jackby03 <70082129+jackby03@users.noreply.github.com>
@jackby03
jackby03 merged commit b73123b into main Aug 29, 2026
11 checks passed
@jackby03
jackby03 deleted the fix/sanitize-service-unit-names-17949466509601655490 branch August 29, 2026 22:30
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