Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion internal/check/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ func (r *Registry) Register(c Checker) {
r.checks[c.Name()] = c
}

// Truncate truncates s to at most max UTF-8 code points, appending "..." if
// the string was longer than max. It is safe for multi-byte characters.
func Truncate(s string, max int) string {
runes := []rune(s)
if len(runes) <= max {
return string(runes)
}
return string(runes[:max]) + "..."
}

// truncate is a package-level alias for internal use.
func truncate(s string, max int) string { return Truncate(s, max) }

// Filter returns only the checks whose names appear in the enabled list.
func (r *Registry) Filter(enabled []string) []Checker {
if len(enabled) == 0 {
Expand All @@ -69,7 +82,7 @@ func (r *Registry) Filter(enabled []string) []Checker {
for _, name := range enabled {
enabledSet[name] = true
}
var result []Checker
result := make([]Checker, 0, len(r.checks))
for name, chk := range r.checks {
if enabledSet[name] {
result = append(result, chk)
Expand Down
21 changes: 7 additions & 14 deletions internal/check/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func checkCSPQuality(page *crawler.Page) []Finding {
URL: page.URL,
Message: "CSP allows 'unsafe-inline' in script-src",
Fix: "Remove 'unsafe-inline' from script-src and use nonces or hashes instead",
Evidence: fmt.Sprintf("Content-Security-Policy: %s", truncate(csp, 120)),
Evidence: fmt.Sprintf("Content-Security-Policy: %s", Truncate(csp, 120)),
})
}
if lower == "'unsafe-eval'" {
Expand All @@ -141,7 +141,7 @@ func checkCSPQuality(page *crawler.Page) []Finding {
URL: page.URL,
Message: "CSP allows 'unsafe-eval' in script-src",
Fix: "Remove 'unsafe-eval' and refactor code to avoid eval()",
Evidence: fmt.Sprintf("Content-Security-Policy: %s", truncate(csp, 120)),
Evidence: fmt.Sprintf("Content-Security-Policy: %s", Truncate(csp, 120)),
})
}
}
Expand All @@ -155,7 +155,7 @@ func checkCSPQuality(page *crawler.Page) []Finding {
URL: page.URL,
Message: fmt.Sprintf("CSP contains wildcard '*' in %s", directive),
Fix: fmt.Sprintf("Replace '*' in %s with specific trusted origins", directive),
Evidence: fmt.Sprintf("Content-Security-Policy: %s", truncate(csp, 120)),
Evidence: fmt.Sprintf("Content-Security-Policy: %s", Truncate(csp, 120)),
})
}
}
Expand All @@ -168,7 +168,7 @@ func checkCSPQuality(page *crawler.Page) []Finding {
URL: page.URL,
Message: "CSP missing frame-ancestors directive",
Fix: "Add frame-ancestors 'self' (or 'none') to prevent clickjacking via CSP",
Evidence: fmt.Sprintf("Content-Security-Policy: %s", truncate(csp, 120)),
Evidence: fmt.Sprintf("Content-Security-Policy: %s", Truncate(csp, 120)),
})
}

Expand All @@ -182,7 +182,7 @@ func checkCSPQuality(page *crawler.Page) []Finding {
URL: page.URL,
Message: fmt.Sprintf("CSP directive %s uses overly broad source %q", directive, src),
Fix: fmt.Sprintf("Replace %q in %s with specific domain origins", src, directive),
Evidence: fmt.Sprintf("Content-Security-Policy: %s", truncate(csp, 120)),
Evidence: fmt.Sprintf("Content-Security-Policy: %s", Truncate(csp, 120)),
})
}
}
Expand Down Expand Up @@ -258,7 +258,7 @@ func (s *SecurityCheck) checkExposedSecrets(page *crawler.Page) []Finding {
URL: page.URL,
Message: "Potential secret or credential exposed in page source",
Fix: "Remove hardcoded secrets; rotate any exposed credentials immediately",
Evidence: truncate(string(loc), 80),
Evidence: Truncate(string(loc), 80),
})
}
}
Expand Down Expand Up @@ -318,7 +318,7 @@ func (s *SecurityCheck) checkSetCookie(page *crawler.Page) []Finding {
}
}

evidence := fmt.Sprintf("Set-Cookie: %s", truncate(cookie, 80))
evidence := fmt.Sprintf("Set-Cookie: %s", Truncate(cookie, 80))

// Check missing Secure flag on HTTPS pages
if isHTTPS && !hasSecure {
Expand Down Expand Up @@ -381,10 +381,3 @@ var versionRegex = regexp.MustCompile(`\d+\.\d+`)
func containsVersion(s string) bool {
return versionRegex.MatchString(s)
}

func truncate(s string, max int) string {
if len(s) <= max {
return s
}
return s[:max] + "..."
}
Loading