mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-03 05:22:49 +08:00
feat(web): keep deployed WebUI out of search-engine indexes
Searching "TsmusicBot" surfaced many deployed instances' WebUI URLs, letting strangers walk into other people's control pages (issue #128). Add defence-in-depth so crawlers stop indexing public deployments: - send `X-Robots-Tag: noindex, nofollow` on every Express response - serve `/robots.txt` with `User-agent: * / Disallow: /` - add `<meta name="robots" content="noindex, nofollow">` to index.html, which also covers the /bot/<id> dedicated-link pages (same SPA shell) These layers only prevent indexing; real protection stays with WebUI auth and the reverse proxy. Document this in the README security section and warn users not to post their WebUI link on public pages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
051171b019
commit
ea0f7c17b5
4 files changed
+110
-3
No files matched your search
+17
-3
@@ -77,12 +77,19 @@ export function createWebServer(options: WebServerOptions): WebServer {
|
||||
app.set("trust proxy", true);
|
||||
}
|
||||
|
||||
// Security headers: prevent the WebUI from being embedded in a third-party
|
||||
// iframe (clickjacking defence). CSP frame-ancestors is the modern equivalent
|
||||
// of X-Frame-Options; both are set for compatibility across browsers.
|
||||
// Security headers:
|
||||
// • X-Frame-Options / CSP frame-ancestors — prevent the WebUI from being
|
||||
// embedded in a third-party iframe (clickjacking defence). CSP
|
||||
// frame-ancestors is the modern equivalent of X-Frame-Options; both are
|
||||
// set for compatibility across browsers.
|
||||
// • X-Robots-Tag — keep deployed instances out of search-engine indexes
|
||||
// (issue #128: searching "TsmusicBot" surfaced strangers' WebUI URLs).
|
||||
// Set on EVERY response so JSON/API responses and the SPA shell are all
|
||||
// covered; complements /robots.txt and the <meta name="robots"> tag.
|
||||
app.use((_req, res, next) => {
|
||||
res.setHeader("X-Frame-Options", "DENY");
|
||||
res.setHeader("Content-Security-Policy", "frame-ancestors 'none'");
|
||||
res.setHeader("X-Robots-Tag", "noindex, nofollow");
|
||||
next();
|
||||
});
|
||||
|
||||
@@ -95,6 +102,13 @@ export function createWebServer(options: WebServerOptions): WebServer {
|
||||
const permissions = createPermissionStore(options.database.db);
|
||||
|
||||
// ─── Public routes (no auth, no CSRF) ───────────────────────────────────
|
||||
// Disallow every crawler (issue #128). Declared before the static SPA
|
||||
// fallback so this wins over index.html for /robots.txt. Belt-and-braces
|
||||
// with the X-Robots-Tag header above and the <meta name="robots"> tag.
|
||||
app.get("/robots.txt", (_req, res) => {
|
||||
res.type("text/plain").send("User-agent: *\nDisallow: /\n");
|
||||
});
|
||||
|
||||
app.get("/api/health", (_req, res) => {
|
||||
res.json({ status: "ok", version: "0.1.0" });
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user