#414·coai

Default root-password warning checks the wrong password

Author: chenshj73Created Sep 1, 2026Updated Sep 1, 2026

Summary

The first-run root account is created with the default password chatnio123456, and the README also tells operators to log in with root / chatnio123456. However, the frontend warning that asks operators to change the default root password checks for coai123456 instead.

As a result, an operator who logs in with the actual default password may not see the intended warning to rotate it.

Evidence

The backend creates the first root user with chatnio123456:

go
103 func InitRootUser(db *sql.DB) {
104     // create root user if totally empty
105     var count int
106     err := globals.QueryRowDb(db, "SELECT COUNT(*) FROM auth").Scan(&count)
107     if err != nil {
108         globals.Warn(fmt.Sprintf("[service] failed to query user count: %s", err.Error()))
109         return
110     }
111 
112     if count == 0 {
113         globals.Debug("[service] no user found, creating root user (username: root, password: chatnio123456, email: [email protected])")
114         _, err := globals.ExecDb(db, `
115             INSERT INTO auth (username, password, email, is_admin, bind_id, token)
116             VALUES (?, ?, ?, ?, ?, ?)
117         `, "root", utils.Sha2Encrypt("chatnio123456"), "[email protected]", true, 0, "root")

The README tells operators the same default password:

markdown
86 ##  Deployment
87 > [!TIP]
88 > **After successful deployment, the admin account is `root`, with the default password `chatnio123456`**
89 
90 ### ✨ Zeabur (One-Click)
91 [![Deploy on Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/templates/M86XJI)
92 
93 > Zeabur provides a certain free quota, you can use non-paid regions for one-click deployment, and also supports plan subscriptions and elastic billing for flexible expansion.
94 > 1. Click `Deploy` to deploy, and enter the domain name you wish to bind, wait for the deployment to complete.
95 > 2. After deployment is complete, please visit your domain name and log in to the backend management using the username `root` and password `chatnio123456`. Please follow the prompts to change the password in the chatnio backend in a timely manner.

But the frontend default-password warning checks a different value:

typescript
108       toast.success(t("login-success"), {
109         description: t("login-success-prompt"),
110       });
111 
112       if (
113         form.username.trim() === "root" &&
114         form.password.trim() === "coai123456"
115       ) {
116         toast.warning(t("admin.default-password"), {
117           description: t("admin.default-password-prompt"),
118           duration: 15000,
119         });
120       }

Why this matters

CoAI is an LLM gateway/admin system. The root admin account controls sensitive gateway state such as channels, upstream credentials, model routing, pricing, quota, and user/API-key management. A missed default-password warning increases the chance that a newly deployed instance keeps a public, documented administrator password longer than intended.

Suggested fix

At minimum, update the frontend check to match the actual default password:

typescript
form.password.trim() === "chatnio123456"

Longer term, a safer pattern would be to avoid hardcoded default credentials entirely, for example:

  • generate a random first-run root password and print it once to the operator;
  • require setting the initial root password through an environment variable;
  • force a password change after the first login when the account was bootstrap-created.