mirror of
https://github.com/syntrex-lab/gomcp.git
synced 2026-04-28 22:06:22 +02:00
SEC: Fix 3 CRITICAL + 3 MEDIUM red team findings
C1: Remove verification_code_dev from API response (CVSS 9.8)
- Code now logged server-side only when email service not configured
C2: Tenant isolation on /api/auth/users (CVSS 9.1)
- HandleListUsers filters by claims.TenantID
- TenantID added to User struct, DB migration, persistUser, loadFromDB
C3: Include TenantID in JWT tokens (CVSS 8.8)
- Login handler now uses Sign() with full Claims including TenantID
- Enables downstream RBAC tenant filtering
M1: nginx server_tokens off (hide version fingerprint)
M2: syntrex.pro added to server_name
M3: CORS multi-origin support (SOC_CORS_ORIGIN=origin1,origin2)
This commit is contained in:
parent
8d87c453b0
commit
4ce94e9c77
4 changed files with 65 additions and 24 deletions
|
|
@ -30,6 +30,7 @@ type User struct {
|
|||
Email string `json:"email"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Role string `json:"role"` // admin, analyst, viewer
|
||||
TenantID string `json:"tenant_id,omitempty"`
|
||||
Active bool `json:"active"`
|
||||
EmailVerified bool `json:"email_verified"`
|
||||
PasswordHash string `json:"-"` // never serialized
|
||||
|
|
@ -121,12 +122,13 @@ func (s *UserStore) migrate() error {
|
|||
s.db.Exec(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_verified BOOLEAN NOT NULL DEFAULT false`)
|
||||
s.db.Exec(`ALTER TABLE users ADD COLUMN IF NOT EXISTS verify_token TEXT DEFAULT ''`)
|
||||
s.db.Exec(`ALTER TABLE users ADD COLUMN IF NOT EXISTS verify_expiry TIMESTAMPTZ`)
|
||||
s.db.Exec(`ALTER TABLE users ADD COLUMN IF NOT EXISTS tenant_id TEXT DEFAULT ''`)
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadFromDB loads all users from DB into memory cache.
|
||||
func (s *UserStore) loadFromDB() {
|
||||
rows, err := s.db.Query(`SELECT id, email, display_name, role, active, password_hash, created_at, last_login_at FROM users`)
|
||||
rows, err := s.db.Query(`SELECT id, email, display_name, role, active, password_hash, created_at, last_login_at, COALESCE(tenant_id, '') FROM users`)
|
||||
if err != nil {
|
||||
slog.Error("load users from DB", "error", err)
|
||||
return
|
||||
|
|
@ -138,7 +140,7 @@ func (s *UserStore) loadFromDB() {
|
|||
for rows.Next() {
|
||||
var u User
|
||||
var lastLogin sql.NullTime
|
||||
if err := rows.Scan(&u.ID, &u.Email, &u.DisplayName, &u.Role, &u.Active, &u.PasswordHash, &u.CreatedAt, &lastLogin); err != nil {
|
||||
if err := rows.Scan(&u.ID, &u.Email, &u.DisplayName, &u.Role, &u.Active, &u.PasswordHash, &u.CreatedAt, &lastLogin, &u.TenantID); err != nil {
|
||||
slog.Warn("load user row scan", "error", err)
|
||||
continue
|
||||
}
|
||||
|
|
@ -156,8 +158,8 @@ func (s *UserStore) persistUser(u *User) {
|
|||
return
|
||||
}
|
||||
_, err := s.db.Exec(`
|
||||
INSERT INTO users (id, email, display_name, role, active, email_verified, password_hash, verify_token, verify_expiry, created_at, last_login_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
||||
INSERT INTO users (id, email, display_name, role, active, email_verified, password_hash, verify_token, verify_expiry, created_at, last_login_at, tenant_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
email = EXCLUDED.email,
|
||||
display_name = EXCLUDED.display_name,
|
||||
|
|
@ -167,8 +169,9 @@ func (s *UserStore) persistUser(u *User) {
|
|||
password_hash = EXCLUDED.password_hash,
|
||||
verify_token = EXCLUDED.verify_token,
|
||||
verify_expiry = EXCLUDED.verify_expiry,
|
||||
last_login_at = EXCLUDED.last_login_at`,
|
||||
u.ID, u.Email, u.DisplayName, u.Role, u.Active, u.EmailVerified, u.PasswordHash, u.VerifyToken, u.VerifyExpiry, u.CreatedAt, u.LastLoginAt,
|
||||
last_login_at = EXCLUDED.last_login_at,
|
||||
tenant_id = EXCLUDED.tenant_id`,
|
||||
u.ID, u.Email, u.DisplayName, u.Role, u.Active, u.EmailVerified, u.PasswordHash, u.VerifyToken, u.VerifyExpiry, u.CreatedAt, u.LastLoginAt, u.TenantID,
|
||||
)
|
||||
if err != nil {
|
||||
slog.Error("persist user", "email", u.Email, "error", err)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue