@auth0/auth0-checkmate 1.6.16 → 1.6.17
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/analyzer/report.js +110 -4
- package/locales/en.json +2 -2
- package/package.json +1 -1
package/analyzer/report.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
1
2
|
const i18n = require("i18n");
|
|
3
|
+
const path = require("path");
|
|
2
4
|
const _ = require("lodash");
|
|
5
|
+
const Handlebars = require("handlebars");
|
|
6
|
+
const puppeteer = require("puppeteer");
|
|
3
7
|
const listOfAnalyser = require("./lib/listOfAnalyser");
|
|
4
8
|
const {
|
|
5
9
|
getAccessToken,
|
|
@@ -24,7 +28,31 @@ const {
|
|
|
24
28
|
|
|
25
29
|
const logger = require("./lib/logger");
|
|
26
30
|
const { getSummaryReport } = require("./tools/summary");
|
|
27
|
-
const { convertToTitleCase, tranformReport } = require("./tools/utils");
|
|
31
|
+
const { convertToTitleCase, tranformReport, getToday } = require("./tools/utils");
|
|
32
|
+
const { version } = require("../package.json");
|
|
33
|
+
|
|
34
|
+
i18n.configure({
|
|
35
|
+
defaultLocale: "en",
|
|
36
|
+
objectNotation: true,
|
|
37
|
+
directory: path.join(__dirname, "../locales")
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
Handlebars.registerHelper("chooseFont", function (locale) {
|
|
41
|
+
if (locale === "ja") return "Noto Sans JP, sans-serif";
|
|
42
|
+
if (locale === "ko") return "Noto Sans KR, sans-serif";
|
|
43
|
+
return "DM Sans, sans-serif";
|
|
44
|
+
});
|
|
45
|
+
Handlebars.registerHelper("replace", function (str, search, replace) {
|
|
46
|
+
return str.replace(search, replace);
|
|
47
|
+
});
|
|
48
|
+
Handlebars.registerHelper("and", (a, b) => a && b);
|
|
49
|
+
Handlebars.registerHelper("inc", (a) => parseInt(a) + 1);
|
|
50
|
+
|
|
51
|
+
const templateData = fs.readFileSync(
|
|
52
|
+
path.join(__dirname, "../views/pdf_cli_report.handlebars"),
|
|
53
|
+
"utf8"
|
|
54
|
+
);
|
|
55
|
+
|
|
28
56
|
async function runProductionChecks(tenant, validators) {
|
|
29
57
|
try {
|
|
30
58
|
logger.log("info", "Checking your configuration...");
|
|
@@ -170,7 +198,7 @@ async function generateReport(locale, tenantConfig, config) {
|
|
|
170
198
|
cd.message = i18n.__(`checkEmailTemplates.${cd.field}`, cd.value);
|
|
171
199
|
});
|
|
172
200
|
break;
|
|
173
|
-
|
|
201
|
+
case "checkErrorPageTemplate":
|
|
174
202
|
report.details.forEach((cd) => {
|
|
175
203
|
cd.message = i18n.__(`checkErrorPageTemplate.${cd.field}`, cd.value);
|
|
176
204
|
});
|
|
@@ -307,7 +335,7 @@ async function generateReport(locale, tenantConfig, config) {
|
|
|
307
335
|
});
|
|
308
336
|
});
|
|
309
337
|
break;
|
|
310
|
-
case "checkPasswordResetMFA":
|
|
338
|
+
case "checkPasswordResetMFA":
|
|
311
339
|
case "checkPreRegistrationUserEnumeration":
|
|
312
340
|
case "checkActionsHardCodedValues":
|
|
313
341
|
case "checkDASHardCodedValues":
|
|
@@ -334,7 +362,7 @@ async function generateReport(locale, tenantConfig, config) {
|
|
|
334
362
|
return `<li>${message}</li>`;
|
|
335
363
|
}).join("\n");
|
|
336
364
|
const dasTitle = i18n.__(`${report.name}.action_script_title`,
|
|
337
|
-
|
|
365
|
+
scriptName);
|
|
338
366
|
return `<p>${dasTitle}<p>\n<ul>\n${listItems}\n</ul>`;
|
|
339
367
|
});
|
|
340
368
|
|
|
@@ -401,6 +429,84 @@ async function generateReport(locale, tenantConfig, config) {
|
|
|
401
429
|
}
|
|
402
430
|
}
|
|
403
431
|
|
|
432
|
+
async function generatePdfBuffer(report, auth0Domain, locale) {
|
|
433
|
+
locale = locale || "en";
|
|
434
|
+
const today = await getToday(locale);
|
|
435
|
+
|
|
436
|
+
const data = { report, auth0Domain, today, locale, version, config: {} };
|
|
437
|
+
|
|
438
|
+
const browser = await puppeteer.launch({
|
|
439
|
+
headless: true, // Run in headless mode
|
|
440
|
+
args: [
|
|
441
|
+
"--no-sandbox", // Disable the sandbox
|
|
442
|
+
"--disable-setuid-sandbox", // Disable setuid sandbox
|
|
443
|
+
],
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
const template = Handlebars.compile(templateData);
|
|
448
|
+
const htmlContent = template({
|
|
449
|
+
locale: data.locale,
|
|
450
|
+
data,
|
|
451
|
+
preamble: data.report.preamble,
|
|
452
|
+
});
|
|
453
|
+
const page = await browser.newPage();
|
|
454
|
+
|
|
455
|
+
// Disable JS execution in the Puppeteer page. Disabling
|
|
456
|
+
// JS eliminates the browser-side execution surface during PDF rendering.
|
|
457
|
+
await page.setJavaScriptEnabled(false);
|
|
458
|
+
|
|
459
|
+
// Allowlist only the CDN hostnames the template legitimately loads from
|
|
460
|
+
// (Bootstrap, Google Fonts). All other outbound requests — including RFC 1918
|
|
461
|
+
// addresses and cloud metadata endpoints — are aborted to prevent SSRF via
|
|
462
|
+
// passive resource loading (e.g. <img src="http://169.254.169.254/...">) in
|
|
463
|
+
// case tenant-controlled data ever reaches an unescaped template field.
|
|
464
|
+
await page.setRequestInterception(true);
|
|
465
|
+
page.on("request", (req) => {
|
|
466
|
+
const url = new URL(req.url());
|
|
467
|
+
const allowed = [
|
|
468
|
+
"fonts.googleapis.com",
|
|
469
|
+
"fonts.gstatic.com",
|
|
470
|
+
"cdn.jsdelivr.net",
|
|
471
|
+
];
|
|
472
|
+
if (req.resourceType() === "document" || allowed.includes(url.hostname)) {
|
|
473
|
+
req.continue();
|
|
474
|
+
} else {
|
|
475
|
+
req.abort();
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
await page.setContent(htmlContent, { waitUntil: "networkidle2" });
|
|
480
|
+
|
|
481
|
+
const pdfResult = await page.pdf({
|
|
482
|
+
format: "A4",
|
|
483
|
+
printBackground: true,
|
|
484
|
+
displayHeaderFooter: true,
|
|
485
|
+
headerTemplate: `<div></div>`,
|
|
486
|
+
footerTemplate: `
|
|
487
|
+
<div style="font-size:10px; width:100%; padding:10px 0; display:flex; align-items:center; justify-content:space-between; border-top:1px solid #ddd;">
|
|
488
|
+
<span style="flex:1; text-align:center;">Confidential. For internal evaluation purposes only.</span>
|
|
489
|
+
<span style="flex:1; text-align:right; padding-right:20px;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></span>
|
|
490
|
+
</div>`,
|
|
491
|
+
margin: {
|
|
492
|
+
top: "20px",
|
|
493
|
+
bottom: "60px",
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
// Puppeteer v20+ returns Uint8Array, not Buffer. Express's res.send() calls
|
|
497
|
+
// Buffer.isBuffer() and JSON-serialises anything that fails the check,
|
|
498
|
+
// producing {"0":37,"1":80,...} instead of raw binary. Convert explicitly.
|
|
499
|
+
|
|
500
|
+
return Buffer.from(pdfResult);
|
|
501
|
+
} catch (error) {
|
|
502
|
+
logger.log("error", `Error generating PDF: ${error}`);
|
|
503
|
+
throw error;
|
|
504
|
+
} finally {
|
|
505
|
+
await browser.close();
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
404
509
|
module.exports = {
|
|
405
510
|
generateReport,
|
|
511
|
+
generatePdfBuffer,
|
|
406
512
|
};
|
package/locales/en.json
CHANGED
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
},
|
|
183
183
|
"no_custom_domains": "This tenant is not configured to use a custom domain. We recommend using custom domains with Universal Login for the most seamless and secure experience for end users. We also highly recommend using custom domains for passkey authentication, given they are tied to a specific domain during enrollment.",
|
|
184
184
|
"ready": "This tenant is configured to use a custom domain. %s",
|
|
185
|
-
"
|
|
185
|
+
"pending_verification": "The tenant's custom domain configuration is incomplete, %s",
|
|
186
186
|
"severity": "High",
|
|
187
187
|
"status": "red",
|
|
188
188
|
"severity_message": "Configure a Custom Domain",
|
|
@@ -1477,4 +1477,4 @@
|
|
|
1477
1477
|
"https://auth0.com/docs/customize/events/event-testing-observability-and-failure-recovery"
|
|
1478
1478
|
]
|
|
1479
1479
|
}
|
|
1480
|
-
}
|
|
1480
|
+
}
|