Skip to content

Commit 4efdcb3

Browse files
authored
restrict vfs access to home path (#9312)
* restrict vfs access to home path * Adding test, code clean up
1 parent 52ab7b1 commit 4efdcb3

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

src/WebJobs.Script.WebHost/Management/VirtualFileSystem.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public virtual Task<HttpResponseMessage> GetItem(HttpRequest request)
6161
{
6262
string localFilePath = GetLocalFilePath(request);
6363

64+
if (!PathAccessAllowed(localFilePath))
65+
{
66+
return Task.FromResult(CreateResponse(HttpStatusCode.Forbidden));
67+
}
68+
6469
if (VfsSpecialFolders.TryHandleRequest(request, localFilePath, out HttpResponseMessage response))
6570
{
6671
return Task.FromResult(response);
@@ -111,6 +116,11 @@ public virtual Task<HttpResponseMessage> PutItem(HttpRequest request)
111116
{
112117
var localFilePath = GetLocalFilePath(request);
113118

119+
if (!PathAccessAllowed(localFilePath))
120+
{
121+
return Task.FromResult(CreateResponse(HttpStatusCode.Forbidden));
122+
}
123+
114124
if (VfsSpecialFolders.TryHandleRequest(request, localFilePath, out HttpResponseMessage response))
115125
{
116126
return Task.FromResult(response);
@@ -140,6 +150,11 @@ public virtual Task<HttpResponseMessage> DeleteItem(HttpRequest request, bool re
140150
{
141151
string localFilePath = GetLocalFilePath(request);
142152

153+
if (!PathAccessAllowed(localFilePath))
154+
{
155+
return Task.FromResult(CreateResponse(HttpStatusCode.Forbidden));
156+
}
157+
143158
if (VfsSpecialFolders.TryHandleRequest(request, localFilePath, out HttpResponseMessage response))
144159
{
145160
return Task.FromResult(response);
@@ -633,5 +648,12 @@ protected HttpResponseMessage CreateResponse(HttpStatusCode statusCode, object p
633648
}
634649
return response;
635650
}
651+
652+
private bool PathAccessAllowed(string path)
653+
{
654+
var home = ScriptSettingsManager.Instance.GetSetting(EnvironmentSettingNames.AzureWebsiteHomePath);
655+
var sitePath = !string.IsNullOrEmpty(home) ? Path.Combine(Path.GetFullPath(home), "site", "wwwroot") : _options.CurrentValue.ScriptPath;
656+
return path.StartsWith(sitePath, StringComparison.OrdinalIgnoreCase);
657+
}
636658
}
637659
}

test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/EndToEndTestFixture.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ protected EndToEndTestFixture(string rootPath, string testId,
8383

8484
public string MasterKey { get; private set; }
8585

86+
public string RootScriptPath { get; private set; }
87+
8688
protected virtual ExtensionPackageReference[] GetExtensionsToInstall()
8789
{
8890
return null;
@@ -173,6 +175,7 @@ string GetDestPath(int counter)
173175
}
174176

175177
MasterKey = await Host.GetMasterKeyAsync();
178+
RootScriptPath = _copiedRootPath;
176179
}
177180

178181
public virtual void ConfigureScriptHost(IWebJobsBuilder webJobsBuilder)

test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/SamplesEndToEndTests_CSharp.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,32 @@ public async Task AdminIsolation_ReturnsExpectedStatus(string uri, bool isAppSer
218218
}
219219
}
220220

221+
222+
223+
[Theory]
224+
[InlineData("admin/vfs/site/wwwroot/host.json", HttpStatusCode.OK)]
225+
[InlineData("admin/vfs/host.json", HttpStatusCode.Forbidden)]
226+
public async Task AccessPathOutsideHome_ReturnsExpectedStatus(string uri, HttpStatusCode expectedStatus)
227+
{
228+
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
229+
await this._fixture.AddMasterKey(request);
230+
231+
string nowString = DateTime.UtcNow.ToString("yyMMdd-HHmmss");
232+
string home = Path.Combine(Path.GetTempPath(), nowString, "home");
233+
string wwwroot = Path.Combine(home, "site", "wwwroot");
234+
FileUtility.CopyDirectory(this._fixture.RootScriptPath, wwwroot);
235+
236+
using var envVars = new TestScopedEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHomePath, home);
237+
{
238+
using (var httpClient = _fixture.Host.CreateHttpClient())
239+
{
240+
HttpResponseMessage response = await httpClient.SendAsync(request);
241+
Assert.Equal(expectedStatus, response.StatusCode);
242+
}
243+
244+
}
245+
}
246+
221247
[Theory]
222248
[InlineData("GET")]
223249
[InlineData("POST")]

0 commit comments

Comments
 (0)