sdk/api/golang
Go

Go API Reference

Write type-inferred taint rules for Go code. The SDK ships with 29 pre-defined QueryType classes in codepathfinder.go_rule covering stdlib and popular frameworks, plus metadata for 33 additional classes documented in the SDK reference. The @go_rule decorator scopes analysis to Go files.

Canonical imports

Every Go rule file starts with these imports:

python
from codepathfinder.go_decorators import go_rule
from codepathfinder.go_rule import (
    GoGinContext, GoGormDB, GoStrconv,
    # ... browse the FQN browser for the full list
)
from codepathfinder import flows
from codepathfinder.presets import PropagationPresets

Browse all 70+ pre-defined classes in the Go SDK reference or the FQN browser.

@go_rule decorator

Declares a Go-scoped rule. The decorator automatically injects language="go" into the generated IR, so analysis stays within .go files.

python
@go_rule(
    id="GO-GORM-SQLI-001",            # required
    name="",                          # auto-generated from function name if empty
    severity="MEDIUM",                # CRITICAL | HIGH | MEDIUM | LOW | INFO
    category="security",
    cwe="",
    cve="",
    tags="",
    message="",                       # defaults to "Security issue detected by {id}"
    owasp="",
)
def detect_gorm_sqli():
    return flows(...)
Parameters
idrequired
str
Unique rule identifier, e.g., GO-GORM-SQLI-001.
name
str = ""
Human-readable name. Auto-generated from the function name when empty.
severity
str = "MEDIUM"
One of "CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO".
category
str = "security"
Arbitrary grouping (e.g., security, performance, best-practice).
cwe
str = ""
CWE identifier, e.g., "CWE-89".
cve
str = ""
Associated CVE ID if applicable.
tags
str = ""
Comma-separated taxonomy tags.
message
str = ""
Finding message shown to the user. Defaults to a generic message with the rule ID.
owasp
str = ""
OWASP Top 10 mapping, e.g., "A03:2021".

QueryType

Base class for type-inferred matchers. Subclass it to describe a Go type; the engine resolves the fully-qualified name of each call site and matches against fqns. Wrong FQN → 0 findings (this is the primary precision tool).

python
from codepathfinder import QueryType

class GoHTTPClient(QueryType):
    fqns = ["net/http.Client"]       # FQNs (prefix match)
    patterns = ["*http.Client"]      # pattern fallbacks with * and ?
    match_subclasses = True          # match types that embed/implement this (default True)
Class attributes
fqns
list[str]
List of exact FQNs to match. The engine prefix-matches each call site's resolved type against these. An empty list means no type-inference match, so only patterns will be used.
patterns
list[str]
Fallback glob patterns matched against type names. Supports * and ? wildcards. Use this when type inference fails or for third-party types not in the stdlib registry.
match_subclasses
bool = True
When True, the matcher also fires for subtypes / interface implementations / embedded types.
Verification test
Change fqns to garbage (e.g., "xxx"). If findings drop to 0, type inference is working. If findings persist, the engine fell through to patterns, so fix your FQN.

.method()

Selects one or more methods on a QueryType. Returns a MethodMatcher that supports .where(), .arg(), and .tracks().

python
# Single method
GoHTTPClient.method("Do")

# Multiple methods (OR semantics; any one triggers)
GoGinContext.method("Query", "Param", "PostForm", "GetHeader")

# Chained with precision modifiers
GoOSExec.method("Command").where(0, regex(r"^sh$|^bash$")).tracks(1)

Raises ValueError if called with no method names. Defined at codepathfinder/query_type.py:156-172.

.attr()

Matches attribute / field access on a typed receiver (as opposed to method calls). Returns an AttributeMethodMatcher. This matcher is terminal and cannot be chained with .where() / .tracks().

python
# HTTP request body / URL are attributes, not method calls
GoHTTPRequest.attr("Body", "URL.Path", "URL.RawQuery")

.where() and .arg()

Filters matches by argument value. .arg() is an exact alias for .where().

python
from codepathfinder import lt, regex, missing

# Positional argument (index 0)
GoOSExec.method("Command").where(0, "sh")
GoOSExec.method("Command").where(0, regex(r"^sh$|^bash$"))

# Keyword-style argument by name
GoHTTPClient.method("Get").where("url", regex(r"^http://"))

# Numeric qualifier
SomeClass.method("MakeKey").where("bits", lt(2048))

# Absent argument (missing keyword)
SomeResponse.method("SetCookie").where("Secure", missing())
Signature
position_or_namerequired
int | str
Integer = positional arg index. String = keyword name, or "return" for the return value.
constraint
Any | Qualifier | None
Plain value (exact match), Qualifier (lt/gt/regex/missing/etc.), or None to only assert the argument is present.

.tracks()

Pins taint to specific parameters. On sinks, only taint reaching a tracked parameter produces a finding. On sources, only the tracked return value / parameter is marked tainted. This is the single highest-impact precision tool, so use it on every sink.

python
# Sink: only alert if taint reaches the first positional arg
GoGormDB.method("Raw").tracks(0)

# Source: track the return value
GoOSEnv.method("Getenv").tracks("return")

# Multiple positions (OR semantics)
CursorLike.method("execute").tracks(0, "query")

Accepts int (positional), str (keyword), or the literal string "return".

Pre-defined QueryType classes

The codepathfinder.go_rule module exports 29 QueryType classes for the Go standard library and popular frameworks. Each has verified FQNs and annotated method roles (source, sink, or sanitizer).

stdlib: GoHTTPRequest, GoSQLDB, GoOS, GoOSExec, GoFmt, GoIO, GoFilepath, GoStrconv, GoJSON, GoTemplate, GoContext, GoCrypto, ...
Web frameworks: GoGinContext, GoEchoContext, GoFiberCtx, GoGorillaMuxRouter, GoChiRouter
Databases: GoGormDB, GoPgxConn, GoSqlxDB, GoRedisClient, GoMongoCollection
Auth / Config: GoJWTToken, GoGRPCServerTransportStream, GoViperConfig, GoYAMLDecoder
HTTP clients: GoHTTPClient, GoRestyClient

Complete example: GORM SQL injection

Real rule from the code-pathfinder registry (GO-GORM-SQLI-001). Detects user input from Gin / Echo / Fiber / Chi / net/http flowing into GORM's Raw() or Exec().

python
"""GO-GORM-SQLI-001: SQL injection via GORM Raw/Exec with user-controlled input."""

from codepathfinder.go_rule import (
    GoGinContext,
    GoEchoContext,
    GoFiberCtx,
    GoGormDB,
    GoHTTPRequest,
    GoStrconv,
    QueryType,
)
from codepathfinder import flows
from codepathfinder.presets import PropagationPresets
from codepathfinder.go_decorators import go_rule


class GoChiRouter(QueryType):
    fqns = ["github.com/go-chi/chi/v5"]
    patterns = ["chi.*"]
    match_subclasses = False


@go_rule(
    id="GO-GORM-SQLI-001",
    severity="CRITICAL",
    cwe="CWE-89",
    owasp="A03:2021",
    tags="go,security,sql-injection,gorm,CWE-89,OWASP-A03",
    message=(
        "User-controlled input flows into GORM Raw() or Exec() with raw SQL. "
        "Use parameterized queries: db.Raw('SELECT * WHERE name = ?', name)"
    ),
)
def detect_gorm_sqli():
    return flows(
        from_sources=[
            GoGinContext.method(
                "Query", "Param", "PostForm", "GetHeader",
                "ShouldBindJSON", "BindJSON", "GetRawData",
            ),
            GoEchoContext.method("QueryParam", "FormValue", "Param", "PathParam"),
            GoFiberCtx.method("Params", "Query", "FormValue", "Get"),
            GoHTTPRequest.method("FormValue", "PostFormValue"),
            GoHTTPRequest.attr("Body", "URL.Path", "URL.RawQuery"),
        ],
        to_sinks=[
            GoGormDB.method("Raw", "Exec"),
        ],
        sanitized_by=[
            GoStrconv.method("Atoi", "ParseInt", "ParseFloat", "ParseUint"),
        ],
        propagates_through=PropagationPresets.standard(),
        scope="global",
    )