Skip to content

Commit f6458f2

Browse files
fix: address Copilot review 2 on PR #7
Four follow-ups from the second pass: 1. Banner no longer prints the env-provided password verbatim. When the credential comes from JSS_SINGLE_USER_PASSWORD, the banner confirms "(hidden — set via JSS_SINGLE_USER_PASSWORD)" instead of echoing the value to stdout. Default rung-1 'me' still prints (the user doesn't know it yet, and it has no secrecy property). Avoids leaking real passwords into terminal scrollback, shell history capture, CI logs, and shared sessions. 2. `--host [::1]` (bracketed IPv6) now parses cleanly. Brackets are stripped at CLI parse time, so options.host stays canonical ('::1'), and formatUrl re-adds brackets only where URLs need them. Previously the bracketed form would round-trip through formatUrl as http://[[::1]]:PORT (invalid). 3. LAN-exposure warning no longer references a `--single-user- password` jspod flag that doesn't exist. It now points users to JSS_SINGLE_USER_PASSWORD=... or binding to 127.0.0.1. 4. README's "Default Configuration" code block previously claimed TOKEN_SECRET was "(auto)" / "auto-generated". The code actually uses a static fallback ('jspod-default-secret-change-in- production'). Documentation now matches reality. A real per-data-dir secret-generator can land in a follow-up PR. Refs #1 #3 #6
1 parent 89d9fe7 commit f6458f2

2 files changed

Lines changed: 23 additions & 8 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ Under the hood, jspod runs JavaScriptSolidServer with these options:
201201
host: '127.0.0.1', // Localhost-only by default (rung-1 credentials)
202202
root: './pod-data', // Local data directory
203203
multiuser: false, // Single pod per server
204-
TOKEN_SECRET: (auto) // JWT secret (auto-generated, change for production)
204+
TOKEN_SECRET: 'jspod-default-secret-change-in-production'
205+
// Static fallback. Override via env for any non-local use.
205206
}
206207
```
207208

index.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ for (let i = 0; i < args.length; i++) {
5656
if (arg === '--port' || arg === '-p') {
5757
options.port = parseInt(args[++i], 10);
5858
} else if (arg === '--host' || arg === '-h') {
59-
options.host = args[++i];
59+
// Strip optional brackets from IPv6 literals so a user-friendly
60+
// `--host [::1]` paste-in stays canonical. formatUrl re-adds the
61+
// brackets where they belong in URLs; the raw host going to JSS
62+
// and to comparisons remains the unbracketed literal.
63+
options.host = args[++i].replace(/^\[|\]$/g, '');
6064
} else if (arg === '--root' || arg === '-r') {
6165
options.root = args[++i];
6266
} else if (arg === '--multiuser') {
@@ -143,25 +147,35 @@ if (options.auth && !options.multiuser) {
143147
: 'Sign In (rung 1 of the auth ladder):';
144148
console.log('\n' + chalk.bold.white(`🔑 ${rungLabel}\n`));
145149
console.log(chalk.cyan(' ├─ ') + chalk.white('Username: ') + chalk.bold.green(RUNG_1_USERNAME));
146-
console.log(chalk.cyan(' ├─ ') + chalk.white('Password: ') + chalk.bold.green(RUNG_1_PASSWORD));
150+
// Only print the literal password when it's the rung-1 default. If
151+
// the user set a real password via env, echoing it to stdout would
152+
// leak into terminal scrollback, shell history capture, CI logs, and
153+
// shared sessions. They already know the value they set; the banner
154+
// just confirms it was picked up.
155+
if (RUNG_1_PASSWORD_FROM_ENV) {
156+
console.log(chalk.cyan(' ├─ ') + chalk.white('Password: ') + chalk.dim('(hidden — set via JSS_SINGLE_USER_PASSWORD)'));
157+
} else {
158+
console.log(chalk.cyan(' ├─ ') + chalk.white('Password: ') + chalk.bold.green(RUNG_1_PASSWORD));
159+
}
147160
console.log(chalk.cyan(' └─ ') + chalk.dim('Climb: change the password or add a passkey from account settings'));
148161

149162
// Loud warning if the rung-1 known credentials are reachable beyond
150163
// the local machine. See issue #6 ("auth ladder"): rung 1 is only
151164
// safe when the host is loopback-only. Any other bind exposes the
152165
// well-known me/me credentials to the LAN (or worse).
153-
// Loopback covers the full 127.0.0.0/8 IPv4 range plus IPv6 ::1
154-
// (and its bracketed form, which a user might paste in by accident).
166+
// Loopback covers the full 127.0.0.0/8 IPv4 range plus IPv6 ::1.
167+
// (Bracketed `[::1]` input is stripped to `::1` at CLI parse time
168+
// — see options.host parsing — so it matches here without a
169+
// bracketed branch.)
155170
const isLoopback =
156171
options.host === 'localhost' ||
157172
/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(options.host) ||
158-
options.host === '::1' ||
159-
options.host === '[::1]';
173+
options.host === '::1';
160174
if (!isLoopback) {
161175
console.log('\n' + chalk.bold.red('⚠ Warning: ') + chalk.yellow(
162176
`--host ${options.host} exposes the well-known me/me credentials beyond localhost.`
163177
));
164-
console.log(chalk.dim(' Set --single-user-password via env (JSS_SINGLE_USER_PASSWORD) or run on 127.0.0.1.'));
178+
console.log(chalk.dim(' Set JSS_SINGLE_USER_PASSWORD=... before running, or bind to 127.0.0.1.'));
165179
}
166180
}
167181

0 commit comments

Comments
 (0)