verification-layer 0.27.7 → 0.27.9
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/dist/rule-catalog.json +2 -2
- package/dist/scanners/authentication/index.js +25 -5
- package/dist/scanners/authentication/index.js.map +1 -1
- package/dist/scanners/authentication/patterns.d.ts +5 -1
- package/dist/scanners/authentication/patterns.d.ts.map +1 -1
- package/dist/scanners/authentication/patterns.js +6 -5
- package/dist/scanners/authentication/patterns.js.map +1 -1
- package/dist/scanners/authentication/supabase-admin-client.test.d.ts +2 -0
- package/dist/scanners/authentication/supabase-admin-client.test.d.ts.map +1 -0
- package/dist/scanners/authentication/supabase-admin-client.test.js +38 -0
- package/dist/scanners/authentication/supabase-admin-client.test.js.map +1 -0
- package/dist/scanners/authentication/supabase-callsite.test.d.ts +2 -0
- package/dist/scanners/authentication/supabase-callsite.test.d.ts.map +1 -0
- package/dist/scanners/authentication/supabase-callsite.test.js +34 -0
- package/dist/scanners/authentication/supabase-callsite.test.js.map +1 -0
- package/package.json +1 -1
package/dist/rule-catalog.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "verification-layer",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.9",
|
|
4
4
|
"total": 143,
|
|
5
5
|
"counts": {
|
|
6
6
|
"phi-exposure": 29,
|
|
@@ -663,7 +663,7 @@
|
|
|
663
663
|
"severity": "critical",
|
|
664
664
|
"title": "Authentication Configuration Without MFA Enabled",
|
|
665
665
|
"description": "Auth provider configuration (NextAuth, Clerk, Auth0, Supabase) does not have MFA/2FA/TOTP enabled",
|
|
666
|
-
"recommendation": "Enable MFA in your auth provider configuration. For NextAuth: add adapter with MFA support. For Clerk: enable MFA in dashboard. For Auth0: enable MFA in tenant settings. For Supabase
|
|
666
|
+
"recommendation": "Enable MFA in your auth provider configuration. For NextAuth: add adapter with MFA support. For Clerk: enable MFA in dashboard. For Auth0: enable MFA in tenant settings. For Supabase, verify MFA policy at the project/provider configuration level rather than inferring it from runtime auth calls.",
|
|
667
667
|
"hipaaReference": "NPRM §164.312(d) - Person or Entity Authentication",
|
|
668
668
|
"source": "pattern",
|
|
669
669
|
"scanner": "authentication"
|
|
@@ -67,13 +67,26 @@ export const authenticationScanner = {
|
|
|
67
67
|
* Scan auth configuration files for missing MFA
|
|
68
68
|
*/
|
|
69
69
|
async function scanAuthConfig(file, content, lines, pattern, findings) {
|
|
70
|
+
// A Supabase SDK client is used for database/storage/admin operations as well
|
|
71
|
+
// as authentication, so createClient() alone is not auth configuration evidence.
|
|
72
|
+
// Preserve the existing auth-config heuristic only when the file itself is
|
|
73
|
+
// auth-oriented or actually invokes a Supabase auth API. This prevents service-
|
|
74
|
+
// role clients in webhooks/background jobs from being mislabeled as missing MFA.
|
|
75
|
+
const hasDirectSupabaseSdkImport = /(?:from\s+['"]@supabase\/supabase-js['"]|require\(\s*['"]@supabase\/supabase-js['"]\s*\))/i.test(content);
|
|
76
|
+
const hasDirectClientConstruction = lines.some((line) => !isImportLine(line) && /createClient\s*\(/i.test(line));
|
|
77
|
+
const hasSupabaseAuthUsage = /\bsupabase\w*\.auth\./i.test(content);
|
|
78
|
+
const hasAuthOrSupabaseConfigFilename = /(?:^|[\\/])(?:auth|supabase(?:-config)?)(?:[.\\/_-]|$)/i.test(file);
|
|
79
|
+
const supabaseClientConfig = hasDirectSupabaseSdkImport &&
|
|
80
|
+
hasDirectClientConstruction &&
|
|
81
|
+
(hasSupabaseAuthUsage || hasAuthOrSupabaseConfigFilename);
|
|
70
82
|
// Check if this is an auth-related file
|
|
71
83
|
const isAuthFile = /(?:auth|clerk|supabase|next-auth)/i.test(file) ||
|
|
72
|
-
pattern.patterns.some((p) => p.test(content))
|
|
84
|
+
pattern.patterns.some((p) => p.test(content)) ||
|
|
85
|
+
supabaseClientConfig;
|
|
73
86
|
if (!isAuthFile)
|
|
74
87
|
return;
|
|
75
88
|
// Check if file has any auth provider configuration
|
|
76
|
-
const hasAuthConfig = pattern.patterns.some((p) => p.test(content));
|
|
89
|
+
const hasAuthConfig = pattern.patterns.some((p) => p.test(content)) || supabaseClientConfig;
|
|
77
90
|
if (!hasAuthConfig)
|
|
78
91
|
return;
|
|
79
92
|
// Check if MFA is configured
|
|
@@ -81,9 +94,7 @@ async function scanAuthConfig(file, content, lines, pattern, findings) {
|
|
|
81
94
|
if (hasMfaConfig)
|
|
82
95
|
return;
|
|
83
96
|
// Find the line with auth configuration. Skip import/require lines — anchoring
|
|
84
|
-
// an "auth config without MFA" finding to an
|
|
85
|
-
// '@supabase/...'` line is a false-positive-looking trigger. If the only
|
|
86
|
-
// evidence is an import, don't fire at all.
|
|
97
|
+
// an "auth config without MFA" finding to an import line is misleading.
|
|
87
98
|
let configLine = 0;
|
|
88
99
|
for (let i = 0; i < lines.length; i++) {
|
|
89
100
|
if (isImportLine(lines[i]))
|
|
@@ -93,6 +104,15 @@ async function scanAuthConfig(file, content, lines, pattern, findings) {
|
|
|
93
104
|
break;
|
|
94
105
|
}
|
|
95
106
|
}
|
|
107
|
+
// For direct Supabase auth config, anchor the finding to the client constructor.
|
|
108
|
+
if (configLine === 0 && supabaseClientConfig) {
|
|
109
|
+
for (let i = 0; i < lines.length; i++) {
|
|
110
|
+
if (/createClient\s*\(/i.test(lines[i]) && !isImportLine(lines[i])) {
|
|
111
|
+
configLine = i + 1;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
96
116
|
if (configLine === 0)
|
|
97
117
|
return;
|
|
98
118
|
// Create finding for auth config without MFA
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/authentication/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/authentication/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,11 @@ export interface MFAPattern {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* MFA-001: Auth Provider Configuration Without MFA
|
|
18
|
-
* Detects
|
|
18
|
+
* Detects code-local auth provider configuration without MFA enabled.
|
|
19
|
+
*
|
|
20
|
+
* Supabase runtime calls such as `supabase.auth.signUp()` are intentionally
|
|
21
|
+
* excluded. Supabase configuration is handled in the scanner with stronger
|
|
22
|
+
* evidence: a direct client construction that contains a Supabase project URL.
|
|
19
23
|
*/
|
|
20
24
|
export declare const AUTH_CONFIG_NO_MFA: MFAPattern;
|
|
21
25
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../src/scanners/authentication/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../src/scanners/authentication/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,UAyChC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,UAmCpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,UA2CxB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UAAU,EAIxC,CAAC"}
|
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
6
|
* MFA-001: Auth Provider Configuration Without MFA
|
|
7
|
-
* Detects
|
|
7
|
+
* Detects code-local auth provider configuration without MFA enabled.
|
|
8
|
+
*
|
|
9
|
+
* Supabase runtime calls such as `supabase.auth.signUp()` are intentionally
|
|
10
|
+
* excluded. Supabase configuration is handled in the scanner with stronger
|
|
11
|
+
* evidence: a direct client construction that contains a Supabase project URL.
|
|
8
12
|
*/
|
|
9
13
|
export const AUTH_CONFIG_NO_MFA = {
|
|
10
14
|
id: 'MFA-001',
|
|
@@ -24,9 +28,6 @@ export const AUTH_CONFIG_NO_MFA = {
|
|
|
24
28
|
/Auth0Provider/i,
|
|
25
29
|
/auth0\.WebAuth/i,
|
|
26
30
|
/new\s+Auth0Client/i,
|
|
27
|
-
// Supabase Auth configuration
|
|
28
|
-
/supabase\.auth\.signUp/i,
|
|
29
|
-
/createClient.*?supabase/i,
|
|
30
31
|
// Generic auth configs
|
|
31
32
|
/authConfig\s*[:=]/i,
|
|
32
33
|
/authentication\s*:\s*\{/i,
|
|
@@ -43,7 +44,7 @@ export const AUTH_CONFIG_NO_MFA = {
|
|
|
43
44
|
/two[-_]factor/i,
|
|
44
45
|
/authenticator/i,
|
|
45
46
|
],
|
|
46
|
-
recommendation: 'Enable MFA in your auth provider configuration. For NextAuth: add adapter with MFA support. For Clerk: enable MFA in dashboard. For Auth0: enable MFA in tenant settings. For Supabase
|
|
47
|
+
recommendation: 'Enable MFA in your auth provider configuration. For NextAuth: add adapter with MFA support. For Clerk: enable MFA in dashboard. For Auth0: enable MFA in tenant settings. For Supabase, verify MFA policy at the project/provider configuration level rather than inferring it from runtime auth calls.',
|
|
47
48
|
category: 'authentication',
|
|
48
49
|
};
|
|
49
50
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/scanners/authentication/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/scanners/authentication/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC5C,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,kDAAkD;IACxD,WAAW,EACT,mGAAmG;IACrG,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,oDAAoD;IACpE,QAAQ,EAAE;QACR,yBAAyB;QACzB,gBAAgB;QAChB,mCAAmC;QACnC,qBAAqB;QAErB,sBAAsB;QACtB,gBAAgB;QAChB,6BAA6B;QAE7B,sBAAsB;QACtB,gBAAgB;QAChB,iBAAiB;QACjB,oBAAoB;QAEpB,uBAAuB;QACvB,oBAAoB;QACpB,0BAA0B;KAC3B;IACD,gBAAgB,EAAE;QAChB,iCAAiC;QACjC,MAAM;QACN,MAAM;QACN,OAAO;QACP,MAAM;QACN,cAAc;QACd,kBAAkB;QAClB,YAAY;QACZ,gBAAgB;QAChB,gBAAgB;KACjB;IACD,cAAc,EACZ,ySAAyS;IAC3S,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAe;IAChD,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,iDAAiD;IACvD,WAAW,EACT,4GAA4G;IAC9G,QAAQ,EAAE,MAAM;IAChB,cAAc,EAAE,oDAAoD;IACpE,QAAQ,EAAE;QACR,6BAA6B;QAC7B,yEAAyE;QACzE,qFAAqF;QAErF,qCAAqC;QACrC,kEAAkE;QAElE,iCAAiC;QACjC,yCAAyC;QACzC,yCAAyC;KAC1C;IACD,gBAAgB,EAAE;QAChB,iCAAiC;QACjC,WAAW;QACX,WAAW;QACX,mBAAmB;QACnB,gBAAgB;QAChB,oBAAoB;QACpB,MAAM;QACN,cAAc;QACd,aAAa;QACb,WAAW;QACX,YAAY;KACb;IACD,cAAc,EACZ,yNAAyN;IAC3N,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAe;IACpC,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,6BAA6B;IACnC,WAAW,EACT,+DAA+D;IACjE,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,oDAAoD;IACpE,QAAQ,EAAE;QACR,4BAA4B;QAC5B,UAAU;QACV,YAAY;QACZ,aAAa;QACb,YAAY;QAEZ,yBAAyB;QACzB,4BAA4B;QAC5B,4BAA4B;QAC5B,wCAAwC;QACxC,qCAAqC;QACrC,wBAAwB;QAExB,qBAAqB;QACrB,wBAAwB;QACxB,kCAAkC;QAElC,iDAAiD;QACjD,6CAA6C;KAC9C;IACD,gBAAgB,EAAE;QAChB,4CAA4C;QAC5C,aAAa;QACb,aAAa;QACb,aAAa;QACb,OAAO;QACP,SAAS;QACT,WAAW;QACX,WAAW;QACX,8BAA8B;QAC9B,eAAe;KAChB;IACD,cAAc,EACZ,2KAA2K;IAC7K,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,kBAAkB;IAClB,sBAAsB;IACtB,UAAU;CACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase-admin-client.test.d.ts","sourceRoot":"","sources":["../../../src/scanners/authentication/supabase-admin-client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { authenticationScanner } from './index.js';
|
|
3
|
+
import * as fs from 'fs/promises';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as os from 'os';
|
|
6
|
+
describe('MFA-001 Supabase non-auth client precision', () => {
|
|
7
|
+
let tempDir = '';
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'mfa-supabase-admin-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
const options = () => ({ path: tempDir });
|
|
15
|
+
it('does not flag a service-role Supabase client used only for database operations', async () => {
|
|
16
|
+
const routeDir = path.join(tempDir, 'app', 'api', 'stripe', 'webhook');
|
|
17
|
+
await fs.mkdir(routeDir, { recursive: true });
|
|
18
|
+
const file = path.join(routeDir, 'route.ts');
|
|
19
|
+
await fs.writeFile(file, `
|
|
20
|
+
import { createClient } from '@supabase/supabase-js';
|
|
21
|
+
|
|
22
|
+
function getSupabaseAdmin() {
|
|
23
|
+
return createClient(
|
|
24
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL || '',
|
|
25
|
+
process.env.SUPABASE_SERVICE_ROLE_KEY || ''
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function POST() {
|
|
30
|
+
const supabaseAdmin = getSupabaseAdmin();
|
|
31
|
+
await supabaseAdmin.from('profiles').update({ plan: 'pro' }).eq('id', '123');
|
|
32
|
+
}
|
|
33
|
+
`, 'utf-8');
|
|
34
|
+
const findings = await authenticationScanner.scan([file], options());
|
|
35
|
+
expect(findings.filter((f) => f.id === 'MFA-001')).toHaveLength(0);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=supabase-admin-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase-admin-client.test.js","sourceRoot":"","sources":["../../../src/scanners/authentication/supabase-admin-client.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;IAC1D,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,GAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAEvD,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAC9F,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QACvE,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC7C,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,EACJ;;;;;;;;;;;;;;CAcL,EACK,OAAO,CACR,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase-callsite.test.d.ts","sourceRoot":"","sources":["../../../src/scanners/authentication/supabase-callsite.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { authenticationScanner } from './index.js';
|
|
3
|
+
import * as fs from 'fs/promises';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as os from 'os';
|
|
6
|
+
describe('MFA-001 Supabase call-site precision', () => {
|
|
7
|
+
let tempDir = '';
|
|
8
|
+
afterEach(async () => {
|
|
9
|
+
if (tempDir) {
|
|
10
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
it('does not treat a shared-client signup route as provider MFA configuration', async () => {
|
|
14
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'supabase-callsite-'));
|
|
15
|
+
const file = path.join(tempDir, 'route.ts');
|
|
16
|
+
await fs.writeFile(file, `
|
|
17
|
+
import { createClient } from '@/lib/supabase/server';
|
|
18
|
+
|
|
19
|
+
export async function POST(req: Request) {
|
|
20
|
+
const supabase = await createClient();
|
|
21
|
+
const { data, error } = await supabase.auth.signUp({
|
|
22
|
+
email: 'user@example.com',
|
|
23
|
+
password: 'example-password',
|
|
24
|
+
});
|
|
25
|
+
return Response.json({ data, error });
|
|
26
|
+
}
|
|
27
|
+
`, 'utf-8');
|
|
28
|
+
const options = { path: tempDir };
|
|
29
|
+
const findings = await authenticationScanner.scan([file], options);
|
|
30
|
+
const mfaConfigFindings = findings.filter((finding) => finding.id === 'MFA-001');
|
|
31
|
+
expect(mfaConfigFindings).toHaveLength(0);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=supabase-callsite.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase-callsite.test.js","sourceRoot":"","sources":["../../../src/scanners/authentication/supabase-callsite.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAE5C,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,EACJ;;;;;;;;;;;CAWL,EACK,OAAO,CACR,CAAC;QAEF,MAAM,OAAO,GAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAEjF,MAAM,CAAC,iBAAiB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "verification-layer",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.9",
|
|
4
4
|
"description": "Open-source HIPAA compliance scanner for healthcare code. 143 rules, 5 HIPAA categories. CLI + CI/CD + VS Code.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|