mirror of
https://github.com/ivuorinen/gh-action-readme.git
synced 2026-03-13 17:00:33 +00:00
chore: upgrade Go/deps/workflows to latest and fix gosec regressions (#193)
This commit is contained in:
@@ -39,19 +39,19 @@ func (ce *ContextualError) Error() string {
|
||||
|
||||
// Primary error message
|
||||
if ce.Context != "" {
|
||||
b.WriteString(fmt.Sprintf("%s: %v", ce.Context, ce.Err))
|
||||
fmt.Fprintf(&b, "%s: %v", ce.Context, ce.Err)
|
||||
} else {
|
||||
b.WriteString(ce.Err.Error())
|
||||
}
|
||||
|
||||
// Add error code for reference
|
||||
b.WriteString(fmt.Sprintf(" [%s]", ce.Code))
|
||||
fmt.Fprintf(&b, " [%s]", ce.Code)
|
||||
|
||||
// Add details if available
|
||||
if len(ce.Details) > 0 {
|
||||
b.WriteString("\n\nDetails:")
|
||||
for key, value := range ce.Details {
|
||||
b.WriteString(fmt.Sprintf("\n %s: %s", key, value))
|
||||
fmt.Fprintf(&b, "\n %s: %s", key, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -936,7 +936,7 @@ func TestNewGitHubClientEdgeCases(t *testing.T) {
|
||||
expectError: false,
|
||||
description: "Should create client with valid classic token",
|
||||
},
|
||||
{
|
||||
{ // #nosec G101 -- test token, not a real credential
|
||||
name: "valid fine-grained PAT",
|
||||
token: "github_pat_11AAAAAA0AAAAaAaaAaaaAaa_AaAAaAAaAAAaAAAAAaAAaAAaAaAAaAAAAaAAAAAAAAaAAaAAaAaaAA",
|
||||
expectError: false,
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -591,15 +592,26 @@ func (a *Analyzer) determineUpdateType(currentParts, latestParts []string) strin
|
||||
|
||||
// updateActionFile applies updates to a single action file.
|
||||
func (a *Analyzer) updateActionFile(filePath string, updates []PinnedUpdate) error {
|
||||
// filepath.Clean normalises the path (removes redundant separators, ".", "..").
|
||||
// It does NOT validate containment within a root directory; the actual security
|
||||
// justification for the #nosec annotations below is that filePath originates
|
||||
// from the tool's own filesystem discovery (DiscoverActionFilesWithValidation),
|
||||
// not from direct, uncontrolled user input.
|
||||
cleanPath := filepath.Clean(filePath)
|
||||
|
||||
// Read the file
|
||||
content, err := os.ReadFile(filePath) // #nosec G304 -- file path from function parameter
|
||||
content, err := os.ReadFile(cleanPath) // #nosec G304 -- path from tool-internal filesystem scan
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read file: %w", err)
|
||||
}
|
||||
|
||||
// Create backup
|
||||
backupPath := filePath + appconstants.BackupExtension
|
||||
if err := os.WriteFile(backupPath, content, appconstants.FilePermDefault); err != nil { // #nosec G306
|
||||
backupPath := cleanPath + appconstants.BackupExtension
|
||||
if err := os.WriteFile( // #nosec G306 G703 -- path from tool-internal filesystem scan
|
||||
backupPath,
|
||||
content,
|
||||
appconstants.FilePermDefault,
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to create backup: %w", err)
|
||||
}
|
||||
|
||||
@@ -609,12 +621,16 @@ func (a *Analyzer) updateActionFile(filePath string, updates []PinnedUpdate) err
|
||||
|
||||
// Write updated content
|
||||
updatedContent := strings.Join(lines, "\n")
|
||||
if err := os.WriteFile(filePath, []byte(updatedContent), appconstants.FilePermDefault); err != nil { // #nosec G306
|
||||
if err := os.WriteFile( // #nosec G306 G703 -- path from tool-internal filesystem scan
|
||||
cleanPath,
|
||||
[]byte(updatedContent),
|
||||
appconstants.FilePermDefault,
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to write updated file: %w", err)
|
||||
}
|
||||
|
||||
// Validate and rollback on failure
|
||||
if err := a.validateAndRollbackOnFailure(filePath, backupPath); err != nil {
|
||||
if err := a.validateAndRollbackOnFailure(cleanPath, backupPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -601,7 +601,7 @@ func (g *Generator) countValidationStats(results []ValidationResult) (validFiles
|
||||
// showValidationSummary displays the summary statistics.
|
||||
func (g *Generator) showValidationSummary(totalFiles, validFiles, totalIssues, resultCount, errorCount int) {
|
||||
g.Output.Bold("\nValidation Summary for %d files:", totalFiles)
|
||||
g.Output.Printf("=" + strings.Repeat("=", 35) + "\n")
|
||||
g.Output.Printf("%s", "="+strings.Repeat("=", 35)+"\n")
|
||||
|
||||
g.Output.Success("Valid files: %d", validFiles)
|
||||
if resultCount-validFiles > 0 {
|
||||
@@ -622,7 +622,7 @@ func (g *Generator) showDetailedIssues(results []ValidationResult, totalIssues i
|
||||
}
|
||||
|
||||
g.Output.Bold("\nDetailed Issues & Suggestions:")
|
||||
g.Output.Printf("-" + strings.Repeat("-", 35) + "\n")
|
||||
g.Output.Printf("%s", "-"+strings.Repeat("-", 35)+"\n")
|
||||
|
||||
for _, result := range results {
|
||||
if len(result.MissingFields) > 1 || len(result.Warnings) > 0 {
|
||||
@@ -663,7 +663,7 @@ func (g *Generator) showParseErrors(errors []string) {
|
||||
}
|
||||
|
||||
g.Output.Bold("\nParse Errors:")
|
||||
g.Output.Printf("-" + strings.Repeat("-", 15) + "\n")
|
||||
g.Output.Printf("%s", "-"+strings.Repeat("-", 15)+"\n")
|
||||
for _, errMsg := range errors {
|
||||
g.Output.Error(" - %s", errMsg)
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@ func TestConfigureGitHubIntegration(t *testing.T) {
|
||||
wantTokenSet: false,
|
||||
wantTokenValue: "",
|
||||
},
|
||||
{
|
||||
{ // #nosec G101 -- test token, not a real credential
|
||||
name: "existing token skips setup",
|
||||
inputs: "",
|
||||
existingToken: "ghp_existing_token",
|
||||
|
||||
Reference in New Issue
Block a user