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
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0
0.1.3
12 changes: 6 additions & 6 deletions api_security.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
}

// NewAPISecurityChecker creates an APISecurityChecker with sensible defaults.
func NewAPISecurityChecker(baseURL string) *APISecurityChecker {

Check failure on line 21 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: NewAPISecurityChecker
return &APISecurityChecker{
BaseURL: strings.TrimRight(baseURL, "/"),
Headers: make(map[string]string),
Expand All @@ -33,14 +33,14 @@
}

// httpClient returns a configured HTTP client.
func (a *APISecurityChecker) httpClient() *http.Client {

Check failure on line 36 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.httpClient
return &http.Client{
Timeout: a.Timeout,
}
}

// newRequest creates a request with the configured headers.
func (a *APISecurityChecker) newRequest(method, url string, body io.Reader) (*http.Request, error) {

Check failure on line 43 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.newRequest
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
Expand All @@ -53,7 +53,7 @@

// CheckCORS tests for CORS misconfiguration by sending requests with various
// Origin headers and checking if the server reflects arbitrary origins.
func (a *APISecurityChecker) CheckCORS(url string) []Finding {

Check failure on line 56 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.CheckCORS
var findings []Finding
client := a.httpClient()

Expand All @@ -74,7 +74,7 @@
if err != nil {
continue
}
resp.Body.Close()
_ = resp.Body.Close()

acao := resp.Header.Get("Access-Control-Allow-Origin")
acac := resp.Header.Get("Access-Control-Allow-Credentials")
Expand Down Expand Up @@ -122,7 +122,7 @@
}

// CheckRateLimiting sends rapid requests to detect missing rate limiting.
func (a *APISecurityChecker) CheckRateLimiting(url string) []Finding {

Check failure on line 125 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.CheckRateLimiting
var findings []Finding
client := a.httpClient()

Expand All @@ -140,7 +140,7 @@
if err != nil {
continue
}
resp.Body.Close()
_ = resp.Body.Close()

if resp.StatusCode == http.StatusTooManyRequests {
rateLimitHeaderFound = true
Expand Down Expand Up @@ -175,7 +175,7 @@
}

// CheckAuthHeaders checks for missing security headers on API responses.
func (a *APISecurityChecker) CheckAuthHeaders(url string) []Finding {

Check failure on line 178 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.CheckAuthHeaders
var findings []Finding
client := a.httpClient()

Expand All @@ -188,7 +188,7 @@
if err != nil {
return findings
}
resp.Body.Close()
_ = resp.Body.Close()

requiredHeaders := []struct {
Name string
Expand Down Expand Up @@ -231,7 +231,7 @@
}

// CheckVerbTampering tests unusual HTTP methods for unexpected access.
func (a *APISecurityChecker) CheckVerbTampering(url string) []Finding {

Check failure on line 234 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.CheckVerbTampering
var findings []Finding
client := a.httpClient()

Expand All @@ -256,7 +256,7 @@
continue
}
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
resp.Body.Close()
_ = resp.Body.Close()

// TRACE is especially dangerous if it echoes back the request
if m.Method == "TRACE" && resp.StatusCode == http.StatusOK {
Expand Down Expand Up @@ -289,7 +289,7 @@
if err == nil {
resp, err := client.Do(req)
if err == nil {
resp.Body.Close()
_ = resp.Body.Close()
allow := resp.Header.Get("Allow")
if allow == "" {
allow = resp.Header.Get("Access-Control-Allow-Methods")
Expand All @@ -315,7 +315,7 @@

// CheckErrorLeakage sends malformed requests and checks if error responses
// leak stack traces, internal paths, or version information.
func (a *APISecurityChecker) CheckErrorLeakage(url string) []Finding {

Check failure on line 318 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.CheckErrorLeakage
var findings []Finding
client := a.httpClient()

Expand Down Expand Up @@ -370,7 +370,7 @@
continue
}
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
resp.Body.Close()
_ = resp.Body.Close()

bodyStr := string(body)

Expand Down Expand Up @@ -420,7 +420,7 @@

// CheckJWTWeakness analyzes a JWT token structure for common weaknesses:
// none algorithm, weak signing, missing expiry, excessive claims.
func (a *APISecurityChecker) CheckJWTWeakness(token string) []Finding {

Check failure on line 423 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: APISecurityChecker.CheckJWTWeakness
var findings []Finding

claims, err := ParseJWT(token)
Expand Down Expand Up @@ -537,7 +537,7 @@
}

// ParseJWT decodes a JWT token without signature validation (for analysis purposes).
func ParseJWT(token string) (*JWTClaims, error) {

Check failure on line 540 in api_security.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: ParseJWT
parts := strings.Split(token, ".")
if len(parts) < 2 || len(parts) > 3 {
return nil, fmt.Errorf("invalid JWT format: expected 2-3 parts, got %d", len(parts))
Expand Down
2 changes: 1 addition & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func loadConfigFile(dir string) (*FileConfig, error) {
return nil, nil
}

data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path comes from findInspectConfigFile(dir), which searches for .inspect.toml/.inspect.yaml in the target project directory or its parents, not attacker-controlled input
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions dependency_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ var KnownVulnerabilities = map[string][]VulnEntry{
func (d *DependencyChecker) ScanGoMod(path string) []Finding {
var findings []Finding

file, err := os.Open(path)
file, err := os.Open(path) // #nosec G304 -- path is the go.mod location supplied to this dependency checker (a project file to be scanned for vulnerable packages), not attacker-controlled input
if err != nil {
findings = append(findings, Finding{
Check: "dependency-gomod",
Expand Down Expand Up @@ -190,7 +190,7 @@ func (d *DependencyChecker) ScanGoMod(path string) []Finding {
func (d *DependencyChecker) ScanPackageJSON(path string) []Finding {
var findings []Finding

data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is the package.json location supplied to this dependency checker (a project file to be scanned for vulnerable packages), not attacker-controlled input
if err != nil {
findings = append(findings, Finding{
Check: "dependency-npm",
Expand Down Expand Up @@ -238,7 +238,7 @@ func (d *DependencyChecker) ScanPackageJSON(path string) []Finding {
func (d *DependencyChecker) ScanRequirements(path string) []Finding {
var findings []Finding

file, err := os.Open(path)
file, err := os.Open(path) // #nosec G304 -- path is the requirements.txt location supplied to this dependency checker (a project file to be scanned for vulnerable packages), not attacker-controlled input
if err != nil {
findings = append(findings, Finding{
Check: "dependency-python",
Expand Down
4 changes: 2 additions & 2 deletions internal/check/links.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ func (l *LinksCheck) checkExternalLinkWithDetector(ctx context.Context, pageURL,
getResp, err := client.Do(getReq)
if err == nil {
// Read at most 1 byte -- we only need the status code.
io.CopyN(io.Discard, getResp.Body, 1)
getResp.Body.Close()
_, _ = io.CopyN(io.Discard, getResp.Body, 1)
_ = getResp.Body.Close()
// Use the GET response status instead.
if l.isAcceptedStatus(getResp.StatusCode) {
return nil
Expand Down
4 changes: 2 additions & 2 deletions internal/check/reachability.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ func checkResourceReachable(ctx context.Context, client *http.Client, ref resour
getReq.Header.Set("User-Agent", "inspect/1.0 (reachability check)")
getResp, err := client.Do(getReq)
if err == nil {
io.CopyN(io.Discard, getResp.Body, 1)
getResp.Body.Close()
_, _ = io.CopyN(io.Discard, getResp.Body, 1)
_ = getResp.Body.Close()
if getResp.StatusCode >= 200 && getResp.StatusCode < 400 {
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions internal/check/soft404.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func (d *Soft404Detector) Detect(ctx context.Context, client *http.Client, page
return false, nil
}
probeBody, err := io.ReadAll(io.LimitReader(probeResp.Body, 1*1024*1024))
probeResp.Body.Close()
_ = probeResp.Body.Close()
if err != nil {
return false, nil
}
Expand Down Expand Up @@ -213,7 +213,7 @@ func (d *Soft404Detector) Detect(ctx context.Context, client *http.Client, page
return false, nil
}
pageBody, err := io.ReadAll(io.LimitReader(pageResp.Body, 1*1024*1024))
pageResp.Body.Close()
_ = pageResp.Body.Close()
if err != nil {
return false, nil
}
Expand Down
8 changes: 4 additions & 4 deletions internal/crawler/crawler.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ func (c *Crawler) doFetch(ctx context.Context, page *Page, targetURL string) err

// Handle auth-required responses as findings rather than errors
if resp.StatusCode == 401 || resp.StatusCode == 403 {
resp.Body.Close()
_ = resp.Body.Close()
page.StatusCode = resp.StatusCode
page.Headers = resp.Header
page.Error = nil
Expand All @@ -464,7 +464,7 @@ func (c *Crawler) doFetch(ctx context.Context, page *Page, targetURL string) err

// Handle redirects manually
if resp.StatusCode >= 300 && resp.StatusCode < 400 {
resp.Body.Close()
_ = resp.Body.Close()
loc := resp.Header.Get("Location")
if loc == "" {
page.StatusCode = resp.StatusCode
Expand Down Expand Up @@ -493,12 +493,12 @@ func (c *Crawler) doFetch(ctx context.Context, page *Page, targetURL string) err

contentType := resp.Header.Get("Content-Type")
if !strings.Contains(contentType, "text/html") {
resp.Body.Close()
_ = resp.Body.Close()
return nil
}

body, err := io.ReadAll(io.LimitReader(resp.Body, 10*1024*1024))
resp.Body.Close()
_ = resp.Body.Close()
if err != nil {
page.Error = err
return err
Expand Down
6 changes: 3 additions & 3 deletions sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func GenerateSBOMJSON(projectDir string, version string) (string, error) {
func scanGoModForSBOM(path string) []SBOMComponent {
var components []SBOMComponent

file, err := os.Open(path)
file, err := os.Open(path) // #nosec G304 -- path is filepath.Join(projectDir, "go.mod") computed by GenerateSBOM against the project directory being scanned, not attacker-controlled input
if err != nil {
return nil
}
Expand Down Expand Up @@ -160,7 +160,7 @@ func goModLineToComponent(line string) *SBOMComponent {
func scanPackageJSONForSBOM(path string) []SBOMComponent {
var components []SBOMComponent

data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is filepath.Join(projectDir, "package.json") computed by GenerateSBOM against the project directory being scanned, not attacker-controlled input
if err != nil {
return nil
}
Expand Down Expand Up @@ -203,7 +203,7 @@ func scanPackageJSONForSBOM(path string) []SBOMComponent {
func scanRequirementsForSBOM(path string) []SBOMComponent {
var components []SBOMComponent

file, err := os.Open(path)
file, err := os.Open(path) // #nosec G304 -- path is filepath.Join(projectDir, "requirements.txt") computed by GenerateSBOM against the project directory being scanned, not attacker-controlled input
if err != nil {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion symbol_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func extractSymbolName(m []string, kind, ext string) string {
}

func readLines(path string) ([]string, error) {
f, err := os.Open(path)
f, err := os.Open(path) // #nosec G304 -- path is the source file under analysis, supplied by the scanning tool's own localization phase/CLI target; reading arbitrary project files is this tool's purpose
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion template.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func ParseTemplates(data []byte) ([]RuleCheck, error) {

// LoadTemplateFile reads and parses a single YAML template file.
func LoadTemplateFile(path string) ([]RuleCheck, error) {
data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is a caller-supplied template file location (this tool's own declarative check templates), not attacker-controlled input
if err != nil {
return nil, fmt.Errorf("inspect: read template %s: %w", path, err)
}
Expand Down
Loading