-
Notifications
You must be signed in to change notification settings - Fork 424
Expand file tree
/
Copy pathvalidate_lockdown_requirements.test.cjs
More file actions
389 lines (294 loc) · 16.2 KB
/
Copy pathvalidate_lockdown_requirements.test.cjs
File metadata and controls
389 lines (294 loc) · 16.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
import { describe, it, expect, beforeEach, vi } from "vitest";
describe("validate_lockdown_requirements", () => {
let mockCore;
let validateLockdownRequirements;
beforeEach(async () => {
vi.resetModules();
// Setup mock core
mockCore = {
info: vi.fn(),
setFailed: vi.fn(),
setOutput: vi.fn(),
};
// Reset process.env
delete process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT;
delete process.env.GH_AW_GITHUB_TOKEN;
delete process.env.GH_AW_GITHUB_MCP_SERVER_TOKEN;
delete process.env.CUSTOM_GITHUB_TOKEN;
delete process.env.GITHUB_REPOSITORY_VISIBILITY;
delete process.env.GH_AW_COMPILED_STRICT;
delete process.env.GITHUB_EVENT_NAME;
// Import the module
validateLockdownRequirements = (await import("./validate_lockdown_requirements.cjs")).default;
});
it("should skip lockdown validation when lockdown is not explicitly enabled", () => {
// GITHUB_MCP_LOCKDOWN_EXPLICIT not set
validateLockdownRequirements(mockCore);
expect(mockCore.info).toHaveBeenCalledWith("Lockdown mode not explicitly enabled, skipping validation");
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass validation when lockdown is enabled and GH_AW_GITHUB_TOKEN is configured", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
process.env.GH_AW_GITHUB_TOKEN = "ghp_test_token";
validateLockdownRequirements(mockCore);
expect(mockCore.info).toHaveBeenCalledWith("Lockdown mode is explicitly enabled, validating requirements...");
expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_TOKEN configured: true");
expect(mockCore.info).toHaveBeenCalledWith("✓ Lockdown mode requirements validated: Custom GitHub token is configured");
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass validation when lockdown is enabled and GH_AW_GITHUB_MCP_SERVER_TOKEN is configured", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
process.env.GH_AW_GITHUB_MCP_SERVER_TOKEN = "ghp_mcp_token";
validateLockdownRequirements(mockCore);
expect(mockCore.info).toHaveBeenCalledWith("Lockdown mode is explicitly enabled, validating requirements...");
expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_MCP_SERVER_TOKEN configured: true");
expect(mockCore.info).toHaveBeenCalledWith("✓ Lockdown mode requirements validated: Custom GitHub token is configured");
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass validation when lockdown is enabled and custom github-token is configured", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
process.env.CUSTOM_GITHUB_TOKEN = "ghp_custom_token";
validateLockdownRequirements(mockCore);
expect(mockCore.info).toHaveBeenCalledWith("Lockdown mode is explicitly enabled, validating requirements...");
expect(mockCore.info).toHaveBeenCalledWith("Custom github-token configured: true");
expect(mockCore.info).toHaveBeenCalledWith("✓ Lockdown mode requirements validated: Custom GitHub token is configured");
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should fail when lockdown is enabled but no custom tokens are configured", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
// No custom tokens set
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow("Lockdown mode is enabled");
expect(mockCore.info).toHaveBeenCalledWith("Lockdown mode is explicitly enabled, validating requirements...");
expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_TOKEN configured: false");
expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_MCP_SERVER_TOKEN configured: false");
expect(mockCore.info).toHaveBeenCalledWith("Custom github-token configured: false");
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("Lockdown mode is enabled (lockdown: true) but no custom GitHub token is configured"));
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("GH_AW_GITHUB_TOKEN (recommended)"));
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative)"));
expect(mockCore.setOutput).toHaveBeenCalledWith("lockdown_check_failed", "true");
});
it("should include documentation link in error message", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
// No custom tokens set
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow();
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/auth.mdx"));
});
it("should handle empty string tokens as not configured", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
process.env.GH_AW_GITHUB_TOKEN = "";
process.env.GH_AW_GITHUB_MCP_SERVER_TOKEN = "";
process.env.CUSTOM_GITHUB_TOKEN = "";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow("Lockdown mode is enabled");
expect(mockCore.setFailed).toHaveBeenCalled();
});
it("should skip lockdown validation when GITHUB_MCP_LOCKDOWN_EXPLICIT is false", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "false";
// GH_AW_GITHUB_TOKEN not set
validateLockdownRequirements(mockCore);
expect(mockCore.info).toHaveBeenCalledWith("Lockdown mode not explicitly enabled, skipping validation");
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
// Strict mode enforcement for public repositories
describe("strict mode enforcement for public repositories", () => {
it("should fail when repository is public and not compiled with strict mode", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "false";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow("not compiled with strict mode");
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("public repository but was not compiled with strict mode"));
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("gh aw compile --strict"));
expect(mockCore.setOutput).toHaveBeenCalledWith("lockdown_check_failed", "true");
});
it("should fail when repository is public and GH_AW_COMPILED_STRICT is not set", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
// GH_AW_COMPILED_STRICT not set
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow("not compiled with strict mode");
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("public repository but was not compiled with strict mode"));
expect(mockCore.setOutput).toHaveBeenCalledWith("lockdown_check_failed", "true");
});
it("should pass when repository is public and compiled with strict mode", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "true";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
expect(mockCore.info).toHaveBeenCalledWith("✓ Strict mode requirements validated: Public repository compiled with strict mode");
});
it("should pass when repository is private and not compiled with strict mode", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "private";
process.env.GH_AW_COMPILED_STRICT = "false";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass when repository is internal and not compiled with strict mode", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "internal";
process.env.GH_AW_COMPILED_STRICT = "false";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass when visibility is unknown and not compiled with strict mode", () => {
// GITHUB_REPOSITORY_VISIBILITY not set
process.env.GH_AW_COMPILED_STRICT = "false";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should include documentation link in strict mode error message", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "false";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow();
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx"));
});
it("should validate both lockdown and strict mode when both are required", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
process.env.GH_AW_GITHUB_TOKEN = "ghp_test_token";
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "true";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
expect(mockCore.info).toHaveBeenCalledWith("✓ Lockdown mode requirements validated: Custom GitHub token is configured");
expect(mockCore.info).toHaveBeenCalledWith("✓ Strict mode requirements validated: Public repository compiled with strict mode");
});
it("should fail on lockdown check before strict mode check when both fail", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
// No custom tokens - will fail on lockdown check
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "false";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow("Lockdown mode is enabled");
// Strict mode error should not be reached since lockdown check throws first
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("Lockdown mode is enabled"));
});
});
// pull_request_target event enforcement for public repositories
describe("pull_request_target event enforcement for public repositories", () => {
it("should fail when repository is public and event is pull_request_target", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "true";
process.env.GITHUB_EVENT_NAME = "pull_request_target";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow("pull_request_target");
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("pull_request_target event on a public repository"));
expect(mockCore.setOutput).toHaveBeenCalledWith("lockdown_check_failed", "true");
});
it("should pass when repository is public but event is pull_request (not pull_request_target)", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "true";
process.env.GITHUB_EVENT_NAME = "pull_request";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass when repository is private and event is pull_request_target", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "private";
process.env.GITHUB_EVENT_NAME = "pull_request_target";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass when repository is internal and event is pull_request_target", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "internal";
process.env.GITHUB_EVENT_NAME = "pull_request_target";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should pass when event is pull_request_target but visibility is unknown", () => {
// GITHUB_REPOSITORY_VISIBILITY not set
process.env.GITHUB_EVENT_NAME = "pull_request_target";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should include security documentation link in pull_request_target error message", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "true";
process.env.GITHUB_EVENT_NAME = "pull_request_target";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow();
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx"));
});
it("should fail on strict mode check before pull_request_target check when both fail", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "false";
process.env.GITHUB_EVENT_NAME = "pull_request_target";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow("not compiled with strict mode");
// pull_request_target error should not be reached since strict mode check throws first
expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("not compiled with strict mode"));
});
});
describe("setOutput side effects", () => {
it("should not set lockdown_check_failed output on a fully successful run", () => {
// All conditions pass: no lockdown, private repo, no special event
process.env.GITHUB_REPOSITORY_VISIBILITY = "private";
process.env.GITHUB_EVENT_NAME = "push";
validateLockdownRequirements(mockCore);
expect(mockCore.setOutput).not.toHaveBeenCalled();
expect(mockCore.setFailed).not.toHaveBeenCalled();
});
it("should not set lockdown_check_failed when lockdown is enabled with token and repo is private", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
process.env.GH_AW_GITHUB_TOKEN = "ghp_test";
process.env.GITHUB_REPOSITORY_VISIBILITY = "private";
validateLockdownRequirements(mockCore);
expect(mockCore.setOutput).not.toHaveBeenCalled();
});
});
describe("multiple tokens", () => {
it("should pass when all three tokens are configured simultaneously", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
process.env.GH_AW_GITHUB_TOKEN = "ghp_token1";
process.env.GH_AW_GITHUB_MCP_SERVER_TOKEN = "ghp_token2";
process.env.CUSTOM_GITHUB_TOKEN = "ghp_token3";
validateLockdownRequirements(mockCore);
expect(mockCore.setFailed).not.toHaveBeenCalled();
expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_TOKEN configured: true");
expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_MCP_SERVER_TOKEN configured: true");
expect(mockCore.info).toHaveBeenCalledWith("Custom github-token configured: true");
expect(mockCore.info).toHaveBeenCalledWith("✓ Lockdown mode requirements validated: Custom GitHub token is configured");
});
});
describe("error message formatting", () => {
it("should include newlines in lockdown error message for readability", () => {
process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow();
const errorMsg = mockCore.setFailed.mock.calls[0][0];
expect(errorMsg).toContain("\n");
expect(errorMsg).toContain("GH_AW_GITHUB_TOKEN (recommended)");
expect(errorMsg).toContain("GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative)");
});
it("should include newlines in strict mode error message for readability", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "false";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow();
const errorMsg = mockCore.setFailed.mock.calls[0][0];
expect(errorMsg).toContain("\n");
expect(errorMsg).toContain("gh aw compile --strict");
});
it("should include newlines in pull_request_target error message for readability", () => {
process.env.GITHUB_REPOSITORY_VISIBILITY = "public";
process.env.GH_AW_COMPILED_STRICT = "true";
process.env.GITHUB_EVENT_NAME = "pull_request_target";
expect(() => {
validateLockdownRequirements(mockCore);
}).toThrow();
const errorMsg = mockCore.setFailed.mock.calls[0][0];
expect(errorMsg).toContain("\n");
expect(errorMsg).toContain("pwn request");
});
});
});