insa-check-core 0.1.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/LICENSE +24 -0
- package/dist/annex-b.d.ts +6 -0
- package/dist/annex-b.d.ts.map +1 -0
- package/dist/annex-b.js +152 -0
- package/dist/annex-b.js.map +1 -0
- package/dist/checks/content/page.d.ts +7 -0
- package/dist/checks/content/page.d.ts.map +1 -0
- package/dist/checks/content/page.js +133 -0
- package/dist/checks/content/page.js.map +1 -0
- package/dist/checks/cookies/cookie-flags.d.ts +3 -0
- package/dist/checks/cookies/cookie-flags.d.ts.map +1 -0
- package/dist/checks/cookies/cookie-flags.js +41 -0
- package/dist/checks/cookies/cookie-flags.js.map +1 -0
- package/dist/checks/cookies/cookie-scope.d.ts +6 -0
- package/dist/checks/cookies/cookie-scope.d.ts.map +1 -0
- package/dist/checks/cookies/cookie-scope.js +60 -0
- package/dist/checks/cookies/cookie-scope.js.map +1 -0
- package/dist/checks/deployment/server-banner.d.ts +4 -0
- package/dist/checks/deployment/server-banner.d.ts.map +1 -0
- package/dist/checks/deployment/server-banner.js +60 -0
- package/dist/checks/deployment/server-banner.js.map +1 -0
- package/dist/checks/deployment/trace.d.ts +3 -0
- package/dist/checks/deployment/trace.d.ts.map +1 -0
- package/dist/checks/deployment/trace.js +30 -0
- package/dist/checks/deployment/trace.js.map +1 -0
- package/dist/checks/headers/clickjacking.d.ts +5 -0
- package/dist/checks/headers/clickjacking.d.ts.map +1 -0
- package/dist/checks/headers/clickjacking.js +57 -0
- package/dist/checks/headers/clickjacking.js.map +1 -0
- package/dist/checks/headers/content-type-options.d.ts +3 -0
- package/dist/checks/headers/content-type-options.d.ts.map +1 -0
- package/dist/checks/headers/content-type-options.js +17 -0
- package/dist/checks/headers/content-type-options.js.map +1 -0
- package/dist/checks/headers/cors.d.ts +4 -0
- package/dist/checks/headers/cors.d.ts.map +1 -0
- package/dist/checks/headers/cors.js +38 -0
- package/dist/checks/headers/cors.js.map +1 -0
- package/dist/checks/html.d.ts +11 -0
- package/dist/checks/html.d.ts.map +1 -0
- package/dist/checks/html.js +30 -0
- package/dist/checks/html.js.map +1 -0
- package/dist/checks/index.d.ts +7 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +48 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/checks/info-disclosure/directory-listing.d.ts +6 -0
- package/dist/checks/info-disclosure/directory-listing.d.ts.map +1 -0
- package/dist/checks/info-disclosure/directory-listing.js +60 -0
- package/dist/checks/info-disclosure/directory-listing.js.map +1 -0
- package/dist/checks/info-disclosure/exposed-files.d.ts +4 -0
- package/dist/checks/info-disclosure/exposed-files.d.ts.map +1 -0
- package/dist/checks/info-disclosure/exposed-files.js +56 -0
- package/dist/checks/info-disclosure/exposed-files.js.map +1 -0
- package/dist/checks/info-disclosure/more.d.ts +8 -0
- package/dist/checks/info-disclosure/more.d.ts.map +1 -0
- package/dist/checks/info-disclosure/more.js +186 -0
- package/dist/checks/info-disclosure/more.js.map +1 -0
- package/dist/checks/tls/certificate.d.ts +3 -0
- package/dist/checks/tls/certificate.d.ts.map +1 -0
- package/dist/checks/tls/certificate.js +49 -0
- package/dist/checks/tls/certificate.js.map +1 -0
- package/dist/checks/tls/hsts.d.ts +5 -0
- package/dist/checks/tls/hsts.d.ts.map +1 -0
- package/dist/checks/tls/hsts.js +35 -0
- package/dist/checks/tls/hsts.js.map +1 -0
- package/dist/checks/tls/https-redirect.d.ts +3 -0
- package/dist/checks/tls/https-redirect.d.ts.map +1 -0
- package/dist/checks/tls/https-redirect.js +46 -0
- package/dist/checks/tls/https-redirect.js.map +1 -0
- package/dist/checks/tls/legacy-protocols.d.ts +3 -0
- package/dist/checks/tls/legacy-protocols.d.ts.map +1 -0
- package/dist/checks/tls/legacy-protocols.js +27 -0
- package/dist/checks/tls/legacy-protocols.js.map +1 -0
- package/dist/checks/util.d.ts +22 -0
- package/dist/checks/util.d.ts.map +1 -0
- package/dist/checks/util.js +63 -0
- package/dist/checks/util.js.map +1 -0
- package/dist/code/checks/crypto.d.ts +5 -0
- package/dist/code/checks/crypto.d.ts.map +1 -0
- package/dist/code/checks/crypto.js +100 -0
- package/dist/code/checks/crypto.js.map +1 -0
- package/dist/code/checks/django.d.ts +14 -0
- package/dist/code/checks/django.d.ts.map +1 -0
- package/dist/code/checks/django.js +313 -0
- package/dist/code/checks/django.js.map +1 -0
- package/dist/code/checks/flask.d.ts +6 -0
- package/dist/code/checks/flask.d.ts.map +1 -0
- package/dist/code/checks/flask.js +100 -0
- package/dist/code/checks/flask.js.map +1 -0
- package/dist/code/checks/index.d.ts +9 -0
- package/dist/code/checks/index.d.ts.map +1 -0
- package/dist/code/checks/index.js +126 -0
- package/dist/code/checks/index.js.map +1 -0
- package/dist/code/checks/injection.d.ts +27 -0
- package/dist/code/checks/injection.d.ts.map +1 -0
- package/dist/code/checks/injection.js +189 -0
- package/dist/code/checks/injection.js.map +1 -0
- package/dist/code/checks/javascript-config.d.ts +14 -0
- package/dist/code/checks/javascript-config.d.ts.map +1 -0
- package/dist/code/checks/javascript-config.js +251 -0
- package/dist/code/checks/javascript-config.js.map +1 -0
- package/dist/code/checks/javascript.d.ts +34 -0
- package/dist/code/checks/javascript.d.ts.map +1 -0
- package/dist/code/checks/javascript.js +333 -0
- package/dist/code/checks/javascript.js.map +1 -0
- package/dist/code/checks/php.d.ts +27 -0
- package/dist/code/checks/php.d.ts.map +1 -0
- package/dist/code/checks/php.js +433 -0
- package/dist/code/checks/php.js.map +1 -0
- package/dist/code/checks/secrets.d.ts +10 -0
- package/dist/code/checks/secrets.d.ts.map +1 -0
- package/dist/code/checks/secrets.js +140 -0
- package/dist/code/checks/secrets.js.map +1 -0
- package/dist/code/checks/shared.d.ts +25 -0
- package/dist/code/checks/shared.d.ts.map +1 -0
- package/dist/code/checks/shared.js +57 -0
- package/dist/code/checks/shared.js.map +1 -0
- package/dist/code/checks/treesitter.d.ts +15 -0
- package/dist/code/checks/treesitter.d.ts.map +1 -0
- package/dist/code/checks/treesitter.js +322 -0
- package/dist/code/checks/treesitter.js.map +1 -0
- package/dist/code/checks/xml.d.ts +9 -0
- package/dist/code/checks/xml.d.ts.map +1 -0
- package/dist/code/checks/xml.js +78 -0
- package/dist/code/checks/xml.js.map +1 -0
- package/dist/code/context.d.ts +6 -0
- package/dist/code/context.d.ts.map +1 -0
- package/dist/code/context.js +92 -0
- package/dist/code/context.js.map +1 -0
- package/dist/code/detect.d.ts +3 -0
- package/dist/code/detect.d.ts.map +1 -0
- package/dist/code/detect.js +118 -0
- package/dist/code/detect.js.map +1 -0
- package/dist/code/django/settings.d.ts +46 -0
- package/dist/code/django/settings.d.ts.map +1 -0
- package/dist/code/django/settings.js +154 -0
- package/dist/code/django/settings.js.map +1 -0
- package/dist/code/findings.d.ts +18 -0
- package/dist/code/findings.d.ts.map +1 -0
- package/dist/code/findings.js +63 -0
- package/dist/code/findings.js.map +1 -0
- package/dist/code/javascript/ast.d.ts +46 -0
- package/dist/code/javascript/ast.d.ts.map +1 -0
- package/dist/code/javascript/ast.js +166 -0
- package/dist/code/javascript/ast.js.map +1 -0
- package/dist/code/javascript/index.d.ts +3 -0
- package/dist/code/javascript/index.d.ts.map +1 -0
- package/dist/code/javascript/index.js +3 -0
- package/dist/code/javascript/index.js.map +1 -0
- package/dist/code/javascript/module.d.ts +59 -0
- package/dist/code/javascript/module.d.ts.map +1 -0
- package/dist/code/javascript/module.js +250 -0
- package/dist/code/javascript/module.js.map +1 -0
- package/dist/code/php/index.d.ts +92 -0
- package/dist/code/php/index.d.ts.map +1 -0
- package/dist/code/php/index.js +316 -0
- package/dist/code/php/index.js.map +1 -0
- package/dist/code/project.d.ts +13 -0
- package/dist/code/project.d.ts.map +1 -0
- package/dist/code/project.js +69 -0
- package/dist/code/project.js.map +1 -0
- package/dist/code/python/ast.d.ts +47 -0
- package/dist/code/python/ast.d.ts.map +1 -0
- package/dist/code/python/ast.js +193 -0
- package/dist/code/python/ast.js.map +1 -0
- package/dist/code/python/index.d.ts +3 -0
- package/dist/code/python/index.d.ts.map +1 -0
- package/dist/code/python/index.js +3 -0
- package/dist/code/python/index.js.map +1 -0
- package/dist/code/python/module.d.ts +55 -0
- package/dist/code/python/module.d.ts.map +1 -0
- package/dist/code/python/module.js +215 -0
- package/dist/code/python/module.js.map +1 -0
- package/dist/code/scan.d.ts +24 -0
- package/dist/code/scan.d.ts.map +1 -0
- package/dist/code/scan.js +159 -0
- package/dist/code/scan.js.map +1 -0
- package/dist/code/treesitter/index.d.ts +83 -0
- package/dist/code/treesitter/index.d.ts.map +1 -0
- package/dist/code/treesitter/index.js +243 -0
- package/dist/code/treesitter/index.js.map +1 -0
- package/dist/code/types.d.ts +48 -0
- package/dist/code/types.d.ts.map +1 -0
- package/dist/code/types.js +2 -0
- package/dist/code/types.js.map +1 -0
- package/dist/content/en.d.ts +3 -0
- package/dist/content/en.d.ts.map +1 -0
- package/dist/content/en.js +722 -0
- package/dist/content/en.js.map +1 -0
- package/dist/content/index.d.ts +15 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +21 -0
- package/dist/content/index.js.map +1 -0
- package/dist/content/types.d.ts +87 -0
- package/dist/content/types.d.ts.map +1 -0
- package/dist/content/types.js +2 -0
- package/dist/content/types.js.map +1 -0
- package/dist/engine.d.ts +52 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +120 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/meta.d.ts +4 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +4 -0
- package/dist/meta.js.map +1 -0
- package/dist/net/context.d.ts +9 -0
- package/dist/net/context.d.ts.map +1 -0
- package/dist/net/context.js +62 -0
- package/dist/net/context.js.map +1 -0
- package/dist/net/guard.d.ts +16 -0
- package/dist/net/guard.d.ts.map +1 -0
- package/dist/net/guard.js +70 -0
- package/dist/net/guard.js.map +1 -0
- package/dist/net/http.d.ts +22 -0
- package/dist/net/http.d.ts.map +1 -0
- package/dist/net/http.js +114 -0
- package/dist/net/http.js.map +1 -0
- package/dist/net/tls.d.ts +15 -0
- package/dist/net/tls.d.ts.map +1 -0
- package/dist/net/tls.js +103 -0
- package/dist/net/tls.js.map +1 -0
- package/dist/report/html.d.ts +14 -0
- package/dist/report/html.d.ts.map +1 -0
- package/dist/report/html.js +210 -0
- package/dist/report/html.js.map +1 -0
- package/dist/report/index.d.ts +10 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +10 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/manual.d.ts +62 -0
- package/dist/report/manual.d.ts.map +1 -0
- package/dist/report/manual.js +190 -0
- package/dist/report/manual.js.map +1 -0
- package/dist/report/merge.d.ts +8 -0
- package/dist/report/merge.d.ts.map +1 -0
- package/dist/report/merge.js +135 -0
- package/dist/report/merge.js.map +1 -0
- package/dist/report/summary.d.ts +10 -0
- package/dist/report/summary.d.ts.map +1 -0
- package/dist/report/summary.js +27 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/validate.d.ts +3 -0
- package/dist/report/validate.d.ts.map +1 -0
- package/dist/report/validate.js +78 -0
- package/dist/report/validate.js.map +1 -0
- package/dist/types.d.ts +244 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +4 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +24 -0
- package/dist/validate.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import { locations, NO_PATTERN, outcomeFromFindings, snippetOf } from "../findings.js";
|
|
2
|
+
import { isPhpDynamicString, isPhpLiteral, isPhpNode, phpArgs, phpDotted, phpIdentifiers, phpString, walkPhp, } from "../php/index.js";
|
|
3
|
+
import { looksSecret, SECRET_ASSIGN, SECRET_DICT_KEY } from "./secrets.js";
|
|
4
|
+
import { codeCheck, PASSWORD_IDENT, SECRET_IDENT, SECURITY_CONTEXT } from "./shared.js";
|
|
5
|
+
/** Pattern rules for any PHP code, and configuration rules for Laravel. */
|
|
6
|
+
const LANG = "PHP";
|
|
7
|
+
function phpFinding(module, node, rule, confidence, why) {
|
|
8
|
+
const line = module.lineOf(node);
|
|
9
|
+
return { file: module.path, line, snippet: snippetOf(module.line(line)), why, confidence, method: "ast", rule };
|
|
10
|
+
}
|
|
11
|
+
function phpPatternCheck(key, find, what) {
|
|
12
|
+
return codeCheck(key, ["php"], async (ctx) => {
|
|
13
|
+
const index = await ctx.php();
|
|
14
|
+
return outcomeFromFindings(await find(index, ctx), NO_PATTERN(what, index.modules.length, LANG));
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/** Same scale as the Python and JavaScript rules: direct request data = high, derived/built = medium, unknown = low. */
|
|
18
|
+
function phpArgRisk(site, arg, opts = {}) {
|
|
19
|
+
if (!arg || isPhpLiteral(arg))
|
|
20
|
+
return undefined;
|
|
21
|
+
const scope = site.module.scope(site.fn);
|
|
22
|
+
if (site.module.isRequestDerived(arg))
|
|
23
|
+
return "high";
|
|
24
|
+
const derived = site.module.isRequestDerived(arg, scope);
|
|
25
|
+
if (opts.requestOnly && !derived)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (isPhpDynamicString(arg))
|
|
28
|
+
return derived ? "high" : "medium";
|
|
29
|
+
if (derived)
|
|
30
|
+
return "medium";
|
|
31
|
+
if (arg.kind === "variable" && scope?.dynamicStrings.has(arg["name"]))
|
|
32
|
+
return "medium";
|
|
33
|
+
return opts.unknownIsLow === false ? undefined : "low";
|
|
34
|
+
}
|
|
35
|
+
function sinkFindings(sites, match, rule, why, opts = {}) {
|
|
36
|
+
const out = [];
|
|
37
|
+
for (const site of sites) {
|
|
38
|
+
const m = match(site);
|
|
39
|
+
if (!m)
|
|
40
|
+
continue;
|
|
41
|
+
const risks = (Array.isArray(m) ? m : [m]).map((a) => phpArgRisk(site, a, opts)).filter((r) => !!r);
|
|
42
|
+
if (risks.length === 0)
|
|
43
|
+
continue;
|
|
44
|
+
out.push(phpFinding(site.module, site.node, rule, risks.includes("high") ? "high" : risks.includes("medium") ? "medium" : "low", why));
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
const arg = (s, i = 0) => phpArgs(s.node)[i];
|
|
49
|
+
const fnName = (s) => (s.name ?? "").toLowerCase();
|
|
50
|
+
const allNodes = function* (index) {
|
|
51
|
+
for (const module of index.modules)
|
|
52
|
+
for (const node of walkPhp(module.tree))
|
|
53
|
+
yield { module, node };
|
|
54
|
+
};
|
|
55
|
+
const lineText = (s) => s.module.line(s.module.lineOf(s.node));
|
|
56
|
+
// --- #6 Hard-coded secrets ------------------------------------------------------------
|
|
57
|
+
const VALIDATION_RULE = /\||^(required|nullable|sometimes|string|confirmed|present|filled)\b|^(min|max|size|between|regex|same|different):/;
|
|
58
|
+
const SECRET_WHY = "Credentials in source code leak through repositories, backups and builds; load them from the environment or a secret store.";
|
|
59
|
+
export const phpHardcodedSecrets = phpPatternCheck("php-hardcoded-secrets", (index) => {
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const { module, node } of allNodes(index)) {
|
|
62
|
+
if (node.kind === "assign") {
|
|
63
|
+
const name = (phpDotted(node["left"]) ?? "").split(/->|::|\$/).pop() ?? "";
|
|
64
|
+
if (SECRET_ASSIGN.test(name) && looksSecret(phpString(node["right"])))
|
|
65
|
+
out.push(phpFinding(module, node, "php-hardcoded-secret", "medium", SECRET_WHY));
|
|
66
|
+
}
|
|
67
|
+
else if (node.kind === "entry") {
|
|
68
|
+
const value = phpString(node["value"]);
|
|
69
|
+
// 'password' => 'required|min:12' is a validation rule, not a credential.
|
|
70
|
+
if (value && VALIDATION_RULE.test(value))
|
|
71
|
+
continue;
|
|
72
|
+
if (SECRET_DICT_KEY.test(phpString(node["key"]) ?? "") && looksSecret(value)) {
|
|
73
|
+
out.push(phpFinding(module, node, "php-hardcoded-secret", "medium", SECRET_WHY));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
for (const s of index.calls()) {
|
|
78
|
+
// define('DB_PASSWORD', 'literal')
|
|
79
|
+
if (fnName(s) === "define" && SECRET_ASSIGN.test(phpString(arg(s)) ?? "") && looksSecret(phpString(arg(s, 1)))) {
|
|
80
|
+
out.push(phpFinding(s.module, s.node, "php-hardcoded-secret", "medium", SECRET_WHY));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}, "hard-coded credentials");
|
|
85
|
+
// --- #19 / #20 Cryptography --------------------------------------------------------------
|
|
86
|
+
export const phpWeakCrypto = phpPatternCheck("php-weak-crypto", (index) => {
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const s of index.calls()) {
|
|
89
|
+
const name = fnName(s);
|
|
90
|
+
const alg = (phpString(arg(s)) ?? "").toLowerCase();
|
|
91
|
+
if (name === "md5" || name === "sha1" || (name === "hash" && (alg === "md5" || alg === "sha1"))) {
|
|
92
|
+
const security = SECURITY_CONTEXT.test(lineText(s));
|
|
93
|
+
out.push(phpFinding(s.module, s.node, "php-weak-hash", security ? "high" : "low", security ? "MD5/SHA-1 are broken for security purposes (collisions, fast brute force)." : "MD5/SHA-1 in use; acceptable only for non-security checksums. Confirm how it is used."));
|
|
94
|
+
}
|
|
95
|
+
else if (/^mcrypt_/.test(name)) {
|
|
96
|
+
out.push(phpFinding(s.module, s.node, "php-mcrypt", "high", "The mcrypt extension is abandoned and removed from PHP; use openssl or sodium."));
|
|
97
|
+
}
|
|
98
|
+
else if (/^openssl_(en|de)crypt$/.test(name) && /(^|-)(des|des3|des-ede3?|rc4|rc2|bf)(-|$)/.test((phpString(arg(s, 1)) ?? "").toLowerCase())) {
|
|
99
|
+
out.push(phpFinding(s.module, s.node, "php-weak-cipher", "high", "DES/3DES/RC4/Blowfish-class ciphers are deprecated and breakable."));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}, "use of weak hashes or ciphers");
|
|
104
|
+
export const phpCryptoMisuse = phpPatternCheck("php-crypto-misuse", (index) => {
|
|
105
|
+
const out = [];
|
|
106
|
+
for (const s of index.calls()) {
|
|
107
|
+
const name = fnName(s);
|
|
108
|
+
if (/^(rand|mt_rand|uniqid|lcg_value|str_shuffle)$/.test(name) && SECURITY_CONTEXT.test(lineText(s))) {
|
|
109
|
+
out.push(phpFinding(s.module, s.node, "php-insecure-random", "medium", "rand/mt_rand/uniqid are predictable; use random_bytes() or random_int() for tokens, passwords and keys."));
|
|
110
|
+
}
|
|
111
|
+
else if (/^openssl_(en|de)crypt$/.test(name) && /-ecb$/i.test(phpString(arg(s, 1)) ?? "")) {
|
|
112
|
+
out.push(phpFinding(s.module, s.node, "php-ecb-mode", "high", "ECB mode leaks plaintext patterns; use an authenticated mode such as GCM."));
|
|
113
|
+
}
|
|
114
|
+
else if (/^(md5|sha1|hash|crc32)$/.test(name) && phpArgs(s.node).some((a) => phpIdentifiers(a).some((i) => PASSWORD_IDENT.test(i)) || /['"]pass(word|wd)?['"]/i.test(s.module.text(a)))) {
|
|
115
|
+
out.push(phpFinding(s.module, s.node, "php-fast-password-hash", "high", "Passwords hashed with a fast, unsalted hash can be brute-forced; use password_hash()."));
|
|
116
|
+
}
|
|
117
|
+
else if (name === "curl_setopt" && /CURLOPT_SSL_VERIFY(PEER|HOST)/.test(phpDotted(arg(s, 1)) ?? "")) {
|
|
118
|
+
const v = arg(s, 2);
|
|
119
|
+
if (v && ((v.kind === "boolean" && v["value"] === false) || (v.kind === "number" && Number(v["value"]) === 0))) {
|
|
120
|
+
out.push(phpFinding(s.module, s.node, "php-curl-verify-off", "high", "Disabling certificate verification allows man-in-the-middle attacks."));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const { module, node } of allNodes(index)) {
|
|
125
|
+
// Guzzle: ['verify' => false]
|
|
126
|
+
if (node.kind === "entry" && phpString(node["key"]) === "verify") {
|
|
127
|
+
const v = node["value"];
|
|
128
|
+
if (v?.kind === "boolean" && v["value"] === false)
|
|
129
|
+
out.push(phpFinding(module, node, "php-guzzle-verify-off", "high", "'verify' => false disables TLS certificate verification."));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}, "cryptographic misuse (insecure randomness, ECB, fast password hashes, disabled TLS verification)");
|
|
134
|
+
// --- #34 Plaintext passwords ---------------------------------------------------------------
|
|
135
|
+
const HASHING = /password_hash|hash::make|bcrypt|hash\(|crypt\(|sodium_/i;
|
|
136
|
+
export const phpPlaintextPasswords = phpPatternCheck("php-plaintext-passwords", (index) => {
|
|
137
|
+
const out = [];
|
|
138
|
+
for (const { module, node } of allNodes(index)) {
|
|
139
|
+
if (node.kind === "assign") {
|
|
140
|
+
const left = node["left"];
|
|
141
|
+
const right = node["right"];
|
|
142
|
+
if (!["propertylookup", "offsetlookup"].includes(left.kind) || isPhpLiteral(right))
|
|
143
|
+
continue;
|
|
144
|
+
const name = (phpDotted(left) ?? "").split(/->|\[/).pop()?.replace("]", "") ?? "";
|
|
145
|
+
if (!PASSWORD_IDENT.test(name) || /hash|digest|salt/i.test(name) || HASHING.test(module.text(right)))
|
|
146
|
+
continue;
|
|
147
|
+
out.push(phpFinding(module, node, "php-plaintext-password-assign", module.isRequestDerived(right) ? "high" : "medium", "Assigning a raw value to a password field stores it unhashed; use password_hash() / Hash::make()."));
|
|
148
|
+
}
|
|
149
|
+
else if (node.kind === "entry") {
|
|
150
|
+
const key = phpString(node["key"]) ?? "";
|
|
151
|
+
const value = node["value"];
|
|
152
|
+
if (PASSWORD_IDENT.test(key) && isPhpNode(value) && module.isRequestDerived(value) && !HASHING.test(module.text(value))) {
|
|
153
|
+
out.push(phpFinding(module, node, "php-plaintext-password-stored", "medium", "A request password is passed on unhashed; if this array is saved, the password is stored in plaintext."));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else if (node.kind === "bin" && ["==", "===", "!=", "!=="].includes(node["type"])) {
|
|
157
|
+
const last = (x) => (phpDotted(x) ?? "").split(/->|\[|\$/).pop()?.replace("]", "") ?? "";
|
|
158
|
+
const [l, r] = [node["left"], node["right"]];
|
|
159
|
+
if (isPhpLiteral(l) || isPhpLiteral(r))
|
|
160
|
+
continue;
|
|
161
|
+
if (PASSWORD_IDENT.test(last(l)) && PASSWORD_IDENT.test(last(r)) && !/hash|confirm|repeat/i.test(module.text(node))) {
|
|
162
|
+
out.push(phpFinding(module, node, "php-plaintext-password-compare", "medium", "Comparing passwords directly implies they are stored in plaintext; use password_verify()."));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return out;
|
|
167
|
+
}, "plaintext password storage or comparison");
|
|
168
|
+
// --- #41 SQL injection ---------------------------------------------------------------------
|
|
169
|
+
const SQL_TEXT = /\b(select|insert|update|delete|where|from|values|drop|alter)\b/i;
|
|
170
|
+
const SQL_FUNCTION = { mysql_query: 0, mysqli_query: 1, pg_query: 1, sqlite_query: 1, mysqli_multi_query: 1, mysqli_real_query: 1 };
|
|
171
|
+
const SQL_RAW_METHOD = /^(whereRaw|orWhereRaw|selectRaw|orderByRaw|havingRaw|groupByRaw|fromRaw)$/;
|
|
172
|
+
const DB_FACADE = /(^|\\)DB::(select|insert|update|delete|statement|unprepared|raw|scalar)$/;
|
|
173
|
+
export const phpSqlInjection = phpPatternCheck("php-sql-injection", (index) => sinkFindings(index.calls(), (s) => {
|
|
174
|
+
const name = s.name ?? "";
|
|
175
|
+
const fnIndex = SQL_FUNCTION[fnName(s)];
|
|
176
|
+
if (fnIndex !== undefined)
|
|
177
|
+
return arg(s, fnIndex) ?? arg(s, 0);
|
|
178
|
+
if (DB_FACADE.test(name) || SQL_RAW_METHOD.test(s.method ?? ""))
|
|
179
|
+
return arg(s);
|
|
180
|
+
if (/->(query|exec|prepare|multi_query|real_query)$/.test(name)) {
|
|
181
|
+
const a = arg(s);
|
|
182
|
+
// Generic method names: a built string must look like SQL to count.
|
|
183
|
+
return a && (!isPhpDynamicString(a) || SQL_TEXT.test(s.module.text(a))) ? a : undefined;
|
|
184
|
+
}
|
|
185
|
+
return undefined;
|
|
186
|
+
}, "php-sql-string-building", "SQL built from strings can be manipulated by user input; use prepared statements with bound parameters."), "SQL built by string concatenation or interpolation");
|
|
187
|
+
// --- #44 OS command / #54 code injection ------------------------------------------------------
|
|
188
|
+
export const phpCommandInjection = phpPatternCheck("php-command-injection", (index) => sinkFindings(index.calls(), (s) => (/^(exec|shell_exec|system|passthru|popen|proc_open|pcntl_exec)$/.test(fnName(s)) ? arg(s) : undefined), "php-shell-command", "Running a shell command built from variables allows command injection; avoid the shell or use escapeshellarg()."), "OS command execution with variable input");
|
|
189
|
+
export const phpCodeInjection = phpPatternCheck("php-code-injection", (index) => {
|
|
190
|
+
const out = [
|
|
191
|
+
...sinkFindings(index.calls(), (s) => (/^(assert|create_function)$/.test(fnName(s)) ? arg(s) : undefined), "php-dynamic-code", "Evaluating variable input as code runs arbitrary PHP."),
|
|
192
|
+
...sinkFindings(index.calls(), (s) => (fnName(s) === "unserialize" ? arg(s) : undefined), "php-unserialize", "unserialize() on request data can instantiate arbitrary objects and run code; use JSON.", { requestOnly: true }),
|
|
193
|
+
];
|
|
194
|
+
for (const { module, node } of allNodes(index)) {
|
|
195
|
+
if (node.kind === "eval" && !isPhpLiteral(node["source"])) {
|
|
196
|
+
out.push(phpFinding(module, node, "php-eval", module.isRequestDerived(node["source"]) ? "high" : "medium", "eval() of non-constant input runs arbitrary PHP."));
|
|
197
|
+
}
|
|
198
|
+
else if (node.kind === "include" && module.isRequestDerived(node["target"])) {
|
|
199
|
+
out.push(phpFinding(module, node, "php-dynamic-include", "high", "Including a file chosen by request data allows local/remote file inclusion and code execution."));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return out;
|
|
203
|
+
}, "eval, dynamic includes or unsafe deserialisation of variable input");
|
|
204
|
+
// --- #42 Path traversal -----------------------------------------------------------------------
|
|
205
|
+
const FILE_FN = /^(fopen|file_get_contents|file_put_contents|readfile|unlink|file|copy|rename|mkdir|rmdir|opendir|scandir|move_uploaded_file|fpassthru|highlight_file|show_source)$/;
|
|
206
|
+
export const phpPathTraversal = phpPatternCheck("php-path-traversal", (index) => sinkFindings(index.calls(), (s) => (FILE_FN.test(fnName(s)) || /(^|\\)Storage::(get|put|delete|download|path)$|->download$/.test(s.name ?? "") ? phpArgs(s.node) : undefined), "php-path-from-request", "File paths built from request data allow ../ traversal; use basename() and confine paths to an allowed directory.", { requestOnly: true }), "file paths built from request data");
|
|
207
|
+
// --- #43 Cross-site scripting --------------------------------------------------------------------
|
|
208
|
+
const ESCAPED = /htmlspecialchars|htmlentities|strip_tags|\be\(|intval|\(int\)|json_encode|urlencode/i;
|
|
209
|
+
export const phpXss = phpPatternCheck("php-xss", async (index, ctx) => {
|
|
210
|
+
const out = [];
|
|
211
|
+
for (const { module, node } of allNodes(index)) {
|
|
212
|
+
if (node.kind !== "echo" && node.kind !== "print")
|
|
213
|
+
continue;
|
|
214
|
+
const exprs = node.kind === "echo" ? (node["expressions"] ?? []) : [node["expression"]];
|
|
215
|
+
for (const e of exprs.filter(isPhpNode)) {
|
|
216
|
+
if (!module.isRequestDerived(e) || ESCAPED.test(module.text(e)))
|
|
217
|
+
continue;
|
|
218
|
+
out.push(phpFinding(module, node, "php-echo-request", "high", "Echoing request data without htmlspecialchars() enables reflected XSS."));
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Blade templates: {!! ... !!} outputs without escaping. Regex only (higher false-positive rate, flagged in output).
|
|
223
|
+
for (const f of ctx.files.filter((x) => x.path.endsWith(".blade.php"))) {
|
|
224
|
+
(await ctx.read(f.path)).split(/\r?\n/).forEach((line, i) => {
|
|
225
|
+
if (/\{!!.*!!\}/.test(line)) {
|
|
226
|
+
out.push({ file: f.path, line: i + 1, snippet: snippetOf(line), why: "{!! !!} outputs a value without HTML-escaping; safe only if it can never contain user input.", confidence: "low", method: "regex", rule: "blade-unescaped-output" });
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
231
|
+
}, "unescaped output of request data");
|
|
232
|
+
// --- #55 Regex / #56 mass assignment / #60, #97 open redirect / #77 logs -----------------------------
|
|
233
|
+
export const phpRegexInjection = phpPatternCheck("php-regex-injection", (index) => sinkFindings(index.calls(), (s) => (/^preg_(match|match_all|replace|replace_callback|split|grep)$/.test(fnName(s)) ? arg(s) : undefined), "php-regex-from-request", "Regular expressions built from request data allow ReDoS and pattern manipulation; use preg_quote().", { requestOnly: true }), "regular expressions built from request data");
|
|
234
|
+
export const phpMassAssignment = phpPatternCheck("php-mass-assignment", (index) => {
|
|
235
|
+
const out = [];
|
|
236
|
+
const wholeRequest = (a) => /^(\$request|request\(\))->(all|input|post)\(\)$/.test(phpDotted(a) ?? "") && phpArgs(a).length === 0 || ["$_POST", "$_REQUEST", "$_GET"].includes(phpDotted(a) ?? "");
|
|
237
|
+
for (const s of index.calls()) {
|
|
238
|
+
if ((s.isNew || /^(create|update|fill|forceFill|insert|firstOrCreate|updateOrCreate|forceCreate)$/.test(s.method ?? "")) && phpArgs(s.node).some(wholeRequest)) {
|
|
239
|
+
out.push(phpFinding(s.module, s.node, "php-request-to-model", "medium", "Passing all request input to a model lets clients set any fillable field; use $request->validated() or ->only([...])."));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
for (const { module, node } of allNodes(index)) {
|
|
243
|
+
// protected $guarded = [];
|
|
244
|
+
if (node.kind === "property" && phpDotted(node["name"]) === "guarded" && isPhpNode(node["value"]) && node["value"].kind === "array" && (node["value"]["items"] ?? []).length === 0) {
|
|
245
|
+
out.push(phpFinding(module, node, "laravel-guarded-empty", "medium", "$guarded = [] makes every model attribute mass-assignable."));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}, "mass-assignment patterns (all request input passed to a model, empty $guarded)");
|
|
250
|
+
export const phpOpenRedirect = phpPatternCheck("php-open-redirect", (index) => {
|
|
251
|
+
const out = [];
|
|
252
|
+
for (const s of index.calls()) {
|
|
253
|
+
const name = s.name ?? "";
|
|
254
|
+
let target;
|
|
255
|
+
if (fnName(s) === "header" && /location\s*:/i.test(s.module.text(s.node)))
|
|
256
|
+
target = arg(s);
|
|
257
|
+
else if (name === "redirect" || /(->|::)(to|away)$/.test(name) && /redirect/i.test(name))
|
|
258
|
+
target = arg(s);
|
|
259
|
+
if (!target || !s.module.isRequestDerived(target, s.module.scope(s.fn)))
|
|
260
|
+
continue;
|
|
261
|
+
out.push(phpFinding(s.module, s.node, "php-open-redirect", s.module.isRequestDerived(target) ? "high" : "medium", "Redirecting to a URL taken from the request lets attackers send users to malicious sites; allow only relative paths or known hosts."));
|
|
262
|
+
}
|
|
263
|
+
return out;
|
|
264
|
+
}, "redirects to request-controlled URLs");
|
|
265
|
+
const LOG_CALL = /^(error_log|syslog|logger)$|(^|\\)Log::(debug|info|notice|warning|error|critical|alert|emergency)$|->(debug|info|notice|warning|error|critical)$/;
|
|
266
|
+
export const phpSecretsInLogs = phpPatternCheck("php-secrets-in-logs", (index) => {
|
|
267
|
+
const out = [];
|
|
268
|
+
for (const s of index.calls()) {
|
|
269
|
+
if (!LOG_CALL.test(s.name ?? ""))
|
|
270
|
+
continue;
|
|
271
|
+
for (const a of phpArgs(s.node)) {
|
|
272
|
+
if (isPhpLiteral(a))
|
|
273
|
+
continue;
|
|
274
|
+
const secret = phpIdentifiers(a).find((i) => SECRET_IDENT.test(i));
|
|
275
|
+
const dump = [...walkPhp(a)].some((n) => /^(\$_POST|\$_REQUEST|\$_COOKIE|(\$request|request\(\))->all\(\))$/.test(phpDotted(n) ?? ""));
|
|
276
|
+
if (secret || dump) {
|
|
277
|
+
out.push(phpFinding(s.module, s.node, "php-secret-logged", "medium", dump ? "Logging raw request data can write passwords, tokens and session IDs to logs." : `Logs a value named "${secret}", which may be a credential or token.`));
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}, "logging of passwords, tokens or raw request data");
|
|
284
|
+
// --- #86 / #87 XML ------------------------------------------------------------------------------
|
|
285
|
+
const xmlFlag = (index, flag, rule, why) => {
|
|
286
|
+
const out = [];
|
|
287
|
+
for (const s of index.calls()) {
|
|
288
|
+
if (phpArgs(s.node).some((a) => [...walkPhp(a)].some((n) => flag.test(phpDotted(n) ?? ""))))
|
|
289
|
+
out.push(phpFinding(s.module, s.node, rule, "high", why));
|
|
290
|
+
}
|
|
291
|
+
return out;
|
|
292
|
+
};
|
|
293
|
+
export const phpXxe = phpPatternCheck("php-xml-xxe", (index) => [
|
|
294
|
+
...xmlFlag(index, /^LIBXML_NOENT$/, "php-libxml-noent", "LIBXML_NOENT makes libxml substitute external entities (XXE): file disclosure and SSRF."),
|
|
295
|
+
...index.calls()
|
|
296
|
+
.filter((s) => fnName(s) === "libxml_disable_entity_loader" && arg(s)?.kind === "boolean" && arg(s)["value"] === false)
|
|
297
|
+
.map((s) => phpFinding(s.module, s.node, "php-entity-loader-enabled", "high", "libxml_disable_entity_loader(false) enables external entity loading.")),
|
|
298
|
+
], "XML parser options that expand external entities");
|
|
299
|
+
export const phpExternalDtd = phpPatternCheck("php-xml-dtd", (index) => xmlFlag(index, /^LIBXML_(DTDLOAD|DTDVALID|DTDATTR)$/, "php-libxml-dtd", "Loading DTDs lets documents pull external definitions."), "XML parser options that load external DTDs");
|
|
300
|
+
// --- Laravel configuration -------------------------------------------------------------------------
|
|
301
|
+
function laravelCheck(key, run) {
|
|
302
|
+
return codeCheck(key, ["laravel"], async (ctx) => run(await ctx.php(), ctx));
|
|
303
|
+
}
|
|
304
|
+
/** Value of a top-level key in a config file that returns an array, e.g. config/session.php 'secure'. */
|
|
305
|
+
function configEntry(index, file, key) {
|
|
306
|
+
for (const module of index.modules.filter((m) => file.test(m.path))) {
|
|
307
|
+
for (const n of walkPhp(module.tree)) {
|
|
308
|
+
if (n.kind === "entry" && phpString(n["key"]) === key && isPhpNode(n["value"]))
|
|
309
|
+
return { module, node: n, value: n["value"] };
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
/** Literal true/false, or the literal default of env('NAME', default). */
|
|
315
|
+
function boolOrEnvDefault(input) {
|
|
316
|
+
// (bool) env('X', false) -> look through the cast.
|
|
317
|
+
const value = input.kind === "cast" && isPhpNode(input["expr"]) ? input["expr"] : input;
|
|
318
|
+
if (value.kind === "boolean")
|
|
319
|
+
return { literal: value["value"] };
|
|
320
|
+
if (value.kind === "call" && phpDotted(value["what"]) === "env") {
|
|
321
|
+
const d = phpArgs(value)[1];
|
|
322
|
+
if (d?.kind === "boolean")
|
|
323
|
+
return { envDefault: d["value"] };
|
|
324
|
+
}
|
|
325
|
+
return {};
|
|
326
|
+
}
|
|
327
|
+
export const laravelDebug = laravelCheck("laravel-debug", (index) => {
|
|
328
|
+
const entry = configEntry(index, /(^|\/)config\/app\.php$/, "debug");
|
|
329
|
+
if (!entry)
|
|
330
|
+
return { status: "manual", detail: "config/app.php 'debug' was not found; confirm APP_DEBUG is false in production." };
|
|
331
|
+
const { literal, envDefault } = boolOrEnvDefault(entry.value);
|
|
332
|
+
const where = `${entry.module.path}:${entry.module.lineOf(entry.node)}`;
|
|
333
|
+
if (literal === true) {
|
|
334
|
+
return outcomeFromFindings([phpFinding(entry.module, entry.node, "laravel-debug-true", "high", "'debug' => true shows stack traces, queries and environment values to visitors.")], "");
|
|
335
|
+
}
|
|
336
|
+
if (envDefault === true) {
|
|
337
|
+
return outcomeFromFindings([phpFinding(entry.module, entry.node, "laravel-debug-default-true", "medium", "Debug mode defaults to on when APP_DEBUG is not set; default it to false.")], "");
|
|
338
|
+
}
|
|
339
|
+
if (literal === false)
|
|
340
|
+
return { status: "pass", detail: `Debug mode is off (${where}).` };
|
|
341
|
+
return { status: "manual", detail: `Debug mode is read from APP_DEBUG (${where}) and defaults to off; confirm it is false in the production environment.` };
|
|
342
|
+
});
|
|
343
|
+
function laravelSessionFlag(key, option, label, why) {
|
|
344
|
+
return laravelCheck(key, (index) => {
|
|
345
|
+
const entry = configEntry(index, /(^|\/)config\/session\.php$/, option);
|
|
346
|
+
if (!entry)
|
|
347
|
+
return { status: "manual", detail: `config/session.php '${option}' was not found; confirm ${label} is enabled for session cookies.` };
|
|
348
|
+
const { literal, envDefault } = boolOrEnvDefault(entry.value);
|
|
349
|
+
const where = `${entry.module.path}:${entry.module.lineOf(entry.node)}`;
|
|
350
|
+
if (literal === false || envDefault === false) {
|
|
351
|
+
return outcomeFromFindings([phpFinding(entry.module, entry.node, `${key}-off`, literal === false ? "high" : "medium", why)], "");
|
|
352
|
+
}
|
|
353
|
+
if (literal === true || envDefault === true)
|
|
354
|
+
return { status: "pass", detail: `Session cookies set ${label} (${where}).` };
|
|
355
|
+
return { status: "manual", detail: `${label} for session cookies is read from the environment (${where}); confirm the production value.` };
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
export const laravelSessionSecure = laravelSessionFlag("laravel-session-cookie-secure", "secure", "the Secure flag", "The session cookie can be sent over plain HTTP and intercepted.");
|
|
359
|
+
export const laravelSessionHttpOnly = laravelSessionFlag("laravel-session-cookie-httponly", "http_only", "HttpOnly", "JavaScript (including injected scripts) can read the session cookie.");
|
|
360
|
+
const MAX_SESSION_MINUTES = 24 * 60;
|
|
361
|
+
export const laravelSessionExpiry = laravelCheck("laravel-session-expiry", (index) => {
|
|
362
|
+
const entry = configEntry(index, /(^|\/)config\/session\.php$/, "lifetime");
|
|
363
|
+
if (!entry)
|
|
364
|
+
return { status: "manual", detail: "config/session.php 'lifetime' was not found; confirm session timeouts." };
|
|
365
|
+
const v = entry.value;
|
|
366
|
+
const literal = v.kind === "number" ? Number(v["value"]) : v.kind === "call" && phpDotted(v["what"]) === "env" && phpArgs(v)[1]?.kind === "number" ? Number(phpArgs(v)[1]["value"]) : undefined;
|
|
367
|
+
if (literal === undefined)
|
|
368
|
+
return { status: "manual", detail: `Session lifetime is computed at runtime (${entry.module.path}:${entry.module.lineOf(entry.node)}); confirm the production value.` };
|
|
369
|
+
if (literal > MAX_SESSION_MINUTES) {
|
|
370
|
+
return outcomeFromFindings([phpFinding(entry.module, entry.node, "laravel-session-lifetime", "medium", `Sessions stay valid for ${Math.round(literal / 60)} hours; this tool expects at most 24h as INSA sets no figure.`)], "");
|
|
371
|
+
}
|
|
372
|
+
return { status: "pass", detail: `Sessions expire after ${literal} minutes of inactivity.` };
|
|
373
|
+
});
|
|
374
|
+
export const laravelCsrf = laravelCheck("laravel-csrf", (index) => {
|
|
375
|
+
const exempt = [];
|
|
376
|
+
for (const { module, node } of allNodes(index)) {
|
|
377
|
+
// protected $except = ['webhook/*'] in the CSRF middleware.
|
|
378
|
+
if (node.kind === "property" && phpDotted(node["name"]) === "except" && /csrf/i.test(module.path + module.lines.join("\n")) && isPhpNode(node["value"]) && node["value"].kind === "array" && (node["value"]["items"] ?? []).length > 0) {
|
|
379
|
+
exempt.push(phpFinding(module, node, "laravel-csrf-except", "low", "These routes are exempt from CSRF verification; confirm each uses another defence (e.g. signed webhooks)."));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (exempt.length)
|
|
383
|
+
return { status: "manual", detail: `CSRF verification has ${exempt.length} exemption list(s): ${locations(exempt)}. Review each route.`, findings: exempt };
|
|
384
|
+
return { status: "pass", detail: "Laravel verifies CSRF tokens on web routes by default and no exemptions were found." };
|
|
385
|
+
});
|
|
386
|
+
export const laravelAuthRateLimit = laravelCheck("laravel-auth-rate-limit", (index) => {
|
|
387
|
+
if (index.mentions(/throttle:|RateLimiter::|ThrottleRequests|ThrottlesLogins/)) {
|
|
388
|
+
return { status: "pass", detail: "Rate limiting (throttle middleware / RateLimiter) is used. Confirm it covers login, password-reset and token routes." };
|
|
389
|
+
}
|
|
390
|
+
return { status: "manual", detail: "No throttle middleware or RateLimiter found. It may be enforced by a reverse proxy or WAF; verify there." };
|
|
391
|
+
});
|
|
392
|
+
export const laravelLoginRotation = laravelCheck("laravel-login-session-rotation", (index) => {
|
|
393
|
+
const attempts = index.calls().filter((s) => /(^|\\)Auth::attempt$|auth\(\)->attempt$|->attempt$/.test(s.name ?? ""));
|
|
394
|
+
if (attempts.length === 0)
|
|
395
|
+
return { status: "manual", detail: "No Auth::attempt() login found in the code; review how users are authenticated (starter kits regenerate the session)." };
|
|
396
|
+
if (index.mentions(/->regenerate\(\)/))
|
|
397
|
+
return { status: "pass", detail: "The session is regenerated on login ($request->session()->regenerate())." };
|
|
398
|
+
return outcomeFromFindings(attempts.map((s) => phpFinding(s.module, s.node, "laravel-login-no-regenerate", "medium", "Login does not regenerate the session ID (session fixation); call $request->session()->regenerate() after Auth::attempt().")), "");
|
|
399
|
+
});
|
|
400
|
+
const handlesUploads = (index) => index.mentions(/\$_FILES|->file\(|->hasFile\(|UploadedFile/);
|
|
401
|
+
const NO_UPLOADS = (n) => ({ status: "pass", detail: `No file upload handling found in ${n} PHP file(s).` });
|
|
402
|
+
export const phpUploadPath = codeCheck("php-upload-path", ["php"], async (ctx) => {
|
|
403
|
+
const index = await ctx.php();
|
|
404
|
+
if (!handlesUploads(index))
|
|
405
|
+
return NO_UPLOADS(index.modules.length);
|
|
406
|
+
const findings = [];
|
|
407
|
+
for (const s of index.calls()) {
|
|
408
|
+
const text = s.module.text(s.node);
|
|
409
|
+
const clientName = /getClientOriginalName\(\)|\$_FILES\[[^\]]+\]\[['"]name['"]\]/.test(text);
|
|
410
|
+
if (clientName && (/^(move_uploaded_file|copy|rename)$/.test(fnName(s)) || /->(storeAs|move|putFileAs)$/.test(s.name ?? ""))) {
|
|
411
|
+
findings.push(phpFinding(s.module, s.node, "php-upload-client-filename", "high", "Storing an upload under the client-supplied file name allows ../ to escape the upload directory and overwrites; generate the name (->store()) or use basename() plus an allow-list."));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return outcomeFromFindings(findings, "Uploads are not stored under client-supplied file names.");
|
|
415
|
+
});
|
|
416
|
+
export const phpUploadSize = codeCheck("php-upload-size", ["php"], async (ctx) => {
|
|
417
|
+
const index = await ctx.php();
|
|
418
|
+
if (!handlesUploads(index))
|
|
419
|
+
return NO_UPLOADS(index.modules.length);
|
|
420
|
+
if (index.mentions(/['"|]max:\d+|\[['"]size['"]\]\s*[<>]|getSize\(\)\s*[<>]/))
|
|
421
|
+
return { status: "pass", detail: "Upload size is validated in code (max: rule or size comparison)." };
|
|
422
|
+
return { status: "manual", detail: "The project handles uploads but no size validation was found in code. Confirm upload_max_filesize / post_max_size or add a max: rule." };
|
|
423
|
+
});
|
|
424
|
+
export const phpUploadType = codeCheck("php-upload-type", ["php"], async (ctx) => {
|
|
425
|
+
const index = await ctx.php();
|
|
426
|
+
if (!handlesUploads(index))
|
|
427
|
+
return NO_UPLOADS(index.modules.length);
|
|
428
|
+
if (index.mentions(/mimes:|mimetypes:|['"|]image['"|]|finfo_file|mime_content_type|getMimeType\(\)|exif_imagetype/)) {
|
|
429
|
+
return { status: "pass", detail: "Upload type is validated in code (mimes/mimetypes/image rule or a content-type check)." };
|
|
430
|
+
}
|
|
431
|
+
return { status: "manual", detail: "The project handles uploads but no type validation was found in code; confirm uploads are restricted by content, not only by extension." };
|
|
432
|
+
});
|
|
433
|
+
//# sourceMappingURL=php.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"php.js","sourceRoot":"","sources":["../../../src/code/checks/php.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const SECRET_ASSIGN: RegExp;
|
|
2
|
+
export declare const SECRET_DICT_KEY: RegExp;
|
|
3
|
+
export declare const looksSecret: (value: string | undefined) => value is string;
|
|
4
|
+
/** #6 Hard-coded secrets (Django SECRET_KEY, credentials in code). Snippets are redacted. */
|
|
5
|
+
export declare const hardcodedSecrets: import("../types.js").CodeCheck;
|
|
6
|
+
/** #34 Plaintext password storage or retrieval. */
|
|
7
|
+
export declare const plaintextPasswords: import("../types.js").CodeCheck;
|
|
8
|
+
/** #77 Secrets/tokens written to logs. */
|
|
9
|
+
export declare const secretsInLogs: import("../types.js").CodeCheck;
|
|
10
|
+
//# sourceMappingURL=secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../src/code/checks/secrets.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa,QAA0F,CAAC;AACrH,eAAO,MAAM,eAAe,QAAuF,CAAC;AAMpH,eAAO,MAAM,WAAW,UAAW,MAAM,GAAG,SAAS,KAAG,KAAK,IAAI,MAC8B,CAAC;AAEhG,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,iCA2C5B,CAAC;AAKF,mDAAmD;AACnD,eAAO,MAAM,kBAAkB,iCA6C9B,CAAC;AAMF,0CAA0C;AAC1C,eAAO,MAAM,aAAa,iCA+BzB,CAAC"}
|