Skip to content

Harden against command/script injection#24

Merged
bart-vmware merged 1 commit into
mainfrom
harden-inputs
Jul 7, 2026
Merged

Harden against command/script injection#24
bart-vmware merged 1 commit into
mainfrom
harden-inputs

Conversation

@bart-vmware

Copy link
Copy Markdown
Member

Harden NewController against argument injection (RCE)

An advisory identified two unauthenticated RCE paths in NewController, both rooted in the same cause: user-supplied route and query values were interpolated directly into subprocess argument strings without input validation. UseShellExecute=false prevents shell metacharacter injection but not argument injection.

Attack 1 — subcommand injection via {template}:
GET /api/new/install%20<AttackerPkg> runs dotnet new install <AttackerPkg>, bypassing the EnableSensitiveEndpoints gate.

Attack 2 — RCE via --allow-scripts=yes (chained):
After Attack 1 installs a template with a RunScript post-action, GET /api/new/<shortname>?options=allow-scripts=yes executes that post-action as the service account.

Changes

src/NetCoreToolService/Controllers/NewController.cs

  • TemplateShortNameRegex ([GeneratedRegex]): ^\.?[a-zA-Z0-9][a-zA-Z0-9\-_\.]*$
    Allows all built-in dotnet new list short names (including .gitattributes, global.json, steeltoe-webapi). Blocks spaces, leading dashes, path separators, and all other injection characters. Called in GetTemplateProject and GetTemplateHelp before any subprocess call.

  • NuGetPackageIdRegex ([GeneratedRegex]): ^[A-Za-z0-9_][A-Za-z0-9\.\-]*$
    Follows the official NuGet naming rules (first char: letter/digit/underscore; subsequent chars: letters/digits/dots/dashes only). Called in InstallTemplates and UninstallTemplates after the EnableSensitiveEndpoints gate.

  • BlockedOptionNames (HashSet<string>, OrdinalIgnoreCase): allow-scripts, add-source, force, dry-run, no-update-check, interactive, project. IsValidOptionName additionally enforces ^[a-zA-Z][a-zA-Z0-9\-]*$ on every option key. Both checks are applied in ParseOptions to the key=value branch and the switch branch before any option is appended to the command line. GetTemplateProject returns 400 when ParseOptions sets invalidOptionName.

test/NetCoreToolService.Test/Controllers/NewControllerTest.cs

New [Theory] tests covering each injection vector:

  • GetTemplateProject_InjectedTemplateName_Should_Return_BadRequest
  • GetTemplateHelp_InjectedTemplateName_Should_Return_BadRequest
  • GetTemplateProject_BlockedOrInvalidOption_Should_Return_BadRequest
  • InstallTemplates_InvalidNuGetId_Should_Return_BadRequest
  • UninstallTemplates_InvalidNuGetId_Should_Return_BadRequest

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Preview link: https://netcoretoolservice-pr-24.azurewebsites.net/api/new

  • Your changes have been deployed to the preview site. The preview site will update as you add more commits to this branch.
  • The preview link is shareable, but will be deleted when the pull request is merged or closed.

This is an automated message.

@bart-vmware

Copy link
Copy Markdown
Member Author

Note: The vulnerable Microsoft.OpenAPI version can be ignored; it is a dev-only dependency that will auto-resolve once the next ASP.NET patch is released.

@bart-vmware bart-vmware requested a review from TimHess July 7, 2026 12:04
@bart-vmware bart-vmware marked this pull request as ready for review July 7, 2026 13:41
@bart-vmware bart-vmware merged commit fdb3e62 into main Jul 7, 2026
4 of 5 checks passed
@bart-vmware bart-vmware deleted the harden-inputs branch July 7, 2026 13:41
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.

2 participants