more security improvements
This commit is contained in:
@@ -177,6 +177,21 @@ async function deliverToUserWebhook(
|
||||
return;
|
||||
}
|
||||
|
||||
const hostname = parsed.hostname.toLowerCase();
|
||||
const BLOCKED_HOSTS = ["localhost", "metadata.google.internal", "169.254.169.254"];
|
||||
if (
|
||||
BLOCKED_HOSTS.includes(hostname) ||
|
||||
hostname.endsWith(".internal") ||
|
||||
hostname.startsWith("127.") ||
|
||||
hostname === "[::1]" ||
|
||||
/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(hostname) ||
|
||||
hostname.startsWith("169.254.") ||
|
||||
hostname.startsWith("0.")
|
||||
) {
|
||||
logger.warn(`[notify] blocked webhook to private/internal address: ${hostname}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const isDiscord = /discord(app)?\.com$/i.test(parsed.hostname);
|
||||
if (isDiscord) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import path from "path";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { authenticateRequest } from "../../auth";
|
||||
import { requirePermission } from "../../rbac";
|
||||
import { canUserAccessClient } from "../../users";
|
||||
import * as clientManager from "../../clientManager";
|
||||
import { metrics } from "../../metrics";
|
||||
import { encodeMessage } from "../../protocol";
|
||||
@@ -88,6 +89,9 @@ export async function handlePluginRoutes(
|
||||
}
|
||||
|
||||
const clientId = clientPluginsMatch[1];
|
||||
if (!canUserAccessClient(user.userId, user.role, clientId)) {
|
||||
return new Response("Forbidden: You do not have access to this client", { status: 403 });
|
||||
}
|
||||
const loaded = deps.pluginLoadedByClient.get(clientId) || new Set<string>();
|
||||
const manifests = await deps.listPluginManifests();
|
||||
const plugins = manifests.map((manifest) => ({
|
||||
@@ -337,8 +341,8 @@ export async function handlePluginRoutes(
|
||||
if (req.method === "POST" && pluginExecMatch) {
|
||||
const user = await authenticateRequest(req);
|
||||
if (!user) return new Response("Unauthorized", { status: 401 });
|
||||
if (user.role !== "admin" && user.role !== "operator") {
|
||||
return new Response("Forbidden: Admin or operator access required", { status: 403 });
|
||||
if (user.role !== "admin") {
|
||||
return new Response("Forbidden: Admin access required", { status: 403 });
|
||||
}
|
||||
let pluginId = "";
|
||||
try { pluginId = deps.sanitizePluginId(pluginExecMatch[1]); } catch { return new Response("Invalid plugin id", { status: 400 }); }
|
||||
@@ -458,6 +462,9 @@ export async function handlePluginRoutes(
|
||||
return new Response("Forbidden", { status: 403 });
|
||||
}
|
||||
const targetId = pluginLoadMatch[1];
|
||||
if (!canUserAccessClient(user.userId, user.role, targetId)) {
|
||||
return new Response("Forbidden: You do not have access to this client", { status: 403 });
|
||||
}
|
||||
const pluginId = pluginLoadMatch[2];
|
||||
const target = clientManager.getClient(targetId);
|
||||
if (!target) return new Response("Not found", { status: 404 });
|
||||
@@ -489,6 +496,9 @@ export async function handlePluginRoutes(
|
||||
return new Response("Forbidden", { status: 403 });
|
||||
}
|
||||
const targetId = pluginEventsPollMatch[1];
|
||||
if (!canUserAccessClient(user.userId, user.role, targetId)) {
|
||||
return new Response("Forbidden: You do not have access to this client", { status: 403 });
|
||||
}
|
||||
const pluginId = pluginEventsPollMatch[2];
|
||||
const events = deps.drainPluginUIEvents(targetId, pluginId);
|
||||
return Response.json({ events });
|
||||
@@ -506,6 +516,9 @@ export async function handlePluginRoutes(
|
||||
}
|
||||
|
||||
const targetId = pluginEventMatch[1];
|
||||
if (!canUserAccessClient(user.userId, user.role, targetId)) {
|
||||
return new Response("Forbidden: You do not have access to this client", { status: 403 });
|
||||
}
|
||||
const pluginId = pluginEventMatch[2];
|
||||
const target = clientManager.getClient(targetId);
|
||||
if (!target) return new Response("Not found", { status: 404 });
|
||||
@@ -565,6 +578,9 @@ export async function handlePluginRoutes(
|
||||
}
|
||||
|
||||
const targetId = pluginUnloadMatch[1];
|
||||
if (!canUserAccessClient(user.userId, user.role, targetId)) {
|
||||
return new Response("Forbidden: You do not have access to this client", { status: 403 });
|
||||
}
|
||||
const pluginId = pluginUnloadMatch[2];
|
||||
const target = clientManager.getClient(targetId);
|
||||
if (!target) return new Response("Not found", { status: 404 });
|
||||
|
||||
Reference in New Issue
Block a user