@auth0/auth0-checkmate 1.4.0
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/.github/CODEOWNERS +1 -0
- package/.github/workflows/npm-release.yml +77 -0
- package/.github/workflows/sca_scan.yml +10 -0
- package/.github/workflows/test.yml +48 -0
- package/AUTHORS +5 -0
- package/LICENSE +203 -0
- package/README.md +166 -0
- package/THIRD-PARTY-NOTICES +226 -0
- package/analyzer/lib/actions/checkActionsHardCodedValues.js +151 -0
- package/analyzer/lib/actions/checkActionsRuntime.js +105 -0
- package/analyzer/lib/actions/checkDependencies.js +111 -0
- package/analyzer/lib/attack_protection/checkBotDetectionSetting.js +76 -0
- package/analyzer/lib/attack_protection/checkBreachedPassword.js +140 -0
- package/analyzer/lib/attack_protection/checkBruteForce.js +89 -0
- package/analyzer/lib/attack_protection/checkSuspiciousIPThrottling.js +89 -0
- package/analyzer/lib/canonical_domain/checkCanonicalDomain.js +63 -0
- package/analyzer/lib/clients/checkAllowedCallbacks.js +122 -0
- package/analyzer/lib/clients/checkAllowedLogoutUrl.js +124 -0
- package/analyzer/lib/clients/checkApplicationLoginUri.js +125 -0
- package/analyzer/lib/clients/checkCrossOriginAuthentication.js +91 -0
- package/analyzer/lib/clients/checkGrantTypes.js +138 -0
- package/analyzer/lib/clients/checkJWTSignAlg.js +118 -0
- package/analyzer/lib/clients/checkRefreshToken.js +108 -0
- package/analyzer/lib/clients/checkWebOrigins.js +55 -0
- package/analyzer/lib/constants.js +63 -0
- package/analyzer/lib/custom_domain/checkCustomDomain.js +53 -0
- package/analyzer/lib/databases/checkAuthenticationMethods.js +98 -0
- package/analyzer/lib/databases/checkDASHardCodedValues.js +163 -0
- package/analyzer/lib/databases/checkEmailAttributeVerification.js +114 -0
- package/analyzer/lib/databases/checkEnabledDatabaseCustomization.js +83 -0
- package/analyzer/lib/databases/checkPasswordComplexity.js +100 -0
- package/analyzer/lib/databases/checkPasswordHistory.js +92 -0
- package/analyzer/lib/databases/checkPasswordNoPersonalInfo.js +91 -0
- package/analyzer/lib/databases/checkPasswordPolicy.js +95 -0
- package/analyzer/lib/databases/checkPromotedDBConnection.js +96 -0
- package/analyzer/lib/email_provider/checkEmailProvider.js +37 -0
- package/analyzer/lib/email_templates/checkEmailTemplates.js +71 -0
- package/analyzer/lib/error_page_template/checkErrorPageTemplate.js +153 -0
- package/analyzer/lib/event_streams/checkEventStreams.js +71 -0
- package/analyzer/lib/executeCheck.js +12 -0
- package/analyzer/lib/hooks/checkHooks.js +43 -0
- package/analyzer/lib/listOfAnalyser.js +24 -0
- package/analyzer/lib/log_streams/checkLogStream.js +60 -0
- package/analyzer/lib/logger.js +16 -0
- package/analyzer/lib/multifactor/checkGuardianFactors.js +72 -0
- package/analyzer/lib/multifactor/checkGuardianPolicy.js +40 -0
- package/analyzer/lib/network_acl/checkNetworkACL.js +35 -0
- package/analyzer/lib/rules/checkRules.js +102 -0
- package/analyzer/lib/tenant_settings/checkDefaultAudience.js +53 -0
- package/analyzer/lib/tenant_settings/checkDefaultDirectory.js +48 -0
- package/analyzer/lib/tenant_settings/checkEnabledDynamicClientRegistration.js +60 -0
- package/analyzer/lib/tenant_settings/checkSandboxVersion.js +37 -0
- package/analyzer/lib/tenant_settings/checkSessionLifetime.js +95 -0
- package/analyzer/lib/tenant_settings/checkSupportEmail.js +61 -0
- package/analyzer/lib/tenant_settings/checkSupportUrl.js +61 -0
- package/analyzer/lib/tenant_settings/checkTenantLoginUrl.js +71 -0
- package/analyzer/lib/tenant_settings/checkTenantLogoutUrl.js +60 -0
- package/analyzer/report.js +404 -0
- package/analyzer/tools/auth0.js +443 -0
- package/analyzer/tools/helpers.js +71 -0
- package/analyzer/tools/summary.js +84 -0
- package/analyzer/tools/utils.js +72 -0
- package/bin/index.js +393 -0
- package/eslint.config.mjs +16 -0
- package/images/auth0.png +0 -0
- package/images/okta.png +0 -0
- package/locales/en.json +1417 -0
- package/package.json +66 -0
- package/tests/actions/checkActionsHardCodedValues.test.js +106 -0
- package/tests/actions/checkActionsRuntime.test.js +102 -0
- package/tests/actions/checkDependencies.test.js +131 -0
- package/tests/attack_protection/checkBreachedPassword.test.js +253 -0
- package/tests/attack_protection/checkBruteForce.test.js +181 -0
- package/tests/attack_protection/checkSuspiciousIPThrottling.test.js +222 -0
- package/tests/canonical_domain/checkCanonicalDomain.test.js +94 -0
- package/tests/clients/checkAllowedCallbacks.test.js +149 -0
- package/tests/clients/checkAllowedLogoutUrl.test.js +149 -0
- package/tests/clients/checkApplicationLoginUri.test.js +180 -0
- package/tests/clients/checkCrossOriginAuthentication.test.js +99 -0
- package/tests/clients/checkGrantTypes.test.js +154 -0
- package/tests/clients/checkJWTSignAlg.test.js +121 -0
- package/tests/clients/checkRefreshToken.test.js +63 -0
- package/tests/clients/checkWebOrigins.test.js +140 -0
- package/tests/custom_domain/checkCustomDomain.test.js +73 -0
- package/tests/databases/checkAuthenticationMethods.test.js +124 -0
- package/tests/databases/checkDASHardCodedValues.test.js +77 -0
- package/tests/databases/checkEmailAttributeVerification.test.js +79 -0
- package/tests/databases/checkEnabledDatabaseCustomization.test.js +68 -0
- package/tests/databases/checkPasswordComplexity.test.js +127 -0
- package/tests/databases/checkPasswordHistory.test.js +100 -0
- package/tests/databases/checkPasswordNoPersonalInfo.test.js +94 -0
- package/tests/databases/checkPasswordPolicy.test.js +161 -0
- package/tests/databases/checkPromotedDBConnection.test.js +62 -0
- package/tests/email_provider/checkEmailProvider.test.js +58 -0
- package/tests/email_templates/checkEmailTemplates.test.js +120 -0
- package/tests/error_page_template/checkErrorPageTemplate.test.js +315 -0
- package/tests/event_streams/checkEventStreams.test.js +118 -0
- package/tests/hooks/checkHooks.test.js +112 -0
- package/tests/log_streams/checkLogStream.test.js +140 -0
- package/tests/multifactor/checkGuardianFactors.test.js +94 -0
- package/tests/multifactor/checkGuardianPolicy.test.js +49 -0
- package/tests/rules/checkRules.test.js +102 -0
- package/tests/tenant_settings/checkDefaultAudience.test.js +62 -0
- package/tests/tenant_settings/checkDefaultDirectory.test.js +62 -0
- package/tests/tenant_settings/checkEnabledDynamicClientRegistration.test.js +97 -0
- package/tests/tenant_settings/checkSandboxVersion.test.js +50 -0
- package/tests/tenant_settings/checkSessionLifetime.test.js +108 -0
- package/tests/tenant_settings/checkSupportEmail.test.js +77 -0
- package/tests/tenant_settings/checkSupportUrl.test.js +77 -0
- package/tests/tenant_settings/checkTenantLoginUri.test.js +82 -0
- package/tests/tenant_settings/checkTenantLogoutUrl.test.js +108 -0
- package/tests/tools/auth0.test.js +833 -0
- package/tests/tools/helpers.test.js +692 -0
- package/views/pdf_cli_report.handlebars +571 -0
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@auth0/auth0-checkmate",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "A command line tool for checking configuration of your Auth0 tenant",
|
|
5
|
+
"main": "analyzer/report.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "bin/index.js",
|
|
8
|
+
"format": "npx prettier --write .",
|
|
9
|
+
"lint": "eslint .",
|
|
10
|
+
"test": "nyc mocha tests/*"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"a0checkmate": "bin/index.js"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=20.18.3"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"acorn": "^8.14.0",
|
|
20
|
+
"axios": "^1.12.0",
|
|
21
|
+
"chalk": "^4.1.2",
|
|
22
|
+
"cli-table3": "^0.6.5",
|
|
23
|
+
"estree-walker": "^2.0.2",
|
|
24
|
+
"figlet": "^1.8.0",
|
|
25
|
+
"glob": "^11.0.1",
|
|
26
|
+
"handlebars": "^4.7.8",
|
|
27
|
+
"i18n": "^0.15.1",
|
|
28
|
+
"inquirer": "^12.3.3",
|
|
29
|
+
"jsonwebtoken": "^9.0.2",
|
|
30
|
+
"lodash": "^4.17.21",
|
|
31
|
+
"moment": "^2.30.1",
|
|
32
|
+
"puppeteer": "^24.10.0",
|
|
33
|
+
"semver": "^7.7.1",
|
|
34
|
+
"winston": "^3.17.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@eslint/js": "^9.23.0",
|
|
38
|
+
"chai": "^5.2.0",
|
|
39
|
+
"eslint": "^9.23.0",
|
|
40
|
+
"eslint-plugin-mocha": "^10.5.0",
|
|
41
|
+
"globals": "^16.0.0",
|
|
42
|
+
"mocha": "^11.1.0",
|
|
43
|
+
"nock": "^14.0.1",
|
|
44
|
+
"nyc": "^17.1.0",
|
|
45
|
+
"proxyquire": "^2.1.3",
|
|
46
|
+
"sinon": "^19.0.2"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/auth0/auth0-checkmate.git"
|
|
54
|
+
},
|
|
55
|
+
"keywords": [
|
|
56
|
+
"auth0",
|
|
57
|
+
"analyzer",
|
|
58
|
+
"configuration"
|
|
59
|
+
],
|
|
60
|
+
"author": "Auth0",
|
|
61
|
+
"license": "Apache-2.0",
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/auth0/auth0-checkmate/issues"
|
|
64
|
+
},
|
|
65
|
+
"homepage": "https://github.com/auth0/auth0-checkmate#readme"
|
|
66
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const chai = require("chai");
|
|
2
|
+
const expect = chai.expect;
|
|
3
|
+
const checkActionsHardCodedValues = require("../../analyzer/lib/actions/checkActionsHardCodedValues"); // Import your function
|
|
4
|
+
const CONSTANTS = require("../../analyzer/lib/constants"); // Assuming constants file is required
|
|
5
|
+
|
|
6
|
+
describe("checkActionsHardCodedValues", function () {
|
|
7
|
+
it("should return an empty array when no actions have hardcoded values", async function () {
|
|
8
|
+
const input = {
|
|
9
|
+
actions: {
|
|
10
|
+
actions: [
|
|
11
|
+
{
|
|
12
|
+
id: "0cdb84c6-9faf-4344-b1c5-affa9db5a63f",
|
|
13
|
+
name: "Custom Phone Provider",
|
|
14
|
+
supported_triggers: [
|
|
15
|
+
{ id: "custom-phone-provider", version: "v1" },
|
|
16
|
+
],
|
|
17
|
+
created_at: "2024-12-05T03:14:55.811465959Z",
|
|
18
|
+
updated_at: "2024-12-05T03:14:55.831277001Z",
|
|
19
|
+
code: "exports.onExecuteCustomPhoneProvider = async (event, api) => {\n // Code goes here\n return;\n};",
|
|
20
|
+
dependencies: [],
|
|
21
|
+
runtime: "node18",
|
|
22
|
+
status: "built",
|
|
23
|
+
secrets: [],
|
|
24
|
+
all_changes_deployed: false,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const reports = await checkActionsHardCodedValues(input);
|
|
31
|
+
expect(reports.details).to.be.an("array").that.is.empty;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should detect hardcoded values in action code", async function () {
|
|
35
|
+
const input = {
|
|
36
|
+
actions: {
|
|
37
|
+
actions: [
|
|
38
|
+
{
|
|
39
|
+
id: "89df9e29-d521-43f4-9b80-8a8f9623ad39",
|
|
40
|
+
name: "Console Log",
|
|
41
|
+
supported_triggers: [{ id: "post-login", version: "v3" }],
|
|
42
|
+
created_at: "2024-12-05T03:48:52.546705182Z",
|
|
43
|
+
updated_at: "2025-02-05T04:33:20.935611754Z",
|
|
44
|
+
code: 'exports.onExecutePostLogin = async (event, api) => {\n const PASSWORD = "abcd1234";\n console.log(JSON.stringify(event.user, null, 2));\n};',
|
|
45
|
+
dependencies: [{ name: "aws-sdk", version: "2.1448.0" }],
|
|
46
|
+
runtime: "node18-actions",
|
|
47
|
+
status: "built",
|
|
48
|
+
secrets: [],
|
|
49
|
+
all_changes_deployed: true,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
total: 1,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const reports = await checkActionsHardCodedValues(input);
|
|
57
|
+
expect(reports.details).to.have.lengthOf(1);
|
|
58
|
+
const report = reports.details[0];
|
|
59
|
+
expect(report.name).to.equal("Console Log (post-login)");
|
|
60
|
+
expect(report.report).to.have.lengthOf(1);
|
|
61
|
+
expect(report.report[0].variableName).to.equal("PASSWORD");
|
|
62
|
+
expect(report.report[0].type).to.equal("string");
|
|
63
|
+
expect(report.report[0].field).to.equal("hard_coded_value_detected");
|
|
64
|
+
expect(report.report[0].status).to.equal(CONSTANTS.FAIL);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should flag multiple hardcoded values in action code", async function () {
|
|
68
|
+
const input = {
|
|
69
|
+
actions: {
|
|
70
|
+
actions: [
|
|
71
|
+
{
|
|
72
|
+
id: "0cdb84c6-9faf-4344-b1c5-affa9db5a63f",
|
|
73
|
+
name: "Custom Phone Provider",
|
|
74
|
+
supported_triggers: [
|
|
75
|
+
{ id: "custom-phone-provider", version: "v1" },
|
|
76
|
+
],
|
|
77
|
+
created_at: "2024-12-05T03:14:55.811465959Z",
|
|
78
|
+
updated_at: "2024-12-05T03:14:55.831277001Z",
|
|
79
|
+
code: 'exports.onExecuteCustomPhoneProvider = async (event, api) => {\n const PHONE_NUMBER = "123-456-7890";\n const USERNAME = "user123";\n return;\n};',
|
|
80
|
+
dependencies: [],
|
|
81
|
+
runtime: "node18",
|
|
82
|
+
status: "built",
|
|
83
|
+
secrets: [],
|
|
84
|
+
all_changes_deployed: false,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
total: 1,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const reports = await checkActionsHardCodedValues(input);
|
|
92
|
+
expect(reports.details).to.have.lengthOf(1);
|
|
93
|
+
const report = reports.details[0];
|
|
94
|
+
expect(report.name).to.equal(
|
|
95
|
+
"Custom Phone Provider (custom-phone-provider)",
|
|
96
|
+
);
|
|
97
|
+
expect(report.report).to.have.lengthOf(2);
|
|
98
|
+
|
|
99
|
+
// Check for each of the hardcoded values
|
|
100
|
+
expect(report.report[0].variableName).to.equal("PHONE_NUMBER");
|
|
101
|
+
expect(report.report[0].type).to.equal("string");
|
|
102
|
+
|
|
103
|
+
expect(report.report[1].variableName).to.equal("USERNAME");
|
|
104
|
+
expect(report.report[1].type).to.equal("string");
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const chai = require("chai");
|
|
2
|
+
const expect = chai.expect;
|
|
3
|
+
|
|
4
|
+
const checkActionsRuntime = require("../../analyzer/lib/actions/checkActionsRuntime");
|
|
5
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
6
|
+
|
|
7
|
+
describe("checkActionsRuntime", function () {
|
|
8
|
+
it("should not return a report when no actions are provided", function () {
|
|
9
|
+
const options = {};
|
|
10
|
+
|
|
11
|
+
checkActionsRuntime(options, (report) => {
|
|
12
|
+
expect(report).to.deep.equal([]);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should return a failure report for actions with outdated Node.js versions", function () {
|
|
17
|
+
const options = {
|
|
18
|
+
actions: {
|
|
19
|
+
actions: [
|
|
20
|
+
{
|
|
21
|
+
id: "0cdb84c6-9faf-4344-b1c5-affa9db5a63f",
|
|
22
|
+
name: "Custom Phone Provider",
|
|
23
|
+
runtime: "node16", // Outdated version
|
|
24
|
+
supported_triggers: [
|
|
25
|
+
{ id: "custom-phone-provider", version: "v1" },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "89df9e29-d521-43f4-9b80-8a8f9623ad39",
|
|
30
|
+
name: "Console Log",
|
|
31
|
+
runtime: "node22", // Valid version
|
|
32
|
+
supported_triggers: [{ id: "post-login", version: "v3" }],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
checkActionsRuntime(options, (report) => {
|
|
39
|
+
expect(report).to.deep.equal([
|
|
40
|
+
{
|
|
41
|
+
name: "Custom Phone Provider (custom-phone-provider)",
|
|
42
|
+
field: "old_node_version",
|
|
43
|
+
status: CONSTANTS.FAIL,
|
|
44
|
+
value: 16,
|
|
45
|
+
},
|
|
46
|
+
]);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should not return a report for actions with valid Node.js versions", function () {
|
|
51
|
+
const options = {
|
|
52
|
+
actions: {
|
|
53
|
+
actions: [
|
|
54
|
+
{
|
|
55
|
+
id: "0cdb84c6-9faf-4344-b1c5-affa9db5a63f",
|
|
56
|
+
name: "Custom Phone Provider",
|
|
57
|
+
runtime: "node22", // Valid version
|
|
58
|
+
supported_triggers: [
|
|
59
|
+
{ id: "custom-phone-provider", version: "v1" },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "89df9e29-d521-43f4-9b80-8a8f9623ad39",
|
|
64
|
+
name: "Console Log",
|
|
65
|
+
runtime: "node22", // Valid version
|
|
66
|
+
supported_triggers: [{ id: "post-login", version: "v3" }],
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
checkActionsRuntime(options, (report) => {
|
|
73
|
+
expect(report).to.deep.equal([]);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should return a failure report for actions with outdated Node.js versions and correct trigger names", function () {
|
|
78
|
+
const options = {
|
|
79
|
+
actions: {
|
|
80
|
+
actions: [
|
|
81
|
+
{
|
|
82
|
+
id: "7d24512b-aa56-4ddc-8b51-68583110c5fa",
|
|
83
|
+
name: "action example 1",
|
|
84
|
+
runtime: "node17", // Outdated version
|
|
85
|
+
supported_triggers: [{ id: "post-login", version: "v3" }],
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
checkActionsRuntime(options, (report) => {
|
|
92
|
+
expect(report).to.deep.equal([
|
|
93
|
+
{
|
|
94
|
+
name: "action example 1 (post-login)",
|
|
95
|
+
field: "old_node_version",
|
|
96
|
+
status: CONSTANTS.FAIL,
|
|
97
|
+
value: 17,
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const { expect } = require("chai");
|
|
2
|
+
const checkDependencies = require("../../analyzer/lib/actions/checkDependencies");
|
|
3
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
4
|
+
|
|
5
|
+
// Directly mock the getActionDependencies function
|
|
6
|
+
describe("checkDependencies", function () {
|
|
7
|
+
let originalGetActionDependencies;
|
|
8
|
+
|
|
9
|
+
// Save the original method to restore after each test
|
|
10
|
+
beforeEach(function () {
|
|
11
|
+
// Mock the getActionDependencies function
|
|
12
|
+
originalGetActionDependencies =
|
|
13
|
+
require("../../analyzer/tools/helpers").getActionDependencies;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
afterEach(function () {
|
|
17
|
+
// Restore the original function after each test
|
|
18
|
+
require("../../analyzer/tools/helpers").getActionDependencies =
|
|
19
|
+
originalGetActionDependencies;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should return an empty report if no actions are provided", async function () {
|
|
23
|
+
const callback = (report) => {
|
|
24
|
+
// Assert that the report is empty
|
|
25
|
+
expect(report).to.be.an("array").that.is.empty;
|
|
26
|
+
};
|
|
27
|
+
await checkDependencies({ actions: [] }, callback);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should return an empty report if actions list is empty", async function () {
|
|
31
|
+
const callback = (report) => {
|
|
32
|
+
// Assert that the report is empty
|
|
33
|
+
expect(report).to.be.an("array").that.is.empty;
|
|
34
|
+
};
|
|
35
|
+
await checkDependencies({ actions: { actions: [] } }, callback);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should return a report with dependency vulnerabilities when high or critical vulnerabilities are found", async function () {
|
|
39
|
+
// Mocking the getActionDependencies to simulate vulnerabilities in dependencies
|
|
40
|
+
require("../../analyzer/tools/auth0").getActionDependencies = async () => [
|
|
41
|
+
{
|
|
42
|
+
actionName: "Custom Phone Provider",
|
|
43
|
+
trigger: "custom-phone-provider",
|
|
44
|
+
vulnFindings: [
|
|
45
|
+
{ severity: "high", name: "aws-sdk", version: "2.1448.0" },
|
|
46
|
+
{ severity: "low", name: "lodash", version: "4.17.21" },
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const callback = (report) => {
|
|
52
|
+
expect(report.details).to.have.lengthOf(1);
|
|
53
|
+
expect(report.details[0]).to.deep.equal({
|
|
54
|
+
name: "Custom Phone Provider (custom-phone-provider-action)",
|
|
55
|
+
field: "dependency_with_vuln",
|
|
56
|
+
status: CONSTANTS.FAIL,
|
|
57
|
+
value: "aws-sdk version 2.1448.0",
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
await checkDependencies(
|
|
62
|
+
{
|
|
63
|
+
actions: {
|
|
64
|
+
actions: [
|
|
65
|
+
{
|
|
66
|
+
id: "0cdb84c6",
|
|
67
|
+
name: "Custom Phone Provider",
|
|
68
|
+
dependencies: [
|
|
69
|
+
{
|
|
70
|
+
name: "aws-sdk",
|
|
71
|
+
version: "2.1448.0",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
supported_triggers: [
|
|
75
|
+
{
|
|
76
|
+
id: "custom-phone-provider",
|
|
77
|
+
version: "v1",
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
callback,
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should not return any vulnerabilities if no high or critical vulnerabilities are found", async function () {
|
|
89
|
+
// Mocking the getActionDependencies to simulate no critical or high vulnerabilities
|
|
90
|
+
require("../../analyzer/tools/auth0").getActionDependencies = async () => [
|
|
91
|
+
{
|
|
92
|
+
actionName: "Console Log",
|
|
93
|
+
trigger: "post-login",
|
|
94
|
+
vulnFindings: [
|
|
95
|
+
{ severity: "low", name: "aws-sdk", version: "2.1448.0" },
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
const callback = (report) => {
|
|
101
|
+
// The report should be empty (no high/critical vulnerabilities)
|
|
102
|
+
expect(report.details).to.be.an("array").that.is.empty;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
await checkDependencies(
|
|
106
|
+
{
|
|
107
|
+
actions: {
|
|
108
|
+
actions: [
|
|
109
|
+
{
|
|
110
|
+
id: "89df9e29",
|
|
111
|
+
name: "Console Log",
|
|
112
|
+
dependencies: [
|
|
113
|
+
{
|
|
114
|
+
name: "aws-sdk",
|
|
115
|
+
version: "2.1448.0",
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
supported_triggers: [
|
|
119
|
+
{
|
|
120
|
+
id: "post-login",
|
|
121
|
+
version: "v1",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
callback,
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
const { expect } = require("chai");
|
|
2
|
+
const checkBreachedPassword = require("../../analyzer/lib/attack_protection/checkBreachedPassword");
|
|
3
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
4
|
+
|
|
5
|
+
describe("checkBreachedPassword", function () {
|
|
6
|
+
it("should return a success when breachedPasswordDetection is enabled and correctly configured", function () {
|
|
7
|
+
const options = {
|
|
8
|
+
attackProtection: {
|
|
9
|
+
breachedPasswordDetection: {
|
|
10
|
+
enabled: true,
|
|
11
|
+
shields: ["user_notification", "admin_notification", "block"],
|
|
12
|
+
admin_notification_frequency: ["daily", "weekly"],
|
|
13
|
+
method: "standard",
|
|
14
|
+
stage: {
|
|
15
|
+
"pre-user-registration": {
|
|
16
|
+
shields: ["block", "admin_notification"],
|
|
17
|
+
},
|
|
18
|
+
"pre-change-password": {
|
|
19
|
+
shields: ["block"],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
checkBreachedPassword(options, (report) => {
|
|
27
|
+
// Check if the report contains the expected success statuses for all fields
|
|
28
|
+
expect(report).to.deep.include({
|
|
29
|
+
field: "enabled",
|
|
30
|
+
status: CONSTANTS.SUCCESS,
|
|
31
|
+
});
|
|
32
|
+
expect(report).to.deep.include({
|
|
33
|
+
field: "shields_values",
|
|
34
|
+
status: CONSTANTS.SUCCESS,
|
|
35
|
+
});
|
|
36
|
+
expect(report).to.deep.include({
|
|
37
|
+
field: "admin_frequency_values",
|
|
38
|
+
status: CONSTANTS.SUCCESS,
|
|
39
|
+
});
|
|
40
|
+
expect(report).to.deep.include({
|
|
41
|
+
field: "method_value",
|
|
42
|
+
status: CONSTANTS.SUCCESS,
|
|
43
|
+
});
|
|
44
|
+
expect(report).to.deep.include({
|
|
45
|
+
field: "stage_pre_user_shields",
|
|
46
|
+
status: CONSTANTS.SUCCESS,
|
|
47
|
+
});
|
|
48
|
+
expect(report).to.deep.include({
|
|
49
|
+
field: "stage_pre_change_password_shields",
|
|
50
|
+
status: CONSTANTS.SUCCESS,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should return failure when breachedPasswordDetection is disabled", function () {
|
|
56
|
+
const options = {
|
|
57
|
+
attackProtection: {
|
|
58
|
+
breachedPasswordDetection: {
|
|
59
|
+
enabled: false,
|
|
60
|
+
shields: ["user_notification"],
|
|
61
|
+
admin_notification_frequency: ["daily"],
|
|
62
|
+
method: "standard",
|
|
63
|
+
stage: {
|
|
64
|
+
"pre-user-registration": {
|
|
65
|
+
shields: ["block"],
|
|
66
|
+
},
|
|
67
|
+
"pre-change-password": {
|
|
68
|
+
shields: ["block"],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
checkBreachedPassword(options, (report) => {
|
|
76
|
+
expect(report).to.deep.include({
|
|
77
|
+
field: "disabled",
|
|
78
|
+
status: CONSTANTS.FAIL,
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should return failure when shields have invalid values", function () {
|
|
84
|
+
const options = {
|
|
85
|
+
attackProtection: {
|
|
86
|
+
breachedPasswordDetection: {
|
|
87
|
+
enabled: true,
|
|
88
|
+
shields: ["user_notification", "invalid_shield"],
|
|
89
|
+
admin_notification_frequency: ["daily"],
|
|
90
|
+
method: "standard",
|
|
91
|
+
stage: {
|
|
92
|
+
"pre-user-registration": {
|
|
93
|
+
shields: ["block"],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
checkBreachedPassword(options, (report) => {
|
|
101
|
+
expect(report).to.deep.include({
|
|
102
|
+
field: "shields_invalid_values",
|
|
103
|
+
status: CONSTANTS.FAIL,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("should return failure when admin_notification_frequency has invalid values", function () {
|
|
109
|
+
const options = {
|
|
110
|
+
attackProtection: {
|
|
111
|
+
breachedPasswordDetection: {
|
|
112
|
+
enabled: true,
|
|
113
|
+
shields: ["user_notification"],
|
|
114
|
+
admin_notification_frequency: ["invalid_frequency"],
|
|
115
|
+
method: "standard",
|
|
116
|
+
stage: {
|
|
117
|
+
"pre-user-registration": {
|
|
118
|
+
shields: ["block"],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
checkBreachedPassword(options, (report) => {
|
|
126
|
+
expect(report).to.deep.include({
|
|
127
|
+
field: "admin_frequency_invalid_values",
|
|
128
|
+
status: CONSTANTS.FAIL,
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should return failure when method is invalid", function () {
|
|
134
|
+
const options = {
|
|
135
|
+
attackProtection: {
|
|
136
|
+
breachedPasswordDetection: {
|
|
137
|
+
enabled: true,
|
|
138
|
+
shields: ["user_notification"],
|
|
139
|
+
admin_notification_frequency: ["daily"],
|
|
140
|
+
method: "invalid_method",
|
|
141
|
+
stage: {
|
|
142
|
+
"pre-user-registration": {
|
|
143
|
+
shields: ["block"],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
checkBreachedPassword(options, (report) => {
|
|
151
|
+
expect(report).to.deep.include({
|
|
152
|
+
field: "method_invalid_value",
|
|
153
|
+
status: CONSTANTS.FAIL,
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("should return failure when pre-user-registration stage is missing or incorrectly configured", function () {
|
|
159
|
+
const options = {
|
|
160
|
+
attackProtection: {
|
|
161
|
+
breachedPasswordDetection: {
|
|
162
|
+
enabled: true,
|
|
163
|
+
shields: ["user_notification"],
|
|
164
|
+
admin_notification_frequency: ["daily"],
|
|
165
|
+
method: "standard",
|
|
166
|
+
stage: {},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
checkBreachedPassword(options, (report) => {
|
|
172
|
+
expect(report).to.deep.include({
|
|
173
|
+
field: "stage_pre_user_missing",
|
|
174
|
+
status: CONSTANTS.FAIL,
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("should return failure when pre-user-registration shields are not configured", function () {
|
|
180
|
+
const options = {
|
|
181
|
+
attackProtection: {
|
|
182
|
+
breachedPasswordDetection: {
|
|
183
|
+
enabled: true,
|
|
184
|
+
shields: ["user_notification"],
|
|
185
|
+
admin_notification_frequency: ["daily"],
|
|
186
|
+
method: "standard",
|
|
187
|
+
stage: {
|
|
188
|
+
"pre-user-registration": {
|
|
189
|
+
shields: [],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
checkBreachedPassword(options, (report) => {
|
|
197
|
+
expect(report).to.deep.include({
|
|
198
|
+
field: "stage_pre_user_shields_not_configured",
|
|
199
|
+
status: CONSTANTS.FAIL,
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("should return failure when pre-change-password shields are not configured", function () {
|
|
205
|
+
const options = {
|
|
206
|
+
attackProtection: {
|
|
207
|
+
breachedPasswordDetection: {
|
|
208
|
+
enabled: true,
|
|
209
|
+
shields: ["user_notification"],
|
|
210
|
+
admin_notification_frequency: ["daily"],
|
|
211
|
+
method: "standard",
|
|
212
|
+
stage: {
|
|
213
|
+
"pre-change-password": {
|
|
214
|
+
shields: [],
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
checkBreachedPassword(options, (report) => {
|
|
222
|
+
expect(report).to.deep.include({
|
|
223
|
+
field: "stage_pre_change_password_shields_not_configured",
|
|
224
|
+
status: CONSTANTS.FAIL,
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("should return failure if shields are empty but monitoring mode is enabled", function () {
|
|
230
|
+
const options = {
|
|
231
|
+
attackProtection: {
|
|
232
|
+
breachedPasswordDetection: {
|
|
233
|
+
enabled: true,
|
|
234
|
+
shields: [],
|
|
235
|
+
admin_notification_frequency: ["daily"],
|
|
236
|
+
method: "standard",
|
|
237
|
+
stage: {
|
|
238
|
+
"pre-user-registration": {
|
|
239
|
+
shields: ["block"],
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
checkBreachedPassword(options, (report) => {
|
|
247
|
+
expect(report).to.deep.include({
|
|
248
|
+
field: "monitoring_mode",
|
|
249
|
+
status: CONSTANTS.FAIL,
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|