Critical Security Considerations When Deploying S-UI: A Production Hardening Guide
S-UI stores user credentials and API tokens in plain text, ships with default admin credentials, and disables secure cookie flags by default, requiring immediate hardening before exposing the panel to the internet.
S-UI is an advanced web panel built on Sing-Box for managing proxy configurations. While the repository provides a feature-rich REST API and web interface, it contains several intentional security shortcuts that make it unsuitable for production deployment without modification. This guide examines the critical security considerations when deploying S-UI, referencing specific source files and providing concrete hardening implementations.
Authentication and Credential Storage Vulnerabilities
The authentication system contains multiple high-risk vulnerabilities centered around plain-text storage and weak defaults.
Plain-Text Password Storage
In database/model/model.go, the User struct stores passwords as raw strings without hashing. Because the application uses SQLite by default, these credentials are written to disk in plain text, making them immediately accessible to anyone with file read access. The password verification logic in service/user.go performs direct string comparison rather than cryptographic validation.
Default Admin Credentials
The initialization logic in database/db.go automatically creates a default admin account with credentials admin/admin if the database is empty. According to the repository README, these credentials are intended for initial setup, but the automatic creation logic means a fresh installation is immediately vulnerable to unauthorized access if discovered before configuration.
Insecure Session Cookies
The session middleware in api/session.go creates cookies with Secure: false regardless of whether HTTPS is configured. This allows browsers to transmit session cookies over unencrypted HTTP connections, enabling session hijacking through man-in-the-middle attacks. The cookies also lack HttpOnly and SameSite attributes, exposing them to XSS and CSRF attacks.
API Token Exposure
API v2 tokens are stored in plain text in the tokens table defined in database/model/model.go. The token handling logic in api/apiV2Handler.go returns these tokens to clients without masking in API responses. Tokens are passed in the Token HTTP header without HMAC verification or expiration enforcement, allowing indefinite reuse if leaked.
TLS Configuration and Transport Security
S-UI supports both HTTP and HTTPS through the server implementation in web/web.go. When certificate files are configured via webCertFile and webKeyFile settings, the application creates a TLS listener and uses an auto-HTTPS listener (defined in network/auto_https_listener.go) to upgrade plain connections.
However, if no certificates are provided, the UI falls back to plain HTTP, exposing credentials and session tokens in clear text. The auto-HTTPS implementation does not enforce HTTP Strict Transport Security (HSTS) or verify SNI mismatches, leaving connections vulnerable to downgrade attacks.
Session Management Risks
Session data is stored in signed cookies using Gin's cookie.NewStore(secret), with the secret generated once per installation in service/setting.go. This secret is persisted in the database and never rotated automatically. If an attacker gains database access, they can forge valid session cookies using the stored secret. Additionally, the default sessionMaxAge is set to 0, meaning sessions never expire by default and remain valid indefinitely.
Database and File System Permissions
S-UI uses an SQLite database located under $SUI_DB_FOLDER (default <binary>/db). The folder is created with permissions 01740 (owner read/write/execute, group read, others none) as defined in config/config.go. Because the database contains all credentials in plain text, any process running as the same user or group can extract sensitive information. The system does not implement database encryption or vault integration for secrets.
API Exposure and Rate Limiting
All API endpoints are exposed under /api (session-based) and /apiv2 (token-based) via api/apiHandler.go. The current implementation lacks rate-limiting or brute-force protection on the login endpoint (/api/login). State-changing POST actions such as /api/save and /api/changePass do not implement CSRF tokens, allowing cross-site request forgery attacks against authenticated users.
External Service Integration Risks
The Warp service in service/warp.go makes outbound HTTP calls using bearer tokens stored in memory. When debug logging is enabled, these tokens may be inadvertently logged to disk or output streams, exposing third-party credentials. Tokens are stored in the database and loaded into memory without encryption at rest.
Production Hardening Implementation
To deploy S-UI safely, implement the following modifications drawn directly from the source architecture:
Hash Passwords with bcrypt
Replace the plain-text logic in service/user.go and database/model/model.go:
import "golang.org/x/crypto/bcrypt"
// When creating or updating a user
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return err
}
user.Password = string(hash)
// When checking credentials (replace direct string comparison)
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
if err != nil {
// invalid password
}
Secure Session Configuration
Modify SetLoginUser in api/session.go to enable secure cookie flags:
options := sessions.Options{
Path: "/",
Secure: true, // only over HTTPS
HttpOnly: true, // not accessible via JavaScript
SameSite: http.SameSiteStrictMode,
MaxAge: 1800, // 30 minutes
}
s := sessions.Default(c)
s.Set(loginUser, userName)
s.Options(options)
return s.Save()
Enforce HSTS Headers
Add middleware early in web/web.go to enforce HTTPS:
engine.Use(func(c *gin.Context) {
c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
c.Next()
})
Implement Secret Rotation
Add a rotation function in service/setting.go to invalidate existing sessions:
func (s *SettingService) RotateSecret() error {
newSecret := common.Random(32)
return s.saveSetting("secret", newSecret)
}
Expose this via an admin-only endpoint and schedule regular rotation to mitigate the risk of forged session cookies.
Database Hardening
Run S-UI under an unprivileged dedicated user. Restrict the database folder permissions to 0700 and the database file to 0600 in config/config.go. Consider encrypting the SQLite database using the SEE extension or migrating sensitive tokens to a dedicated vault rather than storing them in model.go.
Summary
- S-UI stores passwords and tokens in plain text in
database/model/model.go, requiring bcrypt implementation before production use. - Default admin credentials (
admin/admin) are automatically created indatabase/db.goand must be removed or changed immediately. - Session cookies lack security flags in
api/session.go, necessitatingSecure,HttpOnly, andSameSite=Strictattributes. - No rate limiting on authentication endpoints in
api/apiHandler.gocreates brute-force vulnerabilities. - SQLite database permissions in
config/config.gomay expose credentials to other system users without proper hardening. - TLS is optional in
web/web.go, risking credential exposure without enforced HTTPS and HSTS headers.
Frequently Asked Questions
How does S-UI store user passwords?
S-UI stores user passwords as plain text strings in the SQLite database. In database/model/model.go, the User struct contains a Password field that receives raw input without hashing. The application validates logins using direct string comparison in service/user.go rather than cryptographic verification, meaning anyone with database read access can view all user credentials immediately.
What are the default credentials for S-UI?
The default credentials are admin for both username and password. These are automatically created when the database initializes if no users exist, as implemented in database/db.go lines 26-31. You must change these immediately after first login, as leaving the defaults unchanged grants full administrative access to anyone who discovers the panel.
How can I secure the S-UI session cookies?
To secure session cookies, modify api/session.go to set Secure: true, HttpOnly: true, and SameSite: http.SameSiteStrictMode on the session options. The current implementation hardcodes Secure: false regardless of TLS status, allowing cookies to leak over HTTP connections. You should also set a reasonable MaxAge (such as 1800 seconds for 30 minutes) rather than the default 0 (no expiration).
Is S-UI safe to expose to the internet?
No, S-UI is not safe for internet exposure without significant modifications. The combination of plain-text credential storage, default weak credentials, missing CSRF protection, lack of rate limiting, and optional TLS enforcement creates multiple attack vectors. Before exposing S-UI externally, you must implement password hashing, enforce HTTPS with HSTS, add rate limiting, and remove default credentials.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →