Skip to content

OWASP Top 10

Every pull request runs the “Security (OWASP Top 10)” CI job (make owasp), which fails when a change breaks one of the checks below. It has four steps:

Step Make target What it does
Static analysis make gosec gosec through golangci-lint on every module: SQL built with string formatting, weak crypto and random numbers, unsafe file paths and commands, integer overflows, insecure cookies. make lint runs it too.
Known vulnerabilities make vulncheck govulncheck on every module, including the standard library of the Go that runs it.
Security tests make test-owasp The tests listed below, including the tests of a fresh dygo new -security project, plain and OIDC.
Fuzzing make fuzz The request binder (path, query, header, cookie, JSON, form, multipart) and the SQL placeholder compiler.

Dependabot (.github/dependabot.yml) opens a weekly PR for Go modules and CI actions, and every action in the workflows is pinned to a commit.

Run make owasp locally before a release; it needs network access for the tools and the vulnerability database.

The tests named security_test.go are the ones dygo g security generates; examples/academy/internal/modules/security runs the same tests.

Category What protects an app Checked by
A01 Broken access control Deny by default, ordered path rules, Roles, Authorities, Require, RequireOwner; generated CRUD needs a role to write TestDenyByDefault, TestPathRules, TestRolesAndAuthorities, TestRequireAndOwner; generated *.controller_test.go check 401 and 403; TestGenerateSecurityGolden
A02 Cryptographic failures HS256 with a secret of 32+ characters (required in production); RS256/ES256 from the provider’s keys; PBKDF2 passwords with rehash; refresh tokens stored hashed TestForgedTokens, TestProviderTokens, TestRehash; gosec
A03 Injection ? placeholders; OrderBy and Patch only accept known columns; strict JSON (unknown fields and trailing data refused) TestRepositoryOrderByChecksColumns, TestMemoryRepository, TestStrictJSONAndContentType; FuzzCompile, FuzzBind*; gosec (G201, G202)
A04 Insecure design Limits by default: body size, login and refresh rate limits, refresh reuse ends the login TestBodyLimit, TestHTTPBindErrorsAndLimits, TestRateLimit, TestRefreshReuseRevokesLogin, TestRefreshRace
A05 Security misconfiguration SecureHeaders and CORS middleware (dygo new and dygo g security add them); a 500 never shows the error; AUTH_SECRET and https issuer required in production TestSecureHeaders, TestCORS, TestCSRF, TestHTTPNotFoundAndPanic, TestGenerateSecurityGolden (app middleware)
A06 Vulnerable components Few dependencies; the core uses only the standard library make vulncheck; Dependabot
A07 Identification and authentication failures Same answer and time for unknown email and wrong password; tokens only from the Authorization header; refresh rotation and logout TestRegisterLoginMe, TestForgedTokens, TestRefreshAndLogout, TestDenyByDefault
A08 Software and data integrity failures Signed tokens with a fixed algorithm (alg: none and algorithm swaps refused); actions pinned to commits; go.sum TestForgedTokens, TestProviderTokens; Dependabot
A09 Security logging and monitoring failures Denied requests, bad tokens, failed logins and reused refresh tokens are logged; passwords and tokens never are TestSecurityLog; TestOpenFailsWithoutLeakingPassword
A10 Server-side request forgery The app only calls the configured OAUTH_ISSUER_URL (https in production) and the jwks_uri it names; unknown key IDs fetch the keys at most once a minute TestUnknownKeyFetchLimit, TestKeyRotation; gosec

These checks cover the framework and the code it generates. An app still has to:

  • clean any user input it passes to dygo.File or dygo.RedirectTo;
  • build SQL with placeholders, never by joining strings, in its own queries;
  • set AUTH_SECRET, CORS_ALLOWED_ORIGINS and HTTPS in production;
  • send its logs somewhere they are watched.

The Security recipe explains the generated security package, and SECURITY.md how to report a vulnerability.