diff --git a/doc/wiki/expressions-and-scripting.md b/doc/wiki/expressions-and-scripting.md
index 912d31eb2..f49072967 100644
--- a/doc/wiki/expressions-and-scripting.md
+++ b/doc/wiki/expressions-and-scripting.md
@@ -55,11 +55,14 @@ Additional JavaScript libraries are in [Elsa.Expressions.JavaScript.Libraries](.
```csharp
elsa.UseCSharp(options =>
{
+ options.AllowHostCodeExecution = true;
options.DisableWrappers = disableVariableWrappers;
options.AppendScript("string Greet(string name) => $\"Hello {name}!\";");
});
```
+Roslyn C# scripting is privileged host-code execution, not a sandbox. Hosts must explicitly set `CSharpOptions.AllowHostCodeExecution` to `true` before C# expressions or `RunCSharp` can be authored or executed. API callers that author, publish, dispatch, or directly execute workflows containing C# must have the `exec:csharp-expressions` permission.
+
## Python
[PythonFeature](../../src/modules/Elsa.Expressions.Python/Features/PythonFeature.cs) registers pythonnet-based evaluation and configures `PythonGlobalInterpreterManager` as a hosted service. Python.NET execution is privileged host-code execution, not a sandbox. Python code can access host process capabilities through pythonnet and must only be enabled for trusted workflow authors.
diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs
index 667108ce4..ac0403b53 100644
--- a/src/apps/Elsa.Server.Web/Program.cs
+++ b/src/apps/Elsa.Server.Web/Program.cs
@@ -86,6 +86,7 @@ services
.UseScheduling()
.UseCSharp(options =>
{
+ configuration.GetSection("Scripting:CSharp").Bind(options);
options.DisableWrappers = disableVariableWrappers;
options.AppendScript("string Greet(string name) => $\"Hello {name}!\";");
options.AppendScript("string SayHelloWorld() => Greet(\"World\");");
diff --git a/src/apps/Elsa.Server.Web/appsettings.json b/src/apps/Elsa.Server.Web/appsettings.json
index d997223f0..a1b740393 100644
--- a/src/apps/Elsa.Server.Web/appsettings.json
+++ b/src/apps/Elsa.Server.Web/appsettings.json
@@ -84,6 +84,9 @@
]
},
"Scripting": {
+ "CSharp": {
+ "AllowHostCodeExecution": false
+ },
"Python": {
"AllowHostCodeExecution": true,
"PythonDllPath": "",
diff --git a/src/common/Elsa.Api.Common/PermissionNames.cs b/src/common/Elsa.Api.Common/PermissionNames.cs
index cf75a1662..902d1ca74 100644
--- a/src/common/Elsa.Api.Common/PermissionNames.cs
+++ b/src/common/Elsa.Api.Common/PermissionNames.cs
@@ -5,6 +5,11 @@ public static class PermissionNames
public const string All = "*";
public const string ClaimType = "permissions";
+ ///
+ /// Permission required to author or execute C# workflow expressions.
+ ///
+ public const string ExecuteCSharpExpressions = "exec:csharp-expressions";
+
///
/// Permission required to author or execute Python.NET workflow expressions.
///
diff --git a/src/common/Elsa.Testing.Shared.Integration/TestApplicationBuilder.cs b/src/common/Elsa.Testing.Shared.Integration/TestApplicationBuilder.cs
index ac382f618..ccfc6dc80 100644
--- a/src/common/Elsa.Testing.Shared.Integration/TestApplicationBuilder.cs
+++ b/src/common/Elsa.Testing.Shared.Integration/TestApplicationBuilder.cs
@@ -36,7 +36,7 @@ public class TestApplicationBuilder
_configureElsa += elsa => elsa
.AddActivitiesFrom()
.UseScheduling()
- .UseCSharp()
+ .UseCSharp(options => options.AllowHostCodeExecution = true)
.UseJavaScript()
.UseLiquid()
.UseWorkflowManagement()
@@ -119,4 +119,4 @@ public class TestApplicationBuilder
_configureElsa += elsa => elsa.UseFluentStorageProvider(storage => storage.BlobStorage = sp => StorageFactory.Blobs.DirectoryFiles(Path.Combine(workflowsDirectory)));
return this;
}
-}
\ No newline at end of file
+}
diff --git a/src/modules/Elsa.Expressions.CSharp/Activities/RunCSharp/RunCSharp.cs b/src/modules/Elsa.Expressions.CSharp/Activities/RunCSharp/RunCSharp.cs
index 0bd9ac3dd..60d2638d1 100644
--- a/src/modules/Elsa.Expressions.CSharp/Activities/RunCSharp/RunCSharp.cs
+++ b/src/modules/Elsa.Expressions.CSharp/Activities/RunCSharp/RunCSharp.cs
@@ -15,7 +15,7 @@ namespace Elsa.Expressions.CSharp.Activities;
///
/// Executes C# code.
///
-[Activity("Elsa", "Scripting", "Executes C# code", DisplayName = "Run C#")]
+[Activity(WorkflowScriptActivityTypeNames.Namespace, WorkflowScriptActivityTypeNames.RunCSharpType, 1, "Executes C# code", "Scripting", DisplayName = "Run C#")]
public class RunCSharp : CodeActivity