mirror of
https://github.com/lukaszraczylo/filepuff-mcp.git
synced 2026-10-11 04:47:58 +00:00
fix(config): clamp max_edit_size and max_search_results
Only max_file_size and max_parse_size were clamped after reading .mcp-filepuff.json; max_edit_size and max_search_results were unbounded, letting a config file request excessive memory. Clamp max_edit_size to 100MB and max_search_results to 100k (and floor negatives to 0). Adds TestLoadClampsExcessiveLimits.
This commit is contained in:
@@ -84,14 +84,24 @@ func Load(workspaceRoot string) (*Config, error) {
|
||||
// Restore WorkspaceRoot — config file must not override path guards.
|
||||
cfg.WorkspaceRoot = savedRoot
|
||||
|
||||
// Clamp size limits to prevent config file from requesting excessive memory.
|
||||
// Clamp size/count limits so the config file cannot request excessive memory.
|
||||
const maxAllowedSize int64 = 100 * 1024 * 1024 // 100 MB
|
||||
const maxAllowedSearchResults = 100000
|
||||
if cfg.MaxFileSize > maxAllowedSize {
|
||||
cfg.MaxFileSize = maxAllowedSize
|
||||
}
|
||||
if cfg.MaxParseSize > maxAllowedSize {
|
||||
cfg.MaxParseSize = maxAllowedSize
|
||||
}
|
||||
if cfg.MaxEditSize > maxAllowedSize {
|
||||
cfg.MaxEditSize = maxAllowedSize
|
||||
}
|
||||
if cfg.MaxSearchResults > maxAllowedSearchResults {
|
||||
cfg.MaxSearchResults = maxAllowedSearchResults
|
||||
}
|
||||
if cfg.MaxSearchResults < 0 {
|
||||
cfg.MaxSearchResults = 0 // negative would re-enable unbounded search
|
||||
}
|
||||
|
||||
// Override from environment variables
|
||||
cfg.loadFromEnv()
|
||||
|
||||
@@ -183,6 +183,35 @@ func TestLoadWithConfigFile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A config file requesting excessive size/count limits must be clamped so it
|
||||
// cannot force the server into unbounded memory use.
|
||||
func TestLoadClampsExcessiveLimits(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configPath := filepath.Join(tmpDir, ".mcp-filepuff.json")
|
||||
configContent := `{
|
||||
"max_file_size": 999999999999,
|
||||
"max_parse_size": 999999999999,
|
||||
"max_edit_size": 999999999999,
|
||||
"max_search_results": 999999999
|
||||
}`
|
||||
if err := os.WriteFile(configPath, []byte(configContent), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
|
||||
cfg, err := Load(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Load failed: %v", err)
|
||||
}
|
||||
|
||||
const maxSize int64 = 100 * 1024 * 1024
|
||||
if cfg.MaxFileSize > maxSize || cfg.MaxParseSize > maxSize || cfg.MaxEditSize > maxSize {
|
||||
t.Errorf("size limits not clamped: file=%d parse=%d edit=%d", cfg.MaxFileSize, cfg.MaxParseSize, cfg.MaxEditSize)
|
||||
}
|
||||
if cfg.MaxSearchResults > 100000 {
|
||||
t.Errorf("MaxSearchResults not clamped: %d", cfg.MaxSearchResults)
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidate tests the Validate method with various inputs.
|
||||
func TestValidate(t *testing.T) {
|
||||
tests := []struct {
|
||||
|
||||
Reference in New Issue
Block a user