Skip to content

Commit 14e3847

Browse files
committed
feat: Add path validation and security checks for prefab operations
1 parent f44e1b3 commit 14e3847

1 file changed

Lines changed: 23 additions & 4 deletions

File tree

MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ public static class ManagePrefabs
2424
private const string ACTION_CREATE_FROM_GAMEOBJECT = "create_from_gameobject";
2525
private const string ACTION_GET_INFO = "get_info";
2626
private const string ACTION_GET_HIERARCHY = "get_hierarchy";
27-
2827
private const string SupportedActions = ACTION_OPEN_STAGE + ", " + ACTION_CLOSE_STAGE + ", " + ACTION_SAVE_OPEN_STAGE + ", " + ACTION_CREATE_FROM_GAMEOBJECT + ", " + ACTION_GET_INFO + ", " + ACTION_GET_HIERARCHY;
2928

3029
// Pagination constants
@@ -83,6 +82,10 @@ private static object OpenStage(JObject @params)
8382
}
8483

8584
string sanitizedPath = AssetPathUtility.SanitizeAssetPath(prefabPath);
85+
if (sanitizedPath == null)
86+
{
87+
return new ErrorResponse($"Invalid prefab path: '{prefabPath}'.");
88+
}
8689
GameObject prefabAsset = AssetDatabase.LoadAssetAtPath<GameObject>(sanitizedPath);
8790
if (prefabAsset == null)
8891
{
@@ -117,7 +120,7 @@ private static object CloseStage(JObject @params)
117120

118121
string assetPath = stage.assetPath;
119122
bool saveBeforeClose = @params["saveBeforeClose"]?.ToObject<bool>() ?? false;
120-
123+
121124
if (saveBeforeClose && stage.scene.isDirty)
122125
{
123126
try
@@ -335,8 +338,8 @@ private static object CreatePrefabFromGameObject(JObject @params)
335338
/// <summary>
336339
/// Validates parameters for creating a prefab from GameObject.
337340
/// </summary>
338-
private static (bool isValid, string errorMessage, string targetName, string finalPath, bool includeInactive, bool replaceExisting, bool unlinkIfInstance)
339-
ValidateCreatePrefabParams(JObject @params)
341+
private static (bool isValid, string errorMessage, string targetName, string finalPath, bool includeInactive, bool replaceExisting, bool unlinkIfInstance)
342+
ValidateCreatePrefabParams(JObject @params)
340343
{
341344
string targetName = @params["target"]?.ToString() ?? @params["name"]?.ToString();
342345
if (string.IsNullOrEmpty(targetName))
@@ -351,6 +354,14 @@ private static (bool isValid, string errorMessage, string targetName, string fin
351354
}
352355

353356
string sanitizedPath = AssetPathUtility.SanitizeAssetPath(requestedPath);
357+
if (sanitizedPath == null)
358+
{
359+
return (false, $"Invalid prefab path (path traversal detected): '{requestedPath}'", targetName, null, false, false, false);
360+
}
361+
if (string.IsNullOrEmpty(sanitizedPath))
362+
{
363+
return (false, $"Invalid prefab path '{requestedPath}'. Path cannot be empty.", targetName, null, false, false, false);
364+
}
354365
if (!sanitizedPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
355366
{
356367
sanitizedPath += ".prefab";
@@ -510,6 +521,10 @@ private static object GetInfo(JObject @params)
510521
}
511522

512523
string sanitizedPath = AssetPathUtility.SanitizeAssetPath(prefabPath);
524+
if (sanitizedPath == null)
525+
{
526+
return new ErrorResponse($"Invalid prefab path: '{prefabPath}'.");
527+
}
513528
GameObject prefabAsset = AssetDatabase.LoadAssetAtPath<GameObject>(sanitizedPath);
514529
if (prefabAsset == null)
515530
{
@@ -551,6 +566,10 @@ private static object GetHierarchy(JObject @params)
551566
}
552567

553568
string sanitizedPath = AssetPathUtility.SanitizeAssetPath(prefabPath);
569+
if (string.IsNullOrEmpty(sanitizedPath))
570+
{
571+
return new ErrorResponse($"Invalid prefab path '{prefabPath}'. Path traversal sequences are not allowed.");
572+
}
554573

555574
// Parse pagination parameters
556575
var pagination = PaginationRequest.FromParams(@params, defaultPageSize: DefaultPageSize);

0 commit comments

Comments
 (0)