From 977cda49edd586495a6a622924585e25531d7d6c Mon Sep 17 00:00:00 2001 From: Maksim An Date: Wed, 2 Sep 2026 01:31:40 -0700 Subject: [PATCH] gcs-sidecar: reject application name overrides Reject execute requests that specify an application name outside the command-line policy input. Add coverage ensuring rejected requests are not forwarded to GCS. Signed-off-by: Maksim An --- internal/gcs-sidecar/handlers.go | 3 +++ internal/gcs-sidecar/handlers_test.go | 35 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/internal/gcs-sidecar/handlers.go b/internal/gcs-sidecar/handlers.go index 62db95ab5e..33709a9278 100644 --- a/internal/gcs-sidecar/handlers.go +++ b/internal/gcs-sidecar/handlers.go @@ -369,6 +369,9 @@ func (b *Bridge) executeProcess(req *request) (err error) { if err := commonutils.UnmarshalJSONWithHresult(processParamSettings, &processParams); err != nil { return fmt.Errorf("executeProcess: invalid params type for request: %w", err) } + if processParams.ApplicationName != "" { + return fmt.Errorf("executeProcess: application name is not supported by security policy") + } commandLine := []string{processParams.CommandLine} diff --git a/internal/gcs-sidecar/handlers_test.go b/internal/gcs-sidecar/handlers_test.go index 55e7fb700b..b30f9b5b5a 100644 --- a/internal/gcs-sidecar/handlers_test.go +++ b/internal/gcs-sidecar/handlers_test.go @@ -103,6 +103,41 @@ func newTestBridge(enforcer securitypolicy.SecurityPolicyEnforcer) *Bridge { } } +func TestExecuteProcess_ApplicationNameDenied(t *testing.T) { + b := newTestBridge(&securitypolicy.OpenDoorSecurityPolicyEnforcer{}) + processParams := hcsschema.ProcessParameters{ + ApplicationName: `C:\\Windows\\System32\\not-allowed.exe`, + CommandLine: `C:\\Windows\\System32\\allowed.exe`, + } + processParamsJSON, err := json.Marshal(processParams) + if err != nil { + t.Fatalf("failed to marshal process parameters: %v", err) + } + message, err := json.Marshal(map[string]interface{}{ + "ContainerId": UVMContainerID, + "Settings": map[string]string{ + "ProcessParameters": string(processParamsJSON), + }, + }) + if err != nil { + t.Fatalf("failed to marshal execute process request: %v", err) + } + + err = b.executeProcess(&request{ + ctx: context.Background(), + message: message, + }) + if err == nil || !strings.Contains(err.Error(), "application name is not supported") { + t.Fatalf("expected application name rejection, got: %v", err) + } + + select { + case forwarded := <-b.sendToGCSCh: + t.Fatalf("rejected request must not be forwarded to GCS: %+v", forwarded) + default: + } +} + // TestModifySettings_PolicyFragment_InvalidFragment tests that a PolicyFragment // request with an invalid (non-base64, non-COSE) fragment value returns an error // from the handler. The bridge's main loop converts handler errors into error