gocspevaluator

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2022 License: Apache-2.0 Imports: 7 Imported by: 0

README

go-csp-evaluator

A language port of https://github.com/google/csp-evaluator to evaluate Content Security Policies for a wide range of bypasses and weaknesses in Go.

Usage

To run the validator command line tool, check out this repository and run:

  • cd cmd/validator
  • go build
Usage of ./validator:
  -input string
        input to validate, can be url, file, or raw CSP string
  -output string
        output results to JSON file
  -s    suppress output to stdout

Examples:

Read the Content-Security-Policy header from https://www.mozilla.org/en-US/firefox/new/ and report to console.

./validator -input "https://www.mozilla.org/en-US/firefox/new/"

Read the firefox_sample.txt file, output json results to firefox.json and suppress output to console:

./validator -input firefox_sample.txt -output firefox.json -s

Read the Content-Security-Policy from the command line:

./validator -input "script-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com 'unsafe-inline' 'unsafe-eval' www.googletagmanager.com www.google-analytics.com tagmanager.google.com www.youtube.com s.ytimg.com cdn-3.convertexperiments.com app.convert.com data.track.convertexperiments.com 1003350.track.convertexperiments.com 1003343.track.convertexperiments.com cdn.cookielaw.org assets.getpocket.com; child-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com www.googletagmanager.com www.google-analytics.com www.youtube-nocookie.com trackertest.org www.surveygizmo.com accounts.firefox.com accounts.firefox.com.cn www.youtube.com; frame-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com www.googletagmanager.com www.google-analytics.com www.youtube-nocookie.com trackertest.org www.surveygizmo.com accounts.firefox.com accounts.firefox.com.cn www.youtube.com; connect-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com www.googletagmanager.com www.google-analytics.com logs.convertexperiments.com 1003350.metrics.convertexperiments.com 1003343.metrics.convertexperiments.com sentry.prod.mozaws.net o1069899.sentry.io cdn.cookielaw.org privacyportal.onetrust.com https://accounts.firefox.com/ getpocket.com stage.cjms.nonprod.cloudops.mozgcp.net cjms.services.mozilla.com; font-src 'self' assets.getpocket.com; style-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com 'unsafe-inline' app.convert.com; default-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com; img-src 'self' *.mozilla.net *.mozilla.org *.mozilla.com data: mozilla.org www.googletagmanager.com www.google-analytics.com adservice.google.com adservice.google.de adservice.google.dk creativecommons.org cdn-3.convertexperiments.com logs.convertexperiments.com images.ctfassets.net cdn.cookielaw.org ad.doubleclick.net"

Documentation

Index

Constants

This section is empty.

Variables

*

  • Set of default checks to run.
View Source
var DIRECTIVES_CAUSING_XSS = []Directive{SCRIPT_SRC, OBJECT_SRC, BASE_URI}
View Source
var HASH_PATTERN = regexp.MustCompile(`^\'(sha256|sha384|sha512)-(.+)\'$`)

* A regex pattern to check hash prefix.

View Source
var IPV6_PATTERN = regexp.MustCompile(`^\[[\d:]+\]`)
View Source
var NONCE_PATTERN = regexp.MustCompile(`^\'nonce-(.+)\'$`)

* A regex pattern for checking if nonce prefix.

View Source
var REMOVE_PROTO_AGNOSTIC = regexp.MustCompile(`^\/\/`)
View Source
var REMOVE_URL_PATTERN = regexp.MustCompile(`^\w[+\w.-]*:\/\/`)

*

  • Strict CSP and backward compatibility checks.
View Source
var STRICT_HASH_PATTERN = regexp.MustCompile(`^\'(sha256|sha384|sha512)-[a-zA-Z0-9+/]+[=]{0,2}\'$`)

*

  • A regex pattern to check hash prefix and Base64 formatting of a hash value.
View Source
var STRICT_NONCE_PATTERN = regexp.MustCompile(`^\'nonce-[a-zA-Z0-9+/_-]+[=]{0,2}\'$`)

*

  • A regex pattern to check nonce prefix and Base64 formatting of a nonce value.
View Source
var URL_SCHEMES_CAUSING_XSS = []string{"data:", "http:", "https:"}
View Source
var URL_SCHEME_PATTERN = regexp.MustCompile(`^[a-zA-Z][+a-zA-Z0-9.-]*:$`)
View Source
var VALID_SHA_PATTERN = regexp.MustCompile(`^(sha256|sha384|sha512)-`)
View Source
var WILDCARD_PLACEHOLDER = regexp.MustCompile("^wildcard_placeholder")

Functions

func FetchDirectivesIncludes

func FetchDirectivesIncludes(directive Directive) bool

func Includes

func Includes(elements []string, key string) bool

func IsDirective

func IsDirective(directive string) bool

func IsHash

func IsHash(hash string, strictCheck bool) bool

func IsKeyword

func IsKeyword(keyword string) bool

func IsNonce

func IsNonce(nonce string, strictCheck bool) bool

func IsUrlScheme

func IsUrlScheme(urlScheme string) bool

*

func LooksLikeIPAddress

func LooksLikeIPAddress(maybeIP string) bool

*

  • Returns whether the given string "looks" like an IP address. This function
  • only uses basic heuristics and does not accept all valid IPs nor reject all
  • invalid IPs.

func NormalizeDirectiveValue

func NormalizeDirectiveValue(directiveValue string) string

func Remove

func Remove(elements []string, key string) []string

Types

type CSP

type CSP struct {
	// contains filtered or unexported fields
}

func NewCSP

func NewCSP() CSP

func (*CSP) EffectiveCSP

func (c *CSP) EffectiveCSP(version CSPVersion, optFindings ...Finding) CSP

EffectiveCSP returns CSP as it would be seen by a UA supporting a specific CSP version.

func (*CSP) EffectiveDirective

func (c *CSP) EffectiveDirective(inDirective Directive) Directive

EffectiveDirective returns default-src if directive is a fetch directive and is not present in this CSP. Otherwise the provided directive is returned.

func (*CSP) EffectiveDirectives

func (c *CSP) EffectiveDirectives(inDirectives []Directive) []Directive

EffectiveDirectives returns the passed directives if present in this CSP or default-src otherwise.

func (*CSP) GetDirective

func (c *CSP) GetDirective(directive Directive) []string

func (*CSP) PolicyHasScriptHashes

func (c *CSP) PolicyHasScriptHashes() bool

func (*CSP) PolicyHasScriptNonces

func (c *CSP) PolicyHasScriptNonces() bool

func (*CSP) PolicyHasStrictDynamic

func (c *CSP) PolicyHasStrictDynamic() bool

func (*CSP) String

func (c *CSP) String() string

type CSPEvaluator

type CSPEvaluator struct {
	// contains filtered or unexported fields
}

func NewCSPEvaluator

func NewCSPEvaluator(parsedCSP CSP, cspVersion CSPVersion) CSPEvaluator

func (*CSPEvaluator) Evaluate

func (e *CSPEvaluator) Evaluate(parsedCSPChecks, effectiveCSPChecks []CheckerFn) []Finding

type CSPParser

type CSPParser struct {
	// contains filtered or unexported fields
}

func NewCSPParser

func NewCSPParser(unparsed string) CSPParser

func (*CSPParser) Parse

func (c *CSPParser) Parse() CSP

Parse a CSP from a string.

type CSPVersion

type CSPVersion int
const (
	CSP1 CSPVersion = iota
	CSP2
	CSP3
)

type CheckerFn

type CheckerFn func(csp CSP) []Finding

type Directive

type Directive string
const (
	// Fetch directives
	CHILD_SRC       Directive = "child-src"
	CONNECT_SRC     Directive = "connect-src"
	DEFAULT_SRC     Directive = "default-src"
	FONT_SRC        Directive = "font-src"
	FRAME_SRC       Directive = "frame-src"
	IMG_SRC         Directive = "img-src"
	MEDIA_SRC       Directive = "media-src"
	OBJECT_SRC      Directive = "object-src"
	SCRIPT_SRC      Directive = "script-src"
	SCRIPT_SRC_ATTR Directive = "script-src-attr"
	SCRIPT_SRC_ELEM Directive = "script-src-elem"
	STYLE_SRC       Directive = "style-src"
	STYLE_SRC_ATTR  Directive = "style-src-attr"
	STYLE_SRC_ELEM  Directive = "style-src-elem"
	PREFETCH_SRC    Directive = "prefetch-src"

	MANIFEST_SRC Directive = "manifest-src"
	WORKER_SRC   Directive = "worker-src"

	// Document directives
	BASE_URI      Directive = "base-uri"
	PLUGIN_TYPES  Directive = "plugin-types"
	SANDBOX       Directive = "sandbox"
	DISOWN_OPENER Directive = "disown-opener"

	// Navigation directives
	FORM_ACTION     Directive = "form-action"
	FRAME_ANCESTORS Directive = "frame-ancestors"
	NAVIGATE_TO     Directive = "navigate-to"

	// Reporting directives
	REPORT_TO  Directive = "report-to"
	REPORT_URI Directive = "report-uri"

	// Other directives
	BLOCK_ALL_MIXED_CONTENT   Directive = "block-all-mixed-content"
	UPGRADE_INSECURE_REQUESTS Directive = "upgrade-insecure-requests"
	REFLECTED_XSS             Directive = "reflected-xss"
	REFERRER                  Directive = "referrer"
	REQUIRE_SRI_FOR           Directive = "require-sri-for"
	TRUSTED_TYPES             Directive = "trusted-types"
	// https://github.com/WICG/trusted-types
	REQUIRE_TRUSTED_TYPES_FOR Directive = "require-trusted-types-for"
	WEBRTC                    Directive = "webrtc"
)

func (Directive) String

func (d Directive) String() string

type Finding

type Finding struct {
	FindingType FindingType
	Directive   Directive
	Description string
	Severity    Severity
	Value       string
}

A CSP Finding is returned by a CSP check and can either reference a directive value or a directive. If a directive value is referenced opt_index must be provided.

func CheckAllowlistFallback

func CheckAllowlistFallback(parsedCSP CSP) []Finding

*

  • Checks if the policy has an allowlist fallback (* or http: and https:) when
  • 'strict-dynamic' is present.
  • This will ensure backward compatibility to browser that don't support
  • 'strict-dynamic'. *
  • Example policy where this check would trigger:
  • script-src 'nonce-test' 'strict-dynamic' *
  • @param parsedCsp A parsed csp.

func CheckDeprecatedDirective

func CheckDeprecatedDirective(parsedCSP CSP) []Finding

*

  • Checks if csp contains directives that are deprecated in CSP3.
  • Findings of this check are informal only and are FP free. *
  • Example policy where this check would trigger:
  • report-uri foo.bar/csp *
  • @param parsedCsp Parsed CSP.

func CheckFlashObjectAllowlistBypass

func CheckFlashObjectAllowlistBypass(parsedCSP CSP) []Finding

*

  • Checks if allowlisted object-src origins are bypassable.
  • Findings of this check have a high severity and are FP free. *
  • Example policy where this check would trigger:
  • default-src 'none'; object-src ajax.googleapis.com *
  • @param parsedCsp Parsed CSP.

func CheckHasConfiguredReporting

func CheckHasConfiguredReporting(parsedCSP CSP) []Finding

*

  • Checks if the policy has configured reporting in a robust manner.

func CheckIPSource

func CheckIPSource(parsedCSP CSP) []Finding

*

  • Checks if csp contains IP addresses.
  • Findings of this check are informal only and are FP free. *
  • Example policy where this check would trigger:
  • script-src 127.0.0.1 *
  • @param parsedCsp Parsed CSP.

func CheckInvalidKeyword

func CheckInvalidKeyword(parsedCSP CSP) []Finding

*

  • Checks if csp contains invalid keywords. *
  • Example policy where this check would trigger:
  • script-src 'notAkeyword' *
  • @param parsedCsp A parsed csp.

func CheckMissingBaseUriDirective

func CheckMissingBaseUriDirective(parsedCSP CSP) []Finding

* * Checks if the base-uri needs to be restricted and if so, whether it has been * restricted.

func CheckMissingDirectives

func CheckMissingDirectives(parsedCSP CSP) []Finding

*

  • Checks if all necessary directives for preventing XSS are set.
  • Findings of this check have a high severity and are FP free. *
  • Example policy where this check would trigger:
  • script-src 'none' *
  • @param parsedCsp Parsed CSP.

func CheckMissingObjectSrcDirective

func CheckMissingObjectSrcDirective(parsedCSP CSP) []Finding

*

  • Checks if object-src is restricted to none either directly or via a
  • default-src.

func CheckMissingScriptSrcDirective

func CheckMissingScriptSrcDirective(parsedCSP CSP) []Finding

*

  • Checks if script-src is restricted either directly or via a default-src.

func CheckMissingSemicolon

func CheckMissingSemicolon(parsedCSP CSP) []Finding

*

  • Checks if semicolons are missing in the csp. *
  • Example policy where this check would trigger (missing semicolon before
  • start of object-src):
  • script-src foo.bar object-src 'none' *
  • @param parsedCsp A parsed csp.

func CheckMultipleMissingBaseUriDirective

func CheckMultipleMissingBaseUriDirective(parsedCSPs []CSP) []Finding

* * Checks if the base-uri needs to be restricted and if so, whether it has been * restricted.

func CheckNonceLength

func CheckNonceLength(parsedCSP CSP) []Finding

*

  • Checks if csp nonce is at least 8 characters long.
  • Findings of this check are of medium severity and are FP free. *
  • Example policy where this check would trigger:
  • script-src 'nonce-short' *
  • @param parsedCsp Parsed CSP.

func CheckPlainUrlSchemes

func CheckPlainUrlSchemes(parsedCSP CSP) []Finding

*

  • Checks if plain URL schemes (e.g. http:) are allowed in sensitive directives.
  • Findings of this check have a high severity and are FP free. *
  • Example policy where this check would trigger:
  • script-src https: http: data: *
  • @param parsedCsp Parsed CSP.

func CheckRequiresTrustedTypesForScripts

func CheckRequiresTrustedTypesForScripts(parsedCSP CSP) []Finding

*

  • Checks if the policy requires Trusted Types for scripts. *
  • I.e. the policy should have the following dirctive:
  • require-trusted-types-for 'script' *
  • @param parsedCsp A parsed csp.

func CheckScriptAllowlistBypass

func CheckScriptAllowlistBypass(parsedCSP CSP) []Finding

*

  • Checks if allowlisted origins are bypassable by JSONP/Angular endpoints.
  • High severity findings of this check are FP free. *
  • Example policy where this check would trigger:
  • default-src 'none'; script-src www.google.com *
  • @param parsedCsp Parsed CSP.

func CheckScriptUnsafeEval

func CheckScriptUnsafeEval(parsedCSP CSP) []Finding

*

  • Checks if passed csp allows eval in scripts.
  • Findings of this check have a medium severity and are FP free. *
  • Example policy where this check would trigger:
  • script-src 'unsafe-eval' *
  • @param parsedCsp Parsed CSP.

func CheckScriptUnsafeInline

func CheckScriptUnsafeInline(effectiveCsp CSP) []Finding

*

  • Checks if passed csp allows inline scripts.
  • Findings of this check are critical and FP free.
  • unsafe-inline is ignored in the presence of a nonce or a hash. This check
  • does not account for this and therefore the effectiveCsp needs to be passed. *
  • Example policy where this check would trigger:
  • script-src 'unsafe-inline' *
  • @param effectiveCsp A parsed csp that only contains values which
  • are active in a certain version of CSP (e.g. no unsafe-inline if a nonce
  • is present).

func CheckSrcHttp

func CheckSrcHttp(parsedCSP CSP) []Finding

*

  • Checks if CSP allows sourcing from http://
  • Findings of this check are of medium severity and are FP free. *
  • Example policy where this check would trigger:
  • report-uri http://foo.bar/csp *
  • @param parsedCsp Parsed CSP.

func CheckStrictDynamic

func CheckStrictDynamic(parsedCSP CSP) []Finding

func CheckStrictDynamicNotStandalone

func CheckStrictDynamicNotStandalone(parsedCSP CSP) []Finding

*

  • Checks if 'strict-dynamic' is only used together with a nonce or a hash. *
  • Example policy where this check would trigger:
  • script-src 'strict-dynamic' *
  • @param parsedCsp A parsed csp.

func CheckUnknownDirective

func CheckUnknownDirective(parsedCSP CSP) []Finding

*

  • Checks if the csp contains invalid directives. *
  • Example policy where this check would trigger:
  • foobar-src foo.bar *
  • @param parsedCsp A parsed csp.

func CheckUnsafeInlineFallback

func CheckUnsafeInlineFallback(parsedCSP CSP) []Finding

*

  • Checks if the policy has 'unsafe-inline' when a nonce or hash are present.
  • This will ensure backward compatibility to browser that don't support
  • CSP nonces or hasehs. *
  • Example policy where this check would trigger:
  • script-src 'nonce-test' *
  • @param parsedCsp A parsed csp.

func CheckWildcards

func CheckWildcards(parsedCSP CSP) []Finding

*

  • Checks if csp contains wildcards in sensitive directives.
  • Findings of this check have a high severity and are FP free. *
  • Example policy where this check would trigger:
  • script-src * *
  • @param parsedCsp Parsed CSP.

func (Finding) Equals

func (f Finding) Equals(other Finding) bool

func (Finding) HighestSeverity

func (f Finding) HighestSeverity(findings []Finding) Severity

HighestSeverity returns the highest severity of a list of findings

type FindingType

type FindingType int
const (
	// Parser checks
	MISSING_SEMICOLON FindingType = 100
	UNKNOWN_DIRECTIVE FindingType = 101
	INVALID_KEYWORD   FindingType = 102
	NONCE_CHARSET     FindingType = 106

	// Security cheks
	MISSING_DIRECTIVES      FindingType = 300
	SCRIPT_UNSAFE_INLINE    FindingType = 301
	SCRIPT_UNSAFE_EVAL      FindingType = 302
	PLAIN_URL_SCHEMES       FindingType = 303
	PLAIN_WILDCARD          FindingType = 304
	SCRIPT_ALLOWLIST_BYPASS FindingType = 305
	OBJECT_ALLOWLIST_BYPASS FindingType = 306
	NONCE_LENGTH            FindingType = 307
	IP_SOURCE               FindingType = 308
	DEPRECATED_DIRECTIVE    FindingType = 309
	SRC_HTTP                FindingType = 310

	// Strict dynamic and backward compatibility checks
	STRICT_DYNAMIC                FindingType = 400
	STRICT_DYNAMIC_NOT_STANDALONE FindingType = 401
	NONCE_HASH                    FindingType = 402
	UNSAFE_INLINE_FALLBACK        FindingType = 403
	ALLOWLIST_FALLBACK            FindingType = 404
	IGNORED                       FindingType = 405

	// Trusted Types checks
	REQUIRE_TRUSTED_TYPES_FOR_SCRIPTS FindingType = 500

	// Lighthouse checks
	REPORTING_DESTINATION_MISSING FindingType = 600
	REPORT_TO_ONLY                FindingType = 601
)

type Keyword

type Keyword string
const (
	KW_SELF                     Keyword = "'self'"
	KW_NONE                     Keyword = "'none'"
	KW_UNSAFE_INLINE            Keyword = "'unsafe-inline'"
	KW_UNSAFE_EVAL              Keyword = "'unsafe-eval'"
	KW_WASM_EVAL                Keyword = "'wasm-eval'"
	KW_WASM_UNSAFE_EVAL         Keyword = "'wasm-unsafe-eval'"
	KW_STRICT_DYNAMIC           Keyword = "'strict-dynamic'"
	KW_UNSAFE_HASHED_ATTRIBUTES Keyword = "'unsafe-hashed-attributes'"
	KW_UNSAFE_HASHES            Keyword = "'unsafe-hashes'"
	KW_REPORT_SAMPLE            Keyword = "'report-sample'"
	KW_BLOCK                    Keyword = "'block'"
	KW_ALLOW                    Keyword = "'allow'"
)

func (Keyword) String

func (k Keyword) String() string

type Severity

type Severity int
const (
	SEV_HIGH         Severity = 10
	SEV_SYNTAX       Severity = 20
	SEV_MEDIUM       Severity = 30
	SEV_HIGH_MAYBE   Severity = 40
	SEV_STRICT_CSP   Severity = 45
	SEV_MEDIUM_MAYBE Severity = 50
	SEV_INFO         Severity = 60
	SEV_NONE         Severity = 100
)

type TrustedTypesSink

type TrustedTypesSink string
const (
	SCRIPT TrustedTypesSink = "'script'"
)

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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