



















@@ -6,55 +6,19 @@ import { runAsScript, toLine, unwrapExpression } from "./lib/ts-guard-utils.mjs"
6677const sourceRoots = ["src", "extensions"];
889-const allowedManagedProxyRuntimeMutationCallsites = new Set([
9+const allowedManagedProxyRuntimeMutationScopes = new Set([
1010// Canonical managed proxy lifecycle owns process proxy env/global-agent mutation.
11-"src/infra/net/proxy/proxy-lifecycle.ts:114",
12-"src/infra/net/proxy/proxy-lifecycle.ts:117",
13-"src/infra/net/proxy/proxy-lifecycle.ts:119",
14-"src/infra/net/proxy/proxy-lifecycle.ts:120",
15-"src/infra/net/proxy/proxy-lifecycle.ts:121",
16-"src/infra/net/proxy/proxy-lifecycle.ts:123",
17-"src/infra/net/proxy/proxy-lifecycle.ts:131",
18-"src/infra/net/proxy/proxy-lifecycle.ts:133",
19-"src/infra/net/proxy/proxy-lifecycle.ts:146",
20-"src/infra/net/proxy/proxy-lifecycle.ts:147",
21-"src/infra/net/proxy/proxy-lifecycle.ts:148",
22-"src/infra/net/proxy/proxy-lifecycle.ts:178",
23-"src/infra/net/proxy/proxy-lifecycle.ts:180",
24-"src/infra/net/proxy/proxy-lifecycle.ts:199",
25-"src/infra/net/proxy/proxy-lifecycle.ts:200",
26-"src/infra/net/proxy/proxy-lifecycle.ts:201",
27-"src/infra/net/proxy/proxy-lifecycle.ts:312",
28-"src/infra/net/proxy/proxy-lifecycle.ts:313",
29-"src/infra/net/proxy/proxy-lifecycle.ts:314",
30-"src/infra/net/proxy/proxy-lifecycle.ts:315",
31-"src/infra/net/proxy/proxy-lifecycle.ts:316",
32-"src/infra/net/proxy/proxy-lifecycle.ts:317",
33-"src/infra/net/proxy/proxy-lifecycle.ts:318",
34-"src/infra/net/proxy/proxy-lifecycle.ts:319",
35-"src/infra/net/proxy/proxy-lifecycle.ts:329",
36-"src/infra/net/proxy/proxy-lifecycle.ts:330",
37-"src/infra/net/proxy/proxy-lifecycle.ts:331",
38-"src/infra/net/proxy/proxy-lifecycle.ts:332",
39-"src/infra/net/proxy/proxy-lifecycle.ts:333",
40-"src/infra/net/proxy/proxy-lifecycle.ts:334",
41-"src/infra/net/proxy/proxy-lifecycle.ts:335",
42-"src/infra/net/proxy/proxy-lifecycle.ts:336",
43-"src/infra/net/proxy/proxy-lifecycle.ts:369",
44-"src/infra/net/proxy/proxy-lifecycle.ts:376",
45-"src/infra/net/proxy/proxy-lifecycle.ts:484",
46-"src/infra/net/proxy/proxy-lifecycle.ts:507",
47-"src/infra/net/proxy/proxy-lifecycle.ts:508",
48-"src/infra/net/proxy/proxy-lifecycle.ts:515",
49-"src/infra/net/proxy/proxy-lifecycle.ts:516",
50-51-// Browser CDP loopback control-plane helper leases NO_PROXY only for localhost/loopback CDP URLs.
52-"extensions/browser/src/browser/cdp-proxy-bypass.ts:87",
53-"extensions/browser/src/browser/cdp-proxy-bypass.ts:88",
54-"extensions/browser/src/browser/cdp-proxy-bypass.ts:120",
55-"extensions/browser/src/browser/cdp-proxy-bypass.ts:122",
56-"extensions/browser/src/browser/cdp-proxy-bypass.ts:125",
57-"extensions/browser/src/browser/cdp-proxy-bypass.ts:127",
11+"src/infra/net/proxy/proxy-lifecycle.ts#applyProxyEnv",
12+"src/infra/net/proxy/proxy-lifecycle.ts#restoreProxyEnv",
13+"src/infra/net/proxy/proxy-lifecycle.ts#restoreGlobalAgentRuntime",
14+"src/infra/net/proxy/proxy-lifecycle.ts#restoreNodeHttpStack",
15+"src/infra/net/proxy/proxy-lifecycle.ts#bootstrapNodeHttpStack",
16+"src/infra/net/proxy/proxy-lifecycle.ts#writeGlobalAgentNoProxy",
17+"src/infra/net/proxy/proxy-lifecycle.ts#disableGlobalAgentProxyForIpv6GatewayLoopback",
18+19+// Browser CDP loopback helper leases NO_PROXY only for localhost/loopback CDP URLs.
20+"extensions/browser/src/browser/cdp-proxy-bypass.ts#NoProxyLeaseManager.acquire",
21+"extensions/browser/src/browser/cdp-proxy-bypass.ts#NoProxyLeaseManager.release",
5822]);
59236024const forbiddenEnvKeys = new Set([
@@ -78,6 +42,55 @@ function stringLiteralText(node) {
7842return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node) ? node.text : null;
7943}
804445+function propertyNameText(name) {
46+if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) {
47+return name.text;
48+}
49+return null;
50+}
51+52+function qualifiedScopeName(name, classScopes) {
53+const classScope = classScopes.at(-1);
54+return classScope ? `${classScope}.${name}` : name;
55+}
56+57+function functionExpressionScopeName(node, classScopes) {
58+const parent = node.parent;
59+if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
60+return parent.name.text;
61+}
62+if (ts.isPropertyAssignment(parent)) {
63+const name = propertyNameText(parent.name);
64+return name ? qualifiedScopeName(name, classScopes) : null;
65+}
66+if (ts.isPropertyDeclaration(parent) && parent.name) {
67+const name = propertyNameText(parent.name);
68+return name ? qualifiedScopeName(name, classScopes) : null;
69+}
70+return null;
71+}
72+73+function scopeNameForNode(node, classScopes) {
74+if (ts.isFunctionDeclaration(node) && node.name) {
75+return node.name.text;
76+}
77+if (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
78+return functionExpressionScopeName(node, classScopes);
79+}
80+if (
81+ts.isMethodDeclaration(node) ||
82+ts.isGetAccessorDeclaration(node) ||
83+ts.isSetAccessorDeclaration(node)
84+) {
85+const name = propertyNameText(node.name);
86+return name ? qualifiedScopeName(name, classScopes) : null;
87+}
88+if (ts.isConstructorDeclaration(node)) {
89+return qualifiedScopeName("constructor", classScopes);
90+}
91+return null;
92+}
93+8194function isGlobalIdentifier(node, context = { globalAliases: new Set() }) {
8295const unwrapped = unwrapExpression(node);
8396return (
@@ -398,7 +411,7 @@ function mutatingCallTarget(expression, context) {
398411return null;
399412}
400413401-export function findManagedProxyRuntimeMutationLines(content, fileName = "source.ts") {
414+export function findManagedProxyRuntimeMutations(content, fileName = "source.ts") {
402415const sourceFile = ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true);
403416const globalAliases = collectGlobalAliases(sourceFile);
404417const context = {
@@ -411,19 +424,61 @@ export function findManagedProxyRuntimeMutationLines(content, fileName = "source
411424envAliases: collectEnvAliases(sourceFile),
412425stringConstants: collectStringConstants(sourceFile),
413426};
414-const lines = [];
427+const mutations = [];
428+const classScopes = [];
429+const scopeStack = [];
415430const visit = (node) => {
431+let pushedClass = false;
432+let pushedScope = false;
433+if (ts.isClassDeclaration(node) && node.name) {
434+classScopes.push(node.name.text);
435+pushedClass = true;
436+}
437+const scopeName = scopeNameForNode(node, classScopes);
438+if (scopeName) {
439+scopeStack.push(scopeName);
440+pushedScope = true;
441+}
442+416443const match =
417444assignmentTarget(node, context) ??
418445deleteTarget(node, context) ??
419446mutatingCallTarget(node, context);
420447if (match) {
421-lines.push(toLine(sourceFile, match));
448+mutations.push({
449+line: toLine(sourceFile, match),
450+scope: scopeStack.at(-1) ?? null,
451+});
422452}
423453ts.forEachChild(node, visit);
454+455+if (pushedScope) {
456+scopeStack.pop();
457+}
458+if (pushedClass) {
459+classScopes.pop();
460+}
424461};
425462visit(sourceFile);
426-return lines;
463+return mutations;
464+}
465+466+export function findManagedProxyRuntimeMutationLines(content, fileName = "source.ts") {
467+return findManagedProxyRuntimeMutations(content, fileName).map((mutation) => mutation.line);
468+}
469+470+export function isAllowedManagedProxyRuntimeMutation(violation) {
471+if (!violation.scope) {
472+return false;
473+}
474+return allowedManagedProxyRuntimeMutationScopes.has(
475+`${violation.relativePath}#${violation.scope}`,
476+);
477+}
478+479+function formatManagedProxyRuntimeMutationCallsite(violation) {
480+const scope = violation.scope ? ` (${violation.scope})` : "";
481+return `${violation.relativePath}:${violation.line}${scope}`;
427482}
428483429484export async function main() {
@@ -437,8 +492,9 @@ export async function main() {
437492".e2e.test.ts",
438493".integration.test.ts",
439494],
440-findCallLines: findManagedProxyRuntimeMutationLines,
441-allowCallsite: (callsite) => allowedManagedProxyRuntimeMutationCallsites.has(callsite),
495+findCallViolations: findManagedProxyRuntimeMutations,
496+allowViolation: isAllowedManagedProxyRuntimeMutation,
497+formatViolation: formatManagedProxyRuntimeMutationCallsite,
442498header: "Found unmanaged managed-proxy runtime mutation:",
443499footer:
444500"Only proxy lifecycle code may mutate GLOBAL_AGENT or proxy-related process.env runtime state.",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。