edgeaegis 2026.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +10 -0
- package/README.md +215 -0
- package/config.yml +29 -0
- package/origin/cloudflare/app/config.yml +2 -0
- package/origin/cloudflare/app/index.js +4 -0
- package/origin/edgeone/app/config.yml +2 -0
- package/origin/edgeone/app/index.js +4 -0
- package/origin/esa/app/config.yml +2 -0
- package/origin/esa/app/index.js +4 -0
- package/origin/netlify/app/config.yml +2 -0
- package/origin/netlify/app/index.js +4 -0
- package/origin/vercel/app/config.yml +2 -0
- package/origin/vercel/app/index.js +4 -0
- package/package.json +123 -0
- package/respond/403.html +2 -0
- package/respond/403.json +1 -0
- package/rules/allowlist.yml +2 -0
- package/rules/emergency.conf +4 -0
- package/rules/local.conf +2 -0
- package/rules/seclang-bundle.json +360 -0
- package/rules/seclang-upstreams.json +14 -0
- package/rules/setup.conf +15 -0
- package/secret/credentials.example.yml +7 -0
- package/secret/relay-server.example.yml +10 -0
- package/tools/.build/scr/adapters/cloudflare/runtime.d.ts +18 -0
- package/tools/.build/scr/adapters/cloudflare/runtime.js +16 -0
- package/tools/.build/scr/adapters/cloudflare/runtime.js.map +1 -0
- package/tools/.build/scr/adapters/cloudflare/worker.js +25 -0
- package/tools/.build/scr/adapters/edgeone/worker.js +7 -0
- package/tools/.build/scr/adapters/esa/worker.js +5 -0
- package/tools/.build/scr/adapters/forward.d.ts +4 -0
- package/tools/.build/scr/adapters/forward.js +25 -0
- package/tools/.build/scr/adapters/forward.js.map +1 -0
- package/tools/.build/scr/adapters/handler.js +39 -0
- package/tools/.build/scr/adapters/ingress.d.ts +10 -0
- package/tools/.build/scr/adapters/ingress.js +62 -0
- package/tools/.build/scr/adapters/ingress.js.map +1 -0
- package/tools/.build/scr/adapters/netlify/worker.js +7 -0
- package/tools/.build/scr/adapters/runtime.d.ts +33 -0
- package/tools/.build/scr/adapters/runtime.js +50 -0
- package/tools/.build/scr/adapters/runtime.js.map +1 -0
- package/tools/.build/scr/adapters/vercel/worker.js +7 -0
- package/tools/.build/scr/cli/config.d.ts +2 -0
- package/tools/.build/scr/cli/config.js +23 -0
- package/tools/.build/scr/cli/config.js.map +1 -0
- package/tools/.build/scr/cli/deployment.d.ts +15 -0
- package/tools/.build/scr/cli/deployment.js +108 -0
- package/tools/.build/scr/cli/deployment.js.map +1 -0
- package/tools/.build/scr/cli/init.d.ts +2 -0
- package/tools/.build/scr/cli/init.js +62 -0
- package/tools/.build/scr/cli/init.js.map +1 -0
- package/tools/.build/scr/cli/main.d.ts +2 -0
- package/tools/.build/scr/cli/main.js +99 -0
- package/tools/.build/scr/cli/main.js.map +1 -0
- package/tools/.build/scr/cli/relay-serve.d.ts +1 -0
- package/tools/.build/scr/cli/relay-serve.js +48 -0
- package/tools/.build/scr/cli/relay-serve.js.map +1 -0
- package/tools/.build/scr/cli/responses.d.ts +2 -0
- package/tools/.build/scr/cli/responses.js +31 -0
- package/tools/.build/scr/cli/responses.js.map +1 -0
- package/tools/.build/scr/cli/serve.d.ts +1 -0
- package/tools/.build/scr/cli/serve.js +132 -0
- package/tools/.build/scr/cli/serve.js.map +1 -0
- package/tools/.build/scr/config.d.ts +39 -0
- package/tools/.build/scr/config.js +89 -0
- package/tools/.build/scr/config.js.map +1 -0
- package/tools/.build/scr/core/types.d.ts +27 -0
- package/tools/.build/scr/core/types.js +34 -0
- package/tools/.build/scr/core/types.js.map +1 -0
- package/tools/.build/scr/core/version.d.ts +1 -0
- package/tools/.build/scr/core/version.js +3 -0
- package/tools/.build/scr/core/version.js.map +1 -0
- package/tools/.build/scr/http-boundary/index.d.ts +19 -0
- package/tools/.build/scr/http-boundary/index.js +173 -0
- package/tools/.build/scr/http-boundary/index.js.map +1 -0
- package/tools/.build/scr/http-boundary/json.d.ts +2 -0
- package/tools/.build/scr/http-boundary/json.js +90 -0
- package/tools/.build/scr/http-boundary/json.js.map +1 -0
- package/tools/.build/scr/origin/relay.d.ts +20 -0
- package/tools/.build/scr/origin/relay.js +221 -0
- package/tools/.build/scr/origin/relay.js.map +1 -0
- package/tools/.build/scr/origin/replay-node.d.ts +8 -0
- package/tools/.build/scr/origin/replay-node.js +36 -0
- package/tools/.build/scr/origin/replay-node.js.map +1 -0
- package/tools/.build/scr/origin/types.d.ts +18 -0
- package/tools/.build/scr/origin/types.js +2 -0
- package/tools/.build/scr/origin/types.js.map +1 -0
- package/tools/.build/scr/runtime/allowlist.d.ts +21 -0
- package/tools/.build/scr/runtime/allowlist.js +84 -0
- package/tools/.build/scr/runtime/allowlist.js.map +1 -0
- package/tools/.build/scr/runtime/browser-cache.d.ts +7 -0
- package/tools/.build/scr/runtime/browser-cache.js +50 -0
- package/tools/.build/scr/runtime/browser-cache.js.map +1 -0
- package/tools/.build/scr/runtime/error-pages.d.ts +10 -0
- package/tools/.build/scr/runtime/error-pages.js +72 -0
- package/tools/.build/scr/runtime/error-pages.js.map +1 -0
- package/tools/.build/scr/runtime/index.d.ts +54 -0
- package/tools/.build/scr/runtime/index.js +355 -0
- package/tools/.build/scr/runtime/index.js.map +1 -0
- package/tools/.build/scr/runtime/node.d.ts +3 -0
- package/tools/.build/scr/runtime/node.js +97 -0
- package/tools/.build/scr/runtime/node.js.map +1 -0
- package/tools/.build/scr/runtime/proxy.d.ts +12 -0
- package/tools/.build/scr/runtime/proxy.js +177 -0
- package/tools/.build/scr/runtime/proxy.js.map +1 -0
- package/tools/.build/scr/runtime/stream.d.ts +8 -0
- package/tools/.build/scr/runtime/stream.js +72 -0
- package/tools/.build/scr/runtime/stream.js.map +1 -0
- package/tools/.build/scr/seclang/body.d.ts +13 -0
- package/tools/.build/scr/seclang/body.js +109 -0
- package/tools/.build/scr/seclang/body.js.map +1 -0
- package/tools/.build/scr/seclang/bytes.d.ts +5 -0
- package/tools/.build/scr/seclang/bytes.js +38 -0
- package/tools/.build/scr/seclang/bytes.js.map +1 -0
- package/tools/.build/scr/seclang/index.d.ts +166 -0
- package/tools/.build/scr/seclang/index.js +1519 -0
- package/tools/.build/scr/seclang/index.js.map +1 -0
- package/tools/.build/scr/seclang/json.d.ts +2 -0
- package/tools/.build/scr/seclang/json.js +87 -0
- package/tools/.build/scr/seclang/json.js.map +1 -0
- package/tools/.build/scr/seclang/libinjection.d.ts +9 -0
- package/tools/.build/scr/seclang/libinjection.js +59 -0
- package/tools/.build/scr/seclang/libinjection.js.map +1 -0
- package/tools/.build/scr/seclang/node.d.ts +22 -0
- package/tools/.build/scr/seclang/node.js +113 -0
- package/tools/.build/scr/seclang/node.js.map +1 -0
- package/tools/.build/scr/seclang/pcre2.d.ts +23 -0
- package/tools/.build/scr/seclang/pcre2.js +153 -0
- package/tools/.build/scr/seclang/pcre2.js.map +1 -0
- package/tools/.build/scr/seclang/sources.d.ts +6 -0
- package/tools/.build/scr/seclang/sources.js +59 -0
- package/tools/.build/scr/seclang/sources.js.map +1 -0
- package/tools/.build/scr/seclang/state.d.ts +17 -0
- package/tools/.build/scr/seclang/state.js +53 -0
- package/tools/.build/scr/seclang/state.js.map +1 -0
- package/tools/.build/scr/seclang/syntax.d.ts +9 -0
- package/tools/.build/scr/seclang/syntax.js +74 -0
- package/tools/.build/scr/seclang/syntax.js.map +1 -0
- package/tools/.build/scr/seclang/transforms.d.ts +3 -0
- package/tools/.build/scr/seclang/transforms.js +157 -0
- package/tools/.build/scr/seclang/transforms.js.map +1 -0
- package/tools/.build/scr/seclang/unicode.d.ts +2 -0
- package/tools/.build/scr/seclang/unicode.js +19 -0
- package/tools/.build/scr/seclang/unicode.js.map +1 -0
- package/tools/.build/scr/seclang/vendor/LIBINJECTION-LICENSE +33 -0
- package/tools/.build/scr/seclang/vendor/PCRE2-NOTICE +47 -0
- package/tools/.build/scr/seclang/vendor/PCRE2-WRAPPER-LICENSE +21 -0
- package/tools/.build/scr/seclang/vendor/UNICODE-DATA-NOTICE +6 -0
- package/tools/.build/scr/seclang/vendor/libinjection.json +7 -0
- package/tools/.build/scr/seclang/vendor/libinjection.wasm +0 -0
- package/tools/.build/scr/seclang/vendor/pcre2.json +7 -0
- package/tools/.build/scr/seclang/vendor/pcre2.wasm +0 -0
- package/tools/.build/scr/seclang/vendor/unicode.json +378 -0
- package/tools/build-platform.mjs +199 -0
- package/tools/platform-command.mjs +59 -0
- package/tools/sync-native-seclang.mjs +155 -0
- package/tools/verify-full-crs.mjs +118 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type PlatformName = "cloudflare" | "vercel" | "netlify" | "esa" | "edgeone";
|
|
2
|
+
export type OriginSettings = {
|
|
3
|
+
mode: "function";
|
|
4
|
+
platform: PlatformName;
|
|
5
|
+
} | {
|
|
6
|
+
mode: "proxy";
|
|
7
|
+
platform: PlatformName;
|
|
8
|
+
url: string;
|
|
9
|
+
} | {
|
|
10
|
+
mode: "relay";
|
|
11
|
+
platform: PlatformName;
|
|
12
|
+
endpoint: string;
|
|
13
|
+
publicKeyFile: string;
|
|
14
|
+
authenticationKeyFile: string;
|
|
15
|
+
};
|
|
16
|
+
export interface BusinessFunction {
|
|
17
|
+
fetch(request: Request): Promise<Response> | Response;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../scr/origin/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TrustedContext } from "../core/types.js";
|
|
2
|
+
export interface AllowlistEntry {
|
|
3
|
+
/** Operator-defined identifier for auditing. */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Bypass any rule, or only the listed rule IDs. "*" means every rule. */
|
|
6
|
+
ruleIds?: string[];
|
|
7
|
+
/** Explicitly exempt native WAF rules. */
|
|
8
|
+
skip: "rules"[];
|
|
9
|
+
/** All filters below are optional. Omitting them matches all requests. */
|
|
10
|
+
path?: string;
|
|
11
|
+
pathPrefix?: string;
|
|
12
|
+
methods?: string[];
|
|
13
|
+
identity?: string;
|
|
14
|
+
verifiedClientIp?: string;
|
|
15
|
+
cidrs?: string[];
|
|
16
|
+
/** Optional ISO-8601 expiration: no forced lifetime. */
|
|
17
|
+
expiresAt?: string;
|
|
18
|
+
reason?: string;
|
|
19
|
+
}
|
|
20
|
+
/** All bypass scope and expiry are operator-managed. No automatic whitelist entries. */
|
|
21
|
+
export declare function createAllowlist(entries?: AllowlistEntry[]): (path: string, method: string, context: TrustedContext, ruleId: string | null, now: number) => boolean;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import ipaddr from "ipaddr.js";
|
|
2
|
+
/** All bypass scope and expiry are operator-managed. No automatic whitelist entries. */
|
|
3
|
+
export function createAllowlist(entries = []) {
|
|
4
|
+
if (!Array.isArray(entries))
|
|
5
|
+
throw new Error("Allowlist must be an array");
|
|
6
|
+
const prepared = entries.map((entry) => {
|
|
7
|
+
if (!entry || typeof entry.id !== "string" || !entry.id.trim())
|
|
8
|
+
throw new Error("Allowlist entry requires an id");
|
|
9
|
+
if (!Array.isArray(entry.skip) ||
|
|
10
|
+
!entry.skip.length ||
|
|
11
|
+
entry.skip.some((value) => value !== "rules"))
|
|
12
|
+
throw new Error("Allowlist skip must select rules");
|
|
13
|
+
if (entry.ruleIds !== undefined &&
|
|
14
|
+
(!Array.isArray(entry.ruleIds) || entry.ruleIds.some((x) => typeof x !== "string" || !x)))
|
|
15
|
+
throw new Error("Allowlist ruleIds must be an array of rule names or *");
|
|
16
|
+
if (entry.methods !== undefined &&
|
|
17
|
+
(!Array.isArray(entry.methods) ||
|
|
18
|
+
entry.methods.some((x) => typeof x !== "string" || !/^[A-Z]+$/.test(x))))
|
|
19
|
+
throw new Error("Allowlist methods must be uppercase HTTP methods");
|
|
20
|
+
if (entry.path !== undefined && (typeof entry.path !== "string" || !entry.path.startsWith("/")))
|
|
21
|
+
throw new Error("Allowlist path must be an absolute request path");
|
|
22
|
+
if (entry.pathPrefix !== undefined &&
|
|
23
|
+
(typeof entry.pathPrefix !== "string" || !entry.pathPrefix.startsWith("/")))
|
|
24
|
+
throw new Error("Allowlist pathPrefix must be an absolute request path prefix");
|
|
25
|
+
if (entry.identity !== undefined && (typeof entry.identity !== "string" || !entry.identity))
|
|
26
|
+
throw new Error("Allowlist identity must be a nonempty string");
|
|
27
|
+
if (entry.verifiedClientIp !== undefined && !ipaddr.isValid(entry.verifiedClientIp))
|
|
28
|
+
throw new Error("Allowlist exact IP is invalid");
|
|
29
|
+
if (entry.cidrs !== undefined &&
|
|
30
|
+
(!Array.isArray(entry.cidrs) || entry.cidrs.some((x) => typeof x !== "string")))
|
|
31
|
+
throw new Error("Allowlist CIDRs must be strings");
|
|
32
|
+
const cidrs = (entry.cidrs ?? []).map((value) => {
|
|
33
|
+
try {
|
|
34
|
+
return ipaddr.parseCIDR(value);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw new Error("Invalid allowlist CIDR");
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
const expiry = entry.expiresAt === undefined ? Number.POSITIVE_INFINITY : Date.parse(entry.expiresAt);
|
|
41
|
+
if (Number.isNaN(expiry))
|
|
42
|
+
throw new Error("Invalid allowlist expiration");
|
|
43
|
+
if (entry.reason !== undefined && typeof entry.reason !== "string")
|
|
44
|
+
throw new Error("Invalid allowlist reason");
|
|
45
|
+
return { entry, cidrs, expiry };
|
|
46
|
+
});
|
|
47
|
+
return (path, method, context, ruleId, now) => prepared.some(({ entry, cidrs, expiry }) => {
|
|
48
|
+
if (now >= expiry)
|
|
49
|
+
return false;
|
|
50
|
+
if (entry.ruleIds &&
|
|
51
|
+
!entry.ruleIds.includes("*") &&
|
|
52
|
+
(ruleId === null || !entry.ruleIds.includes(ruleId)))
|
|
53
|
+
return false;
|
|
54
|
+
if (entry.path !== undefined && entry.path !== path)
|
|
55
|
+
return false;
|
|
56
|
+
if (entry.pathPrefix !== undefined && !path.startsWith(entry.pathPrefix))
|
|
57
|
+
return false;
|
|
58
|
+
if (entry.methods !== undefined && !entry.methods.includes(method))
|
|
59
|
+
return false;
|
|
60
|
+
if (entry.identity !== undefined && entry.identity !== context.identity)
|
|
61
|
+
return false;
|
|
62
|
+
if (entry.verifiedClientIp !== undefined &&
|
|
63
|
+
entry.verifiedClientIp !== context.verifiedClientIp)
|
|
64
|
+
return false;
|
|
65
|
+
if (entry.cidrs !== undefined) {
|
|
66
|
+
if (!context.verifiedClientIp)
|
|
67
|
+
return false;
|
|
68
|
+
let actual;
|
|
69
|
+
try {
|
|
70
|
+
actual = ipaddr.process(context.verifiedClientIp);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
if (!cidrs.some(([address, prefix]) => {
|
|
76
|
+
const candidate = ipaddr.process(address.toString());
|
|
77
|
+
return actual.kind() === candidate.kind() && actual.match(candidate, prefix);
|
|
78
|
+
}))
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=allowlist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../../../scr/runtime/allowlist.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface BrowserCachePolicy {
|
|
2
|
+
/** Maximum freshness lifetime. The origin must also explicitly permit public caching. */
|
|
3
|
+
maxAgeSeconds: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function validateBrowserCache(policy: BrowserCachePolicy | undefined): void;
|
|
6
|
+
/** Client caching reduces future network requests; no server-side rule decision is reused. */
|
|
7
|
+
export declare function applyBrowserCache(request: Request, response: Response, headers: Headers, policy?: BrowserCachePolicy): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { requireInteger } from "../core/types.js";
|
|
2
|
+
export function validateBrowserCache(policy) {
|
|
3
|
+
if (policy === undefined)
|
|
4
|
+
return;
|
|
5
|
+
if (!policy ||
|
|
6
|
+
typeof policy !== "object" ||
|
|
7
|
+
Object.keys(policy).some((k) => k !== "maxAgeSeconds"))
|
|
8
|
+
throw new Error("Invalid browser cache policy");
|
|
9
|
+
requireInteger(policy.maxAgeSeconds, 1, 86400, "browser cache lifetime");
|
|
10
|
+
}
|
|
11
|
+
/** Client caching reduces future network requests; no server-side rule decision is reused. */
|
|
12
|
+
export function applyBrowserCache(request, response, headers, policy) {
|
|
13
|
+
headers.set("cache-control", "no-store");
|
|
14
|
+
if (!policy ||
|
|
15
|
+
!["GET", "HEAD"].includes(request.method) ||
|
|
16
|
+
response.status !== 200 ||
|
|
17
|
+
request.headers.has("authorization") ||
|
|
18
|
+
request.headers.has("proxy-authorization") ||
|
|
19
|
+
request.headers.has("cookie") ||
|
|
20
|
+
request.headers.has("upgrade") ||
|
|
21
|
+
response.headers.has("set-cookie") ||
|
|
22
|
+
request.headers.get("pragma")?.toLowerCase().includes("no-cache") ||
|
|
23
|
+
/(?:^|,)\s*(?:(?:no-cache|no-store)(?:\s*=|\s*(?:,|$))|max-age\s*=\s*"?0"?(?:\s|,|$))/i.test(request.headers.get("cache-control") ?? ""))
|
|
24
|
+
return;
|
|
25
|
+
const directives = (response.headers.get("cache-control") ?? "")
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.split(",")
|
|
28
|
+
.map((part) => part.trim());
|
|
29
|
+
if (!directives.includes("public") ||
|
|
30
|
+
directives.some((part) => /^(?:private|no-store|no-cache)(?:\s*=|$)/.test(part)))
|
|
31
|
+
return;
|
|
32
|
+
const ages = directives.filter((part) => /^max-age\s*=/.test(part));
|
|
33
|
+
if (ages.length !== 1 || !/^max-age\s*=\s*\d+$/.test(ages[0]))
|
|
34
|
+
return;
|
|
35
|
+
const originAge = Number(ages[0].split("=")[1]);
|
|
36
|
+
if (!Number.isSafeInteger(originAge) || originAge < 1)
|
|
37
|
+
return;
|
|
38
|
+
const vary = (response.headers.get("vary") ?? "").split(",").map((part) => part.trim());
|
|
39
|
+
if (vary.includes("*"))
|
|
40
|
+
return;
|
|
41
|
+
// Prevent an anonymous browser entry being reused after a login changes credentials.
|
|
42
|
+
for (const name of ["Cookie", "Authorization"])
|
|
43
|
+
if (!vary.some((part) => part.toLowerCase() === name.toLowerCase()))
|
|
44
|
+
vary.push(name);
|
|
45
|
+
headers.set("vary", vary.filter(Boolean).join(", "));
|
|
46
|
+
// Private prohibits a shared cache from answering before the SecLang entry point.
|
|
47
|
+
// Preserve Date/Age, validators and Vary; never extend the origin freshness lifetime.
|
|
48
|
+
headers.set("cache-control", `private, max-age=${Math.min(policy.maxAgeSeconds, originAge)}, must-revalidate`);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=browser-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-cache.js","sourceRoot":"","sources":["../../../../scr/runtime/browser-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Trusted, build-generated HTML only. Never interpolate request data into these pages. */
|
|
2
|
+
export interface ErrorPage {
|
|
3
|
+
html: string;
|
|
4
|
+
contentSecurityPolicy: string;
|
|
5
|
+
json?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export type ErrorPages = Partial<Record<number, ErrorPage>>;
|
|
8
|
+
export declare function wantsHtml(request: Request): boolean;
|
|
9
|
+
export declare function createErrorPageResponse(request: Request, status: number, input: ErrorPage): Response;
|
|
10
|
+
export declare function createErrorPages(input: ErrorPages): (request: Request, status: number) => Response | undefined;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export function wantsHtml(request) {
|
|
2
|
+
const accept = request.headers.get("accept") ?? "";
|
|
3
|
+
if (accept.length > 8192)
|
|
4
|
+
return false;
|
|
5
|
+
let html = 0;
|
|
6
|
+
let json = 0;
|
|
7
|
+
for (const item of accept.split(",").slice(0, 64)) {
|
|
8
|
+
const [type, ...parameters] = item.trim().toLowerCase().split(";");
|
|
9
|
+
const parameter = parameters.find((p) => p.trim().startsWith("q="));
|
|
10
|
+
const quality = parameter ? Number(parameter.trim().slice(2)) : 1;
|
|
11
|
+
if (!Number.isFinite(quality) || quality < 0 || quality > 1)
|
|
12
|
+
continue;
|
|
13
|
+
if (type === "text/html" || type === "application/xhtml+xml")
|
|
14
|
+
html = Math.max(html, quality);
|
|
15
|
+
if (type === "application/json" || type === "application/*" || type === "*/*")
|
|
16
|
+
json = Math.max(json, quality);
|
|
17
|
+
}
|
|
18
|
+
return html > 0 && html >= json;
|
|
19
|
+
}
|
|
20
|
+
function validate(page) {
|
|
21
|
+
if (typeof page.html !== "string" ||
|
|
22
|
+
new TextEncoder().encode(page.html).length > 262144 ||
|
|
23
|
+
!/<html\b/i.test(page.html))
|
|
24
|
+
throw new Error("Error pages require trusted complete HTML within 256 KiB");
|
|
25
|
+
if (typeof page.contentSecurityPolicy !== "string" ||
|
|
26
|
+
!page.contentSecurityPolicy.trim() ||
|
|
27
|
+
page.contentSecurityPolicy.length > 8192 ||
|
|
28
|
+
/[\r\n\0]/.test(page.contentSecurityPolicy))
|
|
29
|
+
throw new Error("Error pages require a bounded, explicit CSP");
|
|
30
|
+
return { ...page };
|
|
31
|
+
}
|
|
32
|
+
export function createErrorPageResponse(request, status, input) {
|
|
33
|
+
if (!Number.isInteger(status) || status < 400 || status > 599)
|
|
34
|
+
throw new Error("Unsupported error page status");
|
|
35
|
+
const page = validate(input);
|
|
36
|
+
return new Response(request.method === "HEAD" ? null : page.html, {
|
|
37
|
+
status,
|
|
38
|
+
headers: {
|
|
39
|
+
"content-type": "text/html; charset=utf-8",
|
|
40
|
+
"cache-control": "no-store",
|
|
41
|
+
"content-security-policy": page.contentSecurityPolicy,
|
|
42
|
+
"x-content-type-options": "nosniff",
|
|
43
|
+
"x-robots-tag": "noindex, nofollow",
|
|
44
|
+
"referrer-policy": "no-referrer",
|
|
45
|
+
vary: "Accept",
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export function createErrorPages(input) {
|
|
50
|
+
if (Object.keys(input).some((key) => !/^\d{3}$/.test(key) || Number(key) < 400 || Number(key) > 599))
|
|
51
|
+
throw new Error("Unsupported error page status");
|
|
52
|
+
const pages = {};
|
|
53
|
+
for (const status of Object.keys(input).map(Number))
|
|
54
|
+
if (input[status])
|
|
55
|
+
pages[status] = validate(input[status]);
|
|
56
|
+
return (request, status) => {
|
|
57
|
+
const page = pages[status];
|
|
58
|
+
if (page && wantsHtml(request))
|
|
59
|
+
return createErrorPageResponse(request, status, page);
|
|
60
|
+
if (page && page.json !== undefined)
|
|
61
|
+
return new Response(request.method === "HEAD" ? null : JSON.stringify(page.json), {
|
|
62
|
+
status,
|
|
63
|
+
headers: {
|
|
64
|
+
"content-type": "application/json; charset=utf-8",
|
|
65
|
+
"cache-control": "no-store",
|
|
66
|
+
"x-content-type-options": "nosniff",
|
|
67
|
+
vary: "Accept",
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=error-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-pages.js","sourceRoot":"","sources":["../../../../scr/runtime/error-pages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type SecurityEvent, type TrustedContext } from "../core/types.js";
|
|
2
|
+
import { type BoundaryLimits } from "../http-boundary/index.js";
|
|
3
|
+
import { type CompileSecLangOptions } from "../seclang/index.js";
|
|
4
|
+
import { type AllowlistEntry } from "./allowlist.js";
|
|
5
|
+
import { type BrowserCachePolicy } from "./browser-cache.js";
|
|
6
|
+
import { type ErrorPages } from "./error-pages.js";
|
|
7
|
+
import { type ProxyOptions } from "./proxy.js";
|
|
8
|
+
export type { SecurityEvent, TrustedContext } from "../core/types.js";
|
|
9
|
+
export type { AllowlistEntry } from "./allowlist.js";
|
|
10
|
+
export type { BrowserCachePolicy } from "./browser-cache.js";
|
|
11
|
+
export type { ProxyOptions } from "./proxy.js";
|
|
12
|
+
export interface Route {
|
|
13
|
+
path: string;
|
|
14
|
+
business: string;
|
|
15
|
+
methods: string[];
|
|
16
|
+
authenticated: boolean;
|
|
17
|
+
body?: "json" | "text" | "none";
|
|
18
|
+
/** Inspect the HTTP handshake; upgraded frames remain opaque to SecLang. */
|
|
19
|
+
websocket?: boolean;
|
|
20
|
+
/** Opt-in client freshness for public origin responses, after full SecLang inspection. */
|
|
21
|
+
browserCache?: BrowserCachePolicy;
|
|
22
|
+
}
|
|
23
|
+
export interface ShieldOptions {
|
|
24
|
+
tenant: string;
|
|
25
|
+
service: string;
|
|
26
|
+
publicHosts: string[];
|
|
27
|
+
routes: Route[];
|
|
28
|
+
/** Native SecLang rules, compiled and evaluated by EdgeAegis itself (no conversion). */
|
|
29
|
+
secLang: string;
|
|
30
|
+
secLangOptions?: Omit<CompileSecLangOptions, "strict">;
|
|
31
|
+
/** Fully operator-defined rule exemptions, including optional global bypass. */
|
|
32
|
+
allowlist?: AllowlistEntry[];
|
|
33
|
+
origins: Record<string, ProxyOptions>;
|
|
34
|
+
limits?: Partial<BoundaryLimits>;
|
|
35
|
+
maxConcurrentRequests?: number;
|
|
36
|
+
event?: (event: SecurityEvent) => void;
|
|
37
|
+
/** Optional trusted static pages; JSON API responses remain the default. */
|
|
38
|
+
errorPages?: ErrorPages;
|
|
39
|
+
now?: () => number;
|
|
40
|
+
}
|
|
41
|
+
export declare function createShield(input: ShieldOptions): Promise<{
|
|
42
|
+
handle: (request: Request, context: TrustedContext, rawTarget?: string, hooks?: {
|
|
43
|
+
event?: (event: SecurityEvent) => void;
|
|
44
|
+
}) => Promise<Response>;
|
|
45
|
+
version: string;
|
|
46
|
+
dispose(): void;
|
|
47
|
+
stats: {
|
|
48
|
+
requests: number;
|
|
49
|
+
ruleEvaluations: number;
|
|
50
|
+
blocked: number;
|
|
51
|
+
originRequests: number;
|
|
52
|
+
eventFailures: number;
|
|
53
|
+
};
|
|
54
|
+
}>;
|