MCPcopy
hub / github.com/PatchMon/PatchMon / SaveCredentials

Method SaveCredentials

agent-source-code/internal/config/config.go:285–355  ·  view source on GitHub ↗

SaveCredentials saves API credentials to file using atomic write to prevent TOCTOU race

(apiID, apiKey string)

Source from the content-addressed store, hash-verified

283
284// SaveCredentials saves API credentials to file using atomic write to prevent TOCTOU race
285func (m *Manager) SaveCredentials(apiID, apiKey string) error {
286 if err := m.setupDirectories(); err != nil {
287 return err
288 }
289
290 m.credentials = &models.Credentials{
291 APIID: apiID,
292 APIKey: apiKey,
293 }
294
295 // Generate YAML content manually to avoid viper's default file creation
296 content := fmt.Sprintf("api_id: %s\napi_key: %s\n", apiID, apiKey)
297
298 // Use atomic write pattern to prevent TOCTOU race condition:
299 // 1. Write to temp file with secure permissions from the start
300 // 2. Atomically rename to target file
301 dir := filepath.Dir(m.config.CredentialsFile)
302
303 // Create temp file in same directory (required for atomic rename)
304 // Use O_CREATE|O_EXCL to prevent race on temp file creation
305 // File is created with 0600 permissions from the start
306 tmpFile, err := os.CreateTemp(dir, ".credentials-*.tmp")
307 if err != nil {
308 return fmt.Errorf("error creating temp credentials file: %w", err)
309 }
310 tmpPath := tmpFile.Name()
311
312 // Clean up temp file on any error
313 defer func() {
314 if tmpFile != nil {
315 if err := tmpFile.Close(); err != nil {
316 // Use a logger if available, otherwise ignore in defer
317 _ = err
318 }
319 }
320 // Remove temp file if it still exists (rename failed or error occurred)
321 if err := os.Remove(tmpPath); err != nil && !os.IsNotExist(err) {
322 // Ignore "file not found" errors in cleanup
323 _ = err
324 }
325 }()
326
327 // Set secure permissions on temp file before writing content
328 if err := tmpFile.Chmod(0600); err != nil {
329 return fmt.Errorf("error setting temp file permissions: %w", err)
330 }
331
332 // Write credentials to temp file
333 if _, err := tmpFile.WriteString(content); err != nil {
334 return fmt.Errorf("error writing credentials to temp file: %w", err)
335 }
336
337 // Ensure data is flushed to disk before rename
338 if err := tmpFile.Sync(); err != nil {
339 return fmt.Errorf("error syncing temp file: %w", err)
340 }
341
342 // Close the file before rename (required on some systems)

Callers 1

configureCredsFunction · 0.80

Calls 5

setupDirectoriesMethod · 0.95
RemoveMethod · 0.80
WriteStringMethod · 0.80
NameMethod · 0.65
CloseMethod · 0.45

Tested by

no test coverage detected