You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: Support for adding taint analysis engine (#1486)
* feat: add taint analysis engine for data flow security
Implements SSA-based taint analysis to detect security vulnerabilities:
- G701: SQL injection via string concatenation
- G702: Command injection via user input
- G703: Path traversal via user input
- G704: SSRF via user-controlled URLs
- G705: XSS via unescaped user input
- G706: Log injection via user input
Uses golang.org/x/tools for SSA/call graph analysis with CHA.
Zero external dependencies beyond existing gosec imports.
-**Pattern-based rules** for detecting common security issues in Go code
11
+
-**SSA-based analyzers** for type conversions, slice bounds, and crypto issues
12
+
-**Taint analysis** for tracking data flow from user input to dangerous functions (SQL injection, command injection, path traversal, SSRF, XSS, log injection)
13
+
8
14
## License
9
15
10
16
Licensed under the Apache License, Version 2.0 (the "License").
@@ -216,6 +222,12 @@ directory you can supply `./...` as the input argument.
[CONTRIBUTING.md](https://github.com/securego/gosec/blob/master/CONTRIBUTING.md) contains detailed information about adding new rules to gosec.
500
512
513
+
### Creating Taint Analysis Rules
514
+
515
+
gosec supports taint analysis to track data flow from untrusted sources (user input) to dangerous sinks (functions that could cause security vulnerabilities). The taint analysis rules detect issues like SQL injection, command injection, path traversal, SSRF, XSS, and log injection.
516
+
517
+
#### Creating a New Taint Rule
518
+
519
+
To create a new taint analysis rule:
520
+
521
+
1.**Create the analyzer file** in `analyzers/` (e.g., `analyzers/newvuln.go`) with both the configuration and analyzer:
522
+
523
+
```go
524
+
package analyzers
525
+
526
+
import (
527
+
"golang.org/x/tools/go/analysis"
528
+
"github.com/securego/gosec/v2/taint"
529
+
)
530
+
531
+
// NewVulnerability returns a configuration for detecting your vulnerability
2.**Register the analyzer** in `analyzers/analyzerslist.go`:
561
+
562
+
```go
563
+
vardefaultAnalyzers = []AnalyzerDefinition{
564
+
// ... existing analyzers ...
565
+
{"G7XX", "Description of vulnerability", newNewVulnAnalyzer},
566
+
}
567
+
```
568
+
569
+
3.**Add test samples** in `testutils/g7xx_samples.go`:
570
+
571
+
```go
572
+
package testutils
573
+
574
+
import"github.com/securego/gosec/v2"
575
+
576
+
// SampleCodeG7XX - Description of vulnerability
577
+
varSampleCodeG7XX = []CodeSample{
578
+
{[]string{`
579
+
package main
580
+
581
+
import (
582
+
"dangerous/package"
583
+
"net/http"
584
+
)
585
+
586
+
func handler(r *http.Request) {
587
+
input := r.URL.Query().Get("param")
588
+
dangerous.DangerousFunc(input) // Should detect
589
+
}
590
+
`}, 1, gosec.NewConfig()},
591
+
{[]string{`
592
+
package main
593
+
594
+
import (
595
+
"dangerous/package"
596
+
)
597
+
598
+
func safeHandler() {
599
+
// Safe - no user input
600
+
dangerous.DangerousFunc("constant")
601
+
}
602
+
`}, 0, gosec.NewConfig()},
603
+
}
604
+
```
605
+
606
+
Then add the test case to `analyzers/analyzers_test.go`:
607
+
608
+
```go
609
+
It("should detect your new vulnerability", func() {
610
+
runner("G7XX", testutils.SampleCodeG7XX)
611
+
})
612
+
```
613
+
614
+
#### Source and Sink Configuration
615
+
616
+
**Sources** define where tainted (untrusted) data originates:
617
+
-`Package`: The import path (e.g., `"net/http"`)
618
+
-`Name`: The type or function name (e.g., `"Request"`)
619
+
-`Pointer`: Set to `true` if it's a pointer type (e.g., `*http.Request`)
620
+
621
+
**Sinks** define dangerous functions that should not receive tainted data:
622
+
-`Package`: The import path (e.g., `"database/sql"`)
623
+
-`Receiver`: The type name for methods (e.g., `"DB"`), or empty for package functions
624
+
-`Method`: The function or method name (e.g., `"Query"`)
625
+
-`Pointer`: Set to `true` if the receiver is a pointer type
626
+
-`CheckArgs`: Optional list of argument indices to check (e.g., `[]int{1}` to check only the second argument). If omitted, all arguments are checked. Useful when some arguments are safe (like prepared statement parameters) or should be ignored (like writer arguments in `fmt.Fprintf`)
627
+
628
+
**Example with CheckArgs:**
629
+
```go
630
+
// For SQL methods, Args[0] is the receiver (*sql.DB), Args[1] is the query string
631
+
// Only check the query string; prepared statement parameters (Args[2+]) are safe
0 commit comments