diff --git a/docs/security-review/AUTH_CREDENTIAL_REVIEW.md b/docs/security-review/AUTH_CREDENTIAL_REVIEW.md index 96b73ec89..bd503a053 100644 --- a/docs/security-review/AUTH_CREDENTIAL_REVIEW.md +++ b/docs/security-review/AUTH_CREDENTIAL_REVIEW.md @@ -78,9 +78,25 @@ Authentication and authorization: - `internal/api/auth.go` - `internal/api/authorization.go` +- `internal/api/router.go` +- `internal/api/router_routes_auth_security.go` +- `internal/api/security.go` +- `internal/api/security_tokens.go` +- `internal/api/session_store.go` - `internal/api/middleware.go` - `internal/api/middleware_tenant.go` +- `internal/config/api_tokens.go` +- `internal/api/oidc_handlers.go` +- `internal/api/oidc_service.go` +- `internal/api/saml_handlers.go` +- `internal/api/saml_service.go` +- `internal/config/sso.go` - `internal/api/api_token_scope_transport_integration_test.go` +- `internal/api/oidc_legacy_callback_recovery_test.go` +- `internal/api/router_csrf_middleware_test.go` +- `internal/api/security_tokens_lifecycle_test.go` +- `internal/api/session_store_test.go` +- `internal/api/saml_service_test.go` - `internal/api/middleware_tenant_authorization_test.go` - `pkg/auth/` @@ -102,9 +118,12 @@ From a clean checkout of the commit under review, run: ``` The script prints the tested commit, records the Go toolchain version in its -output, runs the focused package and authorization tests, and validates the -public documentation mirrors. A passing result is regression evidence only. -It does not prove that the implementation is free of vulnerabilities. +output, runs the focused package and authorization tests, verifies that every +named API security regression still exists before running it, and validates +the public documentation mirrors. The explicit inventory prevents a renamed +or deleted test from becoming a silent successful no-op. A passing result is +regression evidence only. It does not prove that the implementation is free +of vulnerabilities. ## Manual review procedure diff --git a/frontend-modern/public/docs/security-review/AUTH_CREDENTIAL_REVIEW.md b/frontend-modern/public/docs/security-review/AUTH_CREDENTIAL_REVIEW.md index 96b73ec89..bd503a053 100644 --- a/frontend-modern/public/docs/security-review/AUTH_CREDENTIAL_REVIEW.md +++ b/frontend-modern/public/docs/security-review/AUTH_CREDENTIAL_REVIEW.md @@ -78,9 +78,25 @@ Authentication and authorization: - `internal/api/auth.go` - `internal/api/authorization.go` +- `internal/api/router.go` +- `internal/api/router_routes_auth_security.go` +- `internal/api/security.go` +- `internal/api/security_tokens.go` +- `internal/api/session_store.go` - `internal/api/middleware.go` - `internal/api/middleware_tenant.go` +- `internal/config/api_tokens.go` +- `internal/api/oidc_handlers.go` +- `internal/api/oidc_service.go` +- `internal/api/saml_handlers.go` +- `internal/api/saml_service.go` +- `internal/config/sso.go` - `internal/api/api_token_scope_transport_integration_test.go` +- `internal/api/oidc_legacy_callback_recovery_test.go` +- `internal/api/router_csrf_middleware_test.go` +- `internal/api/security_tokens_lifecycle_test.go` +- `internal/api/session_store_test.go` +- `internal/api/saml_service_test.go` - `internal/api/middleware_tenant_authorization_test.go` - `pkg/auth/` @@ -102,9 +118,12 @@ From a clean checkout of the commit under review, run: ``` The script prints the tested commit, records the Go toolchain version in its -output, runs the focused package and authorization tests, and validates the -public documentation mirrors. A passing result is regression evidence only. -It does not prove that the implementation is free of vulnerabilities. +output, runs the focused package and authorization tests, verifies that every +named API security regression still exists before running it, and validates +the public documentation mirrors. The explicit inventory prevents a renamed +or deleted test from becoming a silent successful no-op. A passing result is +regression evidence only. It does not prove that the implementation is free +of vulnerabilities. ## Manual review procedure diff --git a/scripts/security_review_auth_credentials.sh b/scripts/security_review_auth_credentials.sh index e2a96d6e8..0f435657a 100755 --- a/scripts/security_review_auth_credentials.sh +++ b/scripts/security_review_auth_credentials.sh @@ -2,7 +2,7 @@ set -euo pipefail -SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +SCRIPT_DIR="$(unset CDPATH; cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(dirname -- "$SCRIPT_DIR")" cd "$REPO_ROOT" @@ -14,11 +14,71 @@ go version printf '\nRunning cryptography, authentication, and configuration package tests\n' go test ./internal/crypto ./pkg/auth ./internal/config -count=1 -printf '\nRunning API authorization and configuration transfer tests\n' +printf '\nVerifying the required API security regression inventory\n' ./scripts/ensure_test_assets.sh -go test ./internal/api \ - -run '^(TestBearerAPITokenScopesDenyReadWriteAndExecRoutes|TestTenantMiddleware_.*|TestConfigTransfer.*|TestAllowUnprotectedExport.*|TestSecurityStatusMatchesConfigTransferPolicy|TestDeniedConfigTransferDoesNotMutateOrReload)$' \ - -count=1 + +# Keep this list exact rather than relying on a broad regex. Go treats a test +# command that matches no tests as successful, which would let a rename or +# deletion silently weaken the external-review baseline. +required_api_tests=( + TestAPIOnlyModeRequiresToken + TestAllowUnprotectedExportCannotOverrideAuthentication + TestAllowUnprotectedExportIsExportOnly + TestAuthenticatedEndpointsRequireToken + TestBearerAPITokenScopesDenyReadWriteAndExecRoutes + TestCheckAuth_QueryTokenRejectedWithoutWebSocketUpgrade + TestConfigTransferAnonymousAuthenticatedModesDenyBeforeBodyRead + TestConfigTransferEnvironmentOIDCAndSSOLoadFailureFailClosed + TestConfigTransferNoAuthRejectsForwardedLoopback + TestConfigTransferNoAuthUsesDirectLoopbackPolicy + TestConfigTransferAuthorizedInstanceModesReachHandler + TestConfigTransferSSOViewerDeniedBeforeBodyRead + TestConfigTransferTenantSessionsRequireManagement + TestConfigTransferTokenScopesAndOrganizationBinding + TestDeniedConfigTransferDoesNotMutateOrReload + TestHandleChangePassword_InvalidatesSessionsDocker + TestHandleLogout_Post + TestLimitedAPITokenCannotCreateBroaderToken + TestNewOIDCHTTPClient_BlocksCrossOriginRedirects + TestOIDCServiceAuthCodeURLIncludesPKCE + TestProxyAuthNonAdminCannotEscalateWithToken + TestRequireAuth_ProxyAuthInvalidSecretRejects + TestRevokedAPITokenImmediatelyLosesAccess + TestRouterCSRFBlocksCrossSiteProxyAuthMutation + TestRouterCSRFEnforcedForSessionRequests + TestSecurityStatusMatchesConfigTransferPolicy + TestSecurityTokens_Create_RejectsScopeEscalationForTokenCaller + TestSecurityTokens_DeleteFailsAuthImmediately + TestSecurityTokens_ExpiredTokenRejectedAtHTTPLayer + TestSecurityTokens_ListCreateDelete + TestSecurityTokens_RotateRejectsScopeEscalation + TestSessionStore_CreateAndValidate + TestSessionStore_Load_MigratesLegacyFormat + TestSessionStore_Persistence + TestSessionStore_ValidateSession_Expired + TestSSOOIDCCallbackProviderMismatchStillRejected + TestTenantMiddleware_AuthorizationAllowed + TestTenantMiddleware_AuthorizationDenied + TestTenantMiddleware_DefaultOrgAuthorizationDenied + TestTenantMiddleware_RejectsUnknownOrgBeforeLicense + TestValidateSAMLRedirectTarget +) + +printf -v api_test_alternation '|%s' "${required_api_tests[@]}" +api_test_pattern="^(${api_test_alternation:1})$" +api_test_inventory="$(go test ./internal/api -list "$api_test_pattern")" + +for test_name in "${required_api_tests[@]}"; do + if ! grep -Fxq "$test_name" <<<"$api_test_inventory"; then + printf 'Required API security regression is missing: %s\n' "$test_name" >&2 + exit 1 + fi +done + +printf 'Verified %d required API security regressions\n' "${#required_api_tests[@]}" + +printf '\nRunning session, token, proxy, tenant, and configuration-transfer regressions\n' +go test ./internal/api -run "$api_test_pattern" -count=1 printf '\nChecking public documentation links and mirrors\n' python3 scripts/check_public_docs.py