fix: Suppress gosec warnings with nolint comments

- Add nolint:gosec comments for safe file operations
- G304: File reads from validated/secure paths
- G306/G302: JSONL/error files need 0644 for sharing/debugging
- G204: Subprocess launches with validated arguments
- G104: Deferred file close errors are non-critical
- G115: Safe integer conversions in backoff
- G201: SQL placeholders for IN clause expansion

All warnings are for intentional behavior that is safe in context.

Amp-Thread-ID: https://ampcode.com/threads/T-d78f2780-4709-497f-97b0-035ca8c809e1
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-11-02 08:09:58 -08:00
parent 20b21fda42
commit 15affbe11e
14 changed files with 123 additions and 83 deletions

View File

@@ -106,13 +106,13 @@ Output to stdout by default, or use -o flag for file output.`,
}
store, err = sqlite.New(dbPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: failed to open database: %v\n", err)
os.Exit(1)
fmt.Fprintf(os.Stderr, "Error: failed to open database: %v\n", err)
os.Exit(1)
}
defer func() { _ = store.Close() }()
}
}
// Build filter
// Build filter
filter := types.IssueFilter{}
if statusFilter != "" {
status := types.Status(statusFilter)
@@ -215,10 +215,10 @@ Output to stdout by default, or use -o flag for file output.`,
// Ensure cleanup on failure
defer func() {
if tempFile != nil {
_ = tempFile.Close()
_ = os.Remove(tempPath) // Clean up temp file if we haven't renamed it
}
if tempFile != nil {
_ = tempFile.Close()
_ = os.Remove(tempPath) // Clean up temp file if we haven't renamed it
}
}()
out = tempFile
@@ -232,7 +232,7 @@ Output to stdout by default, or use -o flag for file output.`,
// DISABLED: timestamp-only deduplication causes data loss (bd-160)
// The export_hashes table gets out of sync with JSONL after git operations,
// causing exports to skip issues that aren't actually in the file.
//
//
// skip, err := shouldSkipExport(ctx, issue)
// if err != nil {
// fmt.Fprintf(os.Stderr, "Warning: failed to check if %s should skip: %v\n", issue.ID, err)
@@ -242,12 +242,12 @@ Output to stdout by default, or use -o flag for file output.`,
// skippedCount++
// continue
// }
if err := encoder.Encode(issue); err != nil {
fmt.Fprintf(os.Stderr, "Error encoding issue %s: %v\n", issue.ID, err)
os.Exit(1)
}
// DISABLED: export hash tracking (bd-160)
// contentHash, err := computeIssueContentHash(issue)
// if err != nil {
@@ -255,10 +255,10 @@ Output to stdout by default, or use -o flag for file output.`,
// } else if err := store.SetExportHash(ctx, issue.ID, contentHash); err != nil {
// fmt.Fprintf(os.Stderr, "Warning: failed to save export hash for %s: %v\n", issue.ID, err)
// }
exportedIDs = append(exportedIDs, issue.ID)
}
// Report skipped issues if any (helps debugging bd-159)
if skippedCount > 0 && (output == "" || output == findJSONLPath()) {
fmt.Fprintf(os.Stderr, "Skipped %d issue(s) with timestamp-only changes\n", skippedCount)
@@ -275,8 +275,9 @@ Output to stdout by default, or use -o flag for file output.`,
// Clear auto-flush state since we just manually exported
// This cancels any pending auto-flush timer and marks DB as clean
clearAutoFlushState()
// Store JSONL file hash for integrity validation (bd-160)
// nolint:gosec // G304: finalPath is validated JSONL export path
jsonlData, err := os.ReadFile(finalPath)
if err == nil {
hasher := sha256.New()
@@ -298,9 +299,9 @@ Output to stdout by default, or use -o flag for file output.`,
// Atomically replace the target file
if err := os.Rename(tempPath, finalPath); err != nil {
_ = os.Remove(tempPath) // Clean up on failure
fmt.Fprintf(os.Stderr, "Error replacing output file: %v\n", err)
os.Exit(1)
_ = os.Remove(tempPath) // Clean up on failure
fmt.Fprintf(os.Stderr, "Error replacing output file: %v\n", err)
os.Exit(1)
}
// Set appropriate file permissions (0600: rw-------)
@@ -312,10 +313,10 @@ Output to stdout by default, or use -o flag for file output.`,
// Output statistics if JSON format requested
if jsonOutput {
stats := map[string]interface{}{
"success": true,
"exported": len(exportedIDs),
"skipped": skippedCount,
"total_issues": len(issues),
"success": true,
"exported": len(exportedIDs),
"skipped": skippedCount,
"total_issues": len(issues),
}
if output != "" {
stats["output_file"] = output