@@ -87,6 +87,9 @@ public async Task<ActionResult> InstallLoader([FromBody] InstallRequest? request
8787 if ( string . IsNullOrEmpty ( loaderUrl ) )
8888 return NotFound ( "No release found" ) ;
8989
90+ if ( ! IsAllowedDownloadUrl ( loaderUrl ) )
91+ return BadRequest ( "下载 URL 不在白名单内" ) ;
92+
9093 var binPath = Path . Combine ( gamePath , "bin" ) ;
9194 var loaderData = await Http . GetByteArrayAsync ( loaderUrl ) ;
9295 await System . IO . File . WriteAllBytesAsync ( Path . Combine ( binPath , "version.dll" ) , loaderData ) ;
@@ -119,6 +122,9 @@ public async Task<ActionResult> InstallAppleChu([FromBody] InstallRequest? reque
119122 if ( string . IsNullOrEmpty ( url ) )
120123 return NotFound ( "No release found" ) ;
121124
125+ if ( ! IsAllowedDownloadUrl ( url ) )
126+ return BadRequest ( "下载 URL 不在白名单内" ) ;
127+
122128 var data = await Http . GetByteArrayAsync ( url ) ;
123129 var modsDir = Path . Combine ( binPath , "mods" ) ;
124130 Directory . CreateDirectory ( modsDir ) ;
@@ -137,6 +143,19 @@ public async Task<ActionResult> InstallAppleChu([FromBody] InstallRequest? reque
137143
138144 public record InstallRequest ( string ? Url ) ;
139145
146+ private static bool IsAllowedDownloadUrl ( string ? url )
147+ {
148+ if ( string . IsNullOrEmpty ( url ) ) return false ;
149+ return Uri . TryCreate ( url , UriKind . Absolute , out var uri )
150+ && uri . Host is "github.com" or "objects.githubusercontent.com" or "api.github.com"
151+ && uri . AbsolutePath . StartsWith ( "/MuNET-OSS/" , StringComparison . OrdinalIgnoreCase ) ;
152+ }
153+
154+ private static bool IsValidModId ( string modId )
155+ {
156+ return ! string . IsNullOrEmpty ( modId ) && System . Text . RegularExpressions . Regex . IsMatch ( modId , @"^[A-Za-z0-9_-]+$" ) ;
157+ }
158+
140159 private static async Task < GitHubRelease ? > GetLatestRelease ( string repo , string assetName )
141160 {
142161 try
@@ -153,6 +172,9 @@ public record InstallRequest(string? Url);
153172 [ HttpGet ( "manifest/{modId}" ) ]
154173 public ActionResult < object > GetManifest ( string modId )
155174 {
175+ if ( ! IsValidModId ( modId ) )
176+ return BadRequest ( "无效的 modId" ) ;
177+
156178 var source = Path . Combine ( StaticSettings . ExeDir , "Resources" , modId , "manifest.toml" ) ;
157179 if ( ! System . IO . File . Exists ( source ) )
158180 return NotFound ( ) ;
@@ -164,6 +186,8 @@ public ActionResult<object> GetManifest(string modId)
164186 [ HttpGet ( "config/{modId}" ) ]
165187 public ActionResult < ModConfigRequest > GetConfig ( string modId )
166188 {
189+ if ( ! IsValidModId ( modId ) )
190+ return BadRequest ( "无效的 modId" ) ;
167191 if ( ! TryResolveGameFile ( $ "{ modId } .toml", out var path ) )
168192 return BadRequest ( "GamePath not set" ) ;
169193 if ( ! System . IO . File . Exists ( path ) )
@@ -181,6 +205,8 @@ public ActionResult<ModConfigRequest> GetConfig(string modId)
181205 [ HttpPut ( "config/{modId}" ) ]
182206 public ActionResult SaveConfig ( string modId , [ FromBody ] ModConfigRequest request )
183207 {
208+ if ( ! IsValidModId ( modId ) )
209+ return BadRequest ( "无效的 modId" ) ;
184210 if ( ! TryResolveGameFile ( $ "{ modId } .toml", out var path ) )
185211 return BadRequest ( "GamePath not set" ) ;
186212
0 commit comments