Default admin password is hard-coded in the repo and provisioned into production #24

Open
opened 2026-07-31 20:38:34 +00:00 by forgejo-admin · 0 comments

celilo/scripts/setup-web.ts provisions the default admin account with a literal password:

const userResult = await capabilities.idp.create_user({
  username: 'lunacycle_admin',
  email: 'lunacycle_admin@example.com',
  password: 'lunacycle-rules',
  groups: ['lunacycle-admins'],
});

This account exists in production, is in lunacycle-admins, and its password is readable by anyone with repo access.

This is live, not theoretical. While investigating #20 I needed a working OIDC login to verify the fix end to end, could not read the smoketest_bot_password module secret, and simply logged in as lunacycle_admin with the value from this file. Production authentik issued a valid access token with groups: ["lunacycle-admins"]. That was convenient for verification and is precisely the problem.

Contrast with the sibling account provisioned twenty lines below: smoketest_bot correctly reads its password from secrets.smoketest_bot_password and throws if unset. The admin account should work the same way.

Suggested fix

  1. Declare a lunacycle_admin_password secret in manifest.yml alongside smoketest_bot_password, and fail the install if it's unset — matching the bot's existing pattern.
  2. Rotate the existing production credential, since the current value is in git history regardless of what the code does going forward.
  3. Decide whether the default admin should be auto-provisioned at all, or whether first-run should require the operator to create it.

Item 2 is the urgent part and is independent of the code change.

Note this also affects any other deployment of this module — the value is the same everywhere it has ever been installed.

`celilo/scripts/setup-web.ts` provisions the default admin account with a literal password: ```ts const userResult = await capabilities.idp.create_user({ username: 'lunacycle_admin', email: 'lunacycle_admin@example.com', password: 'lunacycle-rules', groups: ['lunacycle-admins'], }); ``` This account exists in production, is in `lunacycle-admins`, and its password is readable by anyone with repo access. **This is live, not theoretical.** While investigating #20 I needed a working OIDC login to verify the fix end to end, could not read the `smoketest_bot_password` module secret, and simply logged in as `lunacycle_admin` with the value from this file. Production authentik issued a valid access token with `groups: ["lunacycle-admins"]`. That was convenient for verification and is precisely the problem. Contrast with the sibling account provisioned twenty lines below: `smoketest_bot` correctly reads its password from `secrets.smoketest_bot_password` and **throws** if unset. The admin account should work the same way. **Suggested fix** 1. Declare a `lunacycle_admin_password` secret in `manifest.yml` alongside `smoketest_bot_password`, and fail the install if it's unset — matching the bot's existing pattern. 2. Rotate the existing production credential, since the current value is in git history regardless of what the code does going forward. 3. Decide whether the default admin should be auto-provisioned at all, or whether first-run should require the operator to create it. Item 2 is the urgent part and is independent of the code change. Note this also affects any other deployment of this module — the value is the same everywhere it has ever been installed.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
celilo/lunacycle#24
No description provided.