authzutil

package
v0.4.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	SequentialIntPattern  = regexp.MustCompile(`^\d{1,10}$`)
	StructuredCodePattern = regexp.MustCompile(`(?i)^[A-Z]{1,4}-\d{3,10}(-\d+)?$`)
	UUIDv1Pattern         = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)
	UUIDv4Pattern         = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)
	HexPattern            = regexp.MustCompile(`(?i)^[0-9a-f]{16,64}$`)
	EmailPattern          = regexp.MustCompile(`(?i)^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
)

Value classification patterns.

View Source
var EnforcementStrings = []string{
	"unauthorized",
	"forbidden",
	"access denied",
	"access_denied",
	"not authorized",
	"not_authorized",
	"permission denied",
	"permission_denied",
	"insufficient privileges",
	"insufficient permissions",
	"requires authentication",
	"authentication required",
	"login required",
	"you do not have permission",
	"you don't have permission",
	"not allowed",
	"no access",
	"invalid token",
	"token expired",
}

EnforcementStrings are substrings in response bodies that indicate authorization enforcement.

View Source
var HighSignalNames = map[string]struct{}{
	"id":             {},
	"uid":            {},
	"user_id":        {},
	"userid":         {},
	"account_id":     {},
	"accountid":      {},
	"order_id":       {},
	"orderid":        {},
	"profile_id":     {},
	"profileid":      {},
	"customer_id":    {},
	"customerid":     {},
	"record_id":      {},
	"recordid":       {},
	"doc_id":         {},
	"docid":          {},
	"invoice_id":     {},
	"invoiceid":      {},
	"transaction_id": {},
	"transactionid":  {},
	"file_id":        {},
	"fileid":         {},
	"message_id":     {},
	"messageid":      {},
	"comment_id":     {},
	"commentid":      {},
	"project_id":     {},
	"projectid":      {},
	"team_id":        {},
	"teamid":         {},
	"org_id":         {},
	"orgid":          {},
	"report_id":      {},
	"reportid":       {},
	"ticket_id":      {},
	"ticketid":       {},
	"session_id":     {},
	"sessionid":      {},
}

HighSignalNames are parameter names that strongly indicate object identifiers.

View Source
var IDSuffixPattern = regexp.MustCompile(`(?i)(.*_)?(id|Id|ID)$`)

IDSuffixPattern matches parameter names ending with _id, Id, or ID.

View Source
var LoginRedirectPatterns = []string{
	"/login",
	"/signin",
	"/sign-in",
	"/auth/login",
	"/auth/signin",
	"/sso/",
	"/oauth/",
	"/cas/login",
}

LoginRedirectPatterns are URL path prefixes that indicate a login redirect.

View Source
var MediumSignalNames = map[string]struct{}{
	"num":    {},
	"number": {},
	"no":     {},
	"ref":    {},
	"key":    {},
	"token":  {},
	"code":   {},
	"handle": {},
	"slug":   {},
	"uuid":   {},
	"guid":   {},
}

MediumSignalNames are parameter names that may indicate identifiers but are less specific.

View Source
var ResourceNouns = map[string]struct{}{
	"users":         {},
	"accounts":      {},
	"orders":        {},
	"profiles":      {},
	"customers":     {},
	"invoices":      {},
	"documents":     {},
	"messages":      {},
	"files":         {},
	"tickets":       {},
	"projects":      {},
	"reports":       {},
	"transactions":  {},
	"comments":      {},
	"teams":         {},
	"organizations": {},
	"items":         {},
	"products":      {},
	"payments":      {},
	"subscriptions": {},
	"notifications": {},
	"roles":         {},
	"groups":        {},
	"events":        {},
	"sessions":      {},
	"books":         {},
	"baskets":       {},
	"reviews":       {},
	"posts":         {},
	"articles":      {},
	"blogs":         {},
	"categories":    {},
}

ResourceNouns are URL path segments that typically precede object identifiers.

View Source
var SensitiveResponseFields = map[string]struct{}{
	"password_hash":   {},
	"password_digest": {},
	"secret_key":      {},
	"private_key":     {},
	"api_secret":      {},
	"internal_id":     {},
	"ssn":             {},
	"social_security": {},
	"credit_card":     {},
	"card_number":     {},
	"cvv":             {},
	"is_admin":        {},
	"isadmin":         {},
	"is_superuser":    {},
	"permissions":     {},
	"access_level":    {},
}

SensitiveResponseFields are JSON field names in responses that indicate excessive data exposure.

Functions

func BaselineLinksNeighbor

func BaselineLinksNeighbor(baselineBody, neighborTarget string) bool

BaselineLinksNeighbor reports whether the baseline response body already links to the neighbor request target — the page itself offers the neighbor as navigation (a "Next"/"Prev" pagination link, a sibling href, a catalog entry). A document never links to another user's *private* object as navigation, so a neighbor reachable straight from the page is intended public browsing, not a broken-authorization bypass.

This is the dominant IDOR false positive on blogs, documentation and product catalogs — e.g. GET /blog/3/ whose body contains href="/blog/4/" and href="/blog/2/", so probing the 2/4 neighbors merely re-fetches pages the site links to anyway.

neighborTarget is the neighbor request's path including any query string. It is only treated as a link signal when specific enough that an incidental short numeric substring cannot match: it must carry a query or a non-numeric path segment, so a bare "/4" does not match arbitrary digits in the body.

func ClassifyParamValue

func ClassifyParamValue(value string) (IDType, Predictability, int)

ClassifyParamValue determines the type and predictability of an identifier value.

func ClassifyPathContext

func ClassifyPathContext(pathSegments []string, segmentValue string) (string, int)

ClassifyPathContext checks if a value appears in a URL path immediately after a resource noun.

func ContainsEnforcementString

func ContainsEnforcementString(body string) bool

ContainsEnforcementString checks if the first 4KB of a response body contains any soft-denial substring indicating authorization enforcement.

func GenerateNeighborIDs

func GenerateNeighborIDs(baseValue string, idType IDType, count int) []string

GenerateNeighborIDs produces candidate neighbor IDs for a given base value based on its detected IDType. Returns nil for unpredictable types (UUIDv4, Hex, Unknown).

func IsAuthChallengePage

func IsAuthChallengePage(body string) bool

IsAuthChallengePage reports whether a response body is an authentication or single-sign-on page (a login form, an OAuth/OIDC/SAML challenge, or an authorization-denied notice) rather than a distinct application object.

IDOR/BOLA modules use this as a negative confirmation gate: a predicted identifier that merely returns the login page is not evidence of a predictable object reference. Every unauthenticated request to a protected endpoint returns the same login shell — only the per-request CSRF/session tokens differ — so a naive "200 + body differs from baseline" oracle fires on pure session-token noise (the Keycloak /openid-connect/auth false positive).

func IsLoginRedirect

func IsLoginRedirect(statusCode int, location string) bool

IsLoginRedirect checks if a response is a redirect to a login page.

func NormalizeName

func NormalizeName(name string) string

NormalizeName converts camelCase and kebab-case parameter names to lowercase snake_case.

func RequestCarriesCredential

func RequestCarriesCredential(req *httpmsg.HttpRequest) bool

RequestCarriesCredential reports whether an HTTP request presents a user-identifying credential — an Authorization header, a Cookie, a well-known API-token header, or a credential query parameter.

IDOR / BOLA is by definition an *authorization* flaw: one principal reaching another principal's object. When the original request carries no credential there is no per-user authorization boundary to cross, so a neighbor id that returns "different but valid" content is most often just public, navigable content — a blog, a docs site, a product catalog — where distinct ids are *expected* to serve distinct pages (e.g. GET /blog/3/ vs /blog/4/). Modules use this to gate severity: without a credential the differential is a weak lead, not a High/Firm authorization bypass.

Types

type AuthzVerdict

type AuthzVerdict int

AuthzVerdict indicates whether authorization was enforced, bypassed, or uncertain.

const (
	VerdictEnforced  AuthzVerdict = iota // Access was denied
	VerdictBypassed                      // Access was granted (potential vulnerability)
	VerdictUncertain                     // Could not determine
)

func (AuthzVerdict) String

func (v AuthzVerdict) String() string

String returns a human-readable label for an AuthzVerdict.

type CompareOptions

type CompareOptions struct {
	SimilarityThreshold float64
	UserSpecificFields  []string
}

CompareOptions configures response comparison behavior.

func DefaultCompareOptions

func DefaultCompareOptions() CompareOptions

DefaultCompareOptions returns sensible defaults for response comparison.

type IDClassification

type IDClassification struct {
	IsObjectID     bool
	IDType         IDType
	Predictability Predictability
	NameSignal     NameSignal
	NameScore      int
	ValueScore     int
	PathScore      int
	TotalScore     int
	ResourceNoun   string
}

IDClassification holds the full classification result for a parameter.

func ClassifyParam

func ClassifyParam(name, value string, isPathParam bool, pathSegments []string) IDClassification

ClassifyParam performs full classification of a parameter as a potential object identifier.

type IDType

type IDType int

IDType classifies the format of an identifier value.

const (
	Unknown        IDType = iota
	SequentialInt         // 1, 42, 123456
	ShortNumeric          // 1-3 digit numbers (low predictability)
	StructuredCode        // ORD-12345, INV-001-2
	Base64Int             // base64-encoded integer
	UUIDv1                // time-based UUID
	UUIDv4                // random UUID
	Hex                   // 16-64 character hex string
	Email                 // user@example.com
	Slug                  // human-readable-slug
)

func (IDType) String

func (t IDType) String() string

String returns a human-readable label for an IDType value.

type NameSignal

type NameSignal int

NameSignal indicates how strongly a parameter name suggests an object identifier.

const (
	NoSignal     NameSignal = 0
	MediumSignal NameSignal = 2
	HighSignal   NameSignal = 3
)

func ClassifyParamName

func ClassifyParamName(name string) (NameSignal, int)

ClassifyParamName evaluates whether a parameter name looks like an object identifier.

func (NameSignal) String

func (s NameSignal) String() string

String returns a human-readable label for a NameSignal value.

type Predictability

type Predictability int

Predictability indicates how easy it is to enumerate or guess an identifier.

const (
	PredictNone     Predictability = 0
	PredictLow      Predictability = 1
	PredictMedium   Predictability = 2
	PredictHigh     Predictability = 3
	PredictVeryHigh Predictability = 4
)

func (Predictability) String

func (p Predictability) String() string

String returns a human-readable label for a Predictability value.

type ResponseComparison

type ResponseComparison struct {
	StatusCodeMatch       bool
	BodyLengthDelta       int
	BodyLengthRatio       float64
	ContentIdentical      bool
	StructurallyIdentical bool
	UserFieldsDiffer      bool
	DifferingFields       []string
	SharedFields          []string
}

ResponseComparison holds the result of comparing two HTTP responses.

func CompareResponses

func CompareResponses(baseline, probe *ResponseSummary, opts CompareOptions) *ResponseComparison

CompareResponses compares a baseline response against a probe response.

type ResponseSummary

type ResponseSummary struct {
	StatusCode      int
	BodyLength      int
	ContentType     string
	Body            []byte
	HasErrorMessage bool
}

ResponseSummary captures the key attributes of an HTTP response for comparison.

func SummarizeResponse

func SummarizeResponse(statusCode int, contentType string, body []byte) *ResponseSummary

SummarizeResponse creates a ResponseSummary from raw response attributes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL