{"record":{"id":"74ed4bf56289423b","repo":"coder/code-server","slug":"hashed-password-can-only-be-set-in-the-config-fi","errorCode":null,"errorMessage":"--hashed-password can only be set in the config file or passed in via $HASHED_PASSWORD","messagePattern":"--hashed-password can only be set in the config file or passed in via \\$HASHED_PASSWORD","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/node/cli.ts","lineNumber":411,"sourceCode":"        value = split[1]\n      } else {\n        const short = arg.replace(/^-/, \"\")\n        const pair = Object.entries(options).find(([, v]) => v.short === short)\n        if (pair) {\n          key = pair[0] as keyof UserProvidedArgs\n        }\n      }\n\n      if (!key || !options[key]) {\n        throw error(`Unknown option ${arg}`)\n      }\n\n      if (key === \"password\" && !opts?.configFile) {\n        throw new Error(\"--password can only be set in the config file or passed in via $PASSWORD\")\n      }\n\n      if (key === \"hashed-password\" && !opts?.configFile) {\n        throw new Error(\"--hashed-password can only be set in the config file or passed in via $HASHED_PASSWORD\")\n      }\n\n      if (key === \"github-auth\" && !opts?.configFile) {\n        throw new Error(\"--github-auth can only be set in the config file or passed in via $GITHUB_TOKEN\")\n      }\n\n      if (key === \"idle-timeout-seconds\" && Number(value) <= 60) {\n        throw new Error(\"--idle-timeout-seconds must be greater than 60 seconds.\")\n      }\n\n      const option = options[key]\n      if (option.type === \"boolean\") {\n        ;(args[key] as boolean) = true\n        continue\n      }\n\n      // Might already have a value if it was the --long=value format.\n      if (typeof value === \"undefined\") {","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/coder/code-server/blob/51f90a376b42e217b38937410fe2855e0c1db87e/src/node/cli.ts#L393-L429","documentation":"Same security guard as --password, applied to `--hashed-password` at cli.ts:411. Hashed passwords (bcrypt/argon2-style) are still secrets and are rejected on the command line for the same process-list visibility reason. Provide the hash via the config file or $HASHED_PASSWORD.","triggerScenarios":"Running `code-server --hashed-password='$argon2id$...'` or `--hashed-password=<bcrypt-hash>` from the command line.","commonSituations":"Operators migrating from plaintext to hashed passwords who pass the hash inline; automation scripts that build the hash and append it as a flag.","solutions":["Set `hashed-password:` in the config file","Export `HASHED_PASSWORD` in the environment before launching code-server","Generate the hash once (`echo -n 'pass' | npx argon2-cli -e`) and store it in a secrets manager that populates the env var"],"exampleFix":"# before\ncode-server --hashed-password='$argon2id$...'\n\n# after\nexport HASHED_PASSWORD='$argon2id$...'\ncode-server","handlingStrategy":"validation","validationCode":"const SECRET_FLAGS = [\"--password\", \"--hashed-password\", \"--github-auth\"]\nconst leaked = process.argv.filter((a) =>\n  SECRET_FLAGS.some((f) => a === f || a.startsWith(f + \"=\"))\n)\nif (leaked.length) {\n  throw new Error(`Refusing to run: ${leaked.join(\", \")} on the CLI. Use $HASHED_PASSWORD / config file.`)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate the hash once and store it in $HASHED_PASSWORD via a secrets broker","Never paste a hash into a shell command — it lands in history and `ps`","Rotate hashes the same way you rotate passwords"],"tags":["security","cli","credentials","secrets","configuration","password-hash"],"backgroundTag":null,"analyzedSha":"51f90a376b42e217b38937410fe2855e0c1db87e","analyzedAt":"2026-08-12T11:27:34.273Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}