@korayda4/vibe-security 0.3.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 +21 -0
- package/README.md +240 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +333 -0
- package/dist/cli.js.map +1 -0
- package/dist/engine/baseline.d.ts +19 -0
- package/dist/engine/baseline.js +48 -0
- package/dist/engine/baseline.js.map +1 -0
- package/dist/engine/config.d.ts +26 -0
- package/dist/engine/config.js +41 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/fixer.d.ts +22 -0
- package/dist/engine/fixer.js +87 -0
- package/dist/engine/fixer.js.map +1 -0
- package/dist/engine/language.d.ts +27 -0
- package/dist/engine/language.js +364 -0
- package/dist/engine/language.js.map +1 -0
- package/dist/engine/output.d.ts +6 -0
- package/dist/engine/output.js +155 -0
- package/dist/engine/output.js.map +1 -0
- package/dist/engine/reporter.d.ts +3 -0
- package/dist/engine/reporter.js +145 -0
- package/dist/engine/reporter.js.map +1 -0
- package/dist/engine/rules/_helpers.d.ts +9 -0
- package/dist/engine/rules/_helpers.js +64 -0
- package/dist/engine/rules/_helpers.js.map +1 -0
- package/dist/engine/rules/backend/fileUpload.d.ts +3 -0
- package/dist/engine/rules/backend/fileUpload.js +40 -0
- package/dist/engine/rules/backend/fileUpload.js.map +1 -0
- package/dist/engine/rules/backend/hashing.d.ts +3 -0
- package/dist/engine/rules/backend/hashing.js +40 -0
- package/dist/engine/rules/backend/hashing.js.map +1 -0
- package/dist/engine/rules/backend/idor.d.ts +3 -0
- package/dist/engine/rules/backend/idor.js +40 -0
- package/dist/engine/rules/backend/idor.js.map +1 -0
- package/dist/engine/rules/backend/index.d.ts +12 -0
- package/dist/engine/rules/backend/index.js +22 -0
- package/dist/engine/rules/backend/index.js.map +1 -0
- package/dist/engine/rules/backend/inputValidation.d.ts +3 -0
- package/dist/engine/rules/backend/inputValidation.js +37 -0
- package/dist/engine/rules/backend/inputValidation.js.map +1 -0
- package/dist/engine/rules/backend/jwt.d.ts +3 -0
- package/dist/engine/rules/backend/jwt.js +42 -0
- package/dist/engine/rules/backend/jwt.js.map +1 -0
- package/dist/engine/rules/backend/rateLimit.d.ts +3 -0
- package/dist/engine/rules/backend/rateLimit.js +45 -0
- package/dist/engine/rules/backend/rateLimit.js.map +1 -0
- package/dist/engine/rules/backend/sqlInjection.d.ts +3 -0
- package/dist/engine/rules/backend/sqlInjection.js +41 -0
- package/dist/engine/rules/backend/sqlInjection.js.map +1 -0
- package/dist/engine/rules/backend/tokenExpiry.d.ts +3 -0
- package/dist/engine/rules/backend/tokenExpiry.js +85 -0
- package/dist/engine/rules/backend/tokenExpiry.js.map +1 -0
- package/dist/engine/rules/backend/tokenInUrl.d.ts +3 -0
- package/dist/engine/rules/backend/tokenInUrl.js +112 -0
- package/dist/engine/rules/backend/tokenInUrl.js.map +1 -0
- package/dist/engine/rules/cicd/dependencies.d.ts +3 -0
- package/dist/engine/rules/cicd/dependencies.js +44 -0
- package/dist/engine/rules/cicd/dependencies.js.map +1 -0
- package/dist/engine/rules/cicd/dockerfile.d.ts +3 -0
- package/dist/engine/rules/cicd/dockerfile.js +42 -0
- package/dist/engine/rules/cicd/dockerfile.js.map +1 -0
- package/dist/engine/rules/cicd/index.d.ts +6 -0
- package/dist/engine/rules/cicd/index.js +10 -0
- package/dist/engine/rules/cicd/index.js.map +1 -0
- package/dist/engine/rules/cicd/secrets.d.ts +3 -0
- package/dist/engine/rules/cicd/secrets.js +41 -0
- package/dist/engine/rules/cicd/secrets.js.map +1 -0
- package/dist/engine/rules/database/encryption.d.ts +3 -0
- package/dist/engine/rules/database/encryption.js +37 -0
- package/dist/engine/rules/database/encryption.js.map +1 -0
- package/dist/engine/rules/database/index.d.ts +5 -0
- package/dist/engine/rules/database/index.js +8 -0
- package/dist/engine/rules/database/index.js.map +1 -0
- package/dist/engine/rules/database/privileges.d.ts +3 -0
- package/dist/engine/rules/database/privileges.js +40 -0
- package/dist/engine/rules/database/privileges.js.map +1 -0
- package/dist/engine/rules/frontend/clickjacking.d.ts +3 -0
- package/dist/engine/rules/frontend/clickjacking.js +41 -0
- package/dist/engine/rules/frontend/clickjacking.js.map +1 -0
- package/dist/engine/rules/frontend/cookies.d.ts +3 -0
- package/dist/engine/rules/frontend/cookies.js +35 -0
- package/dist/engine/rules/frontend/cookies.js.map +1 -0
- package/dist/engine/rules/frontend/envVars.d.ts +3 -0
- package/dist/engine/rules/frontend/envVars.js +34 -0
- package/dist/engine/rules/frontend/envVars.js.map +1 -0
- package/dist/engine/rules/frontend/eval.d.ts +3 -0
- package/dist/engine/rules/frontend/eval.js +35 -0
- package/dist/engine/rules/frontend/eval.js.map +1 -0
- package/dist/engine/rules/frontend/index.d.ts +9 -0
- package/dist/engine/rules/frontend/index.js +16 -0
- package/dist/engine/rules/frontend/index.js.map +1 -0
- package/dist/engine/rules/frontend/sourceMaps.d.ts +3 -0
- package/dist/engine/rules/frontend/sourceMaps.js +79 -0
- package/dist/engine/rules/frontend/sourceMaps.js.map +1 -0
- package/dist/engine/rules/frontend/xss.d.ts +3 -0
- package/dist/engine/rules/frontend/xss.js +70 -0
- package/dist/engine/rules/frontend/xss.js.map +1 -0
- package/dist/engine/rules/index.d.ts +8 -0
- package/dist/engine/rules/index.js +38 -0
- package/dist/engine/rules/index.js.map +1 -0
- package/dist/engine/rules/kotlin/index.d.ts +5 -0
- package/dist/engine/rules/kotlin/index.js +8 -0
- package/dist/engine/rules/kotlin/index.js.map +1 -0
- package/dist/engine/rules/kotlin/kotlinxHtml.d.ts +3 -0
- package/dist/engine/rules/kotlin/kotlinxHtml.js +54 -0
- package/dist/engine/rules/kotlin/kotlinxHtml.js.map +1 -0
- package/dist/engine/rules/kotlin/sqlInjection.d.ts +3 -0
- package/dist/engine/rules/kotlin/sqlInjection.js +57 -0
- package/dist/engine/rules/kotlin/sqlInjection.js.map +1 -0
- package/dist/engine/rules/network/cors.d.ts +3 -0
- package/dist/engine/rules/network/cors.js +106 -0
- package/dist/engine/rules/network/cors.js.map +1 -0
- package/dist/engine/rules/network/headers.d.ts +3 -0
- package/dist/engine/rules/network/headers.js +51 -0
- package/dist/engine/rules/network/headers.js.map +1 -0
- package/dist/engine/rules/network/index.d.ts +6 -0
- package/dist/engine/rules/network/index.js +10 -0
- package/dist/engine/rules/network/index.js.map +1 -0
- package/dist/engine/rules/network/tls.d.ts +3 -0
- package/dist/engine/rules/network/tls.js +40 -0
- package/dist/engine/rules/network/tls.js.map +1 -0
- package/dist/engine/rules/observability/errorHandler.d.ts +3 -0
- package/dist/engine/rules/observability/errorHandler.js +34 -0
- package/dist/engine/rules/observability/errorHandler.js.map +1 -0
- package/dist/engine/rules/observability/index.d.ts +5 -0
- package/dist/engine/rules/observability/index.js +8 -0
- package/dist/engine/rules/observability/index.js.map +1 -0
- package/dist/engine/rules/observability/logging.d.ts +3 -0
- package/dist/engine/rules/observability/logging.js +38 -0
- package/dist/engine/rules/observability/logging.js.map +1 -0
- package/dist/engine/rules/php/index.d.ts +6 -0
- package/dist/engine/rules/php/index.js +10 -0
- package/dist/engine/rules/php/index.js.map +1 -0
- package/dist/engine/rules/php/sqlInjection.d.ts +3 -0
- package/dist/engine/rules/php/sqlInjection.js +58 -0
- package/dist/engine/rules/php/sqlInjection.js.map +1 -0
- package/dist/engine/rules/php/weakHashing.d.ts +3 -0
- package/dist/engine/rules/php/weakHashing.js +36 -0
- package/dist/engine/rules/php/weakHashing.js.map +1 -0
- package/dist/engine/rules/php/xss.d.ts +3 -0
- package/dist/engine/rules/php/xss.js +56 -0
- package/dist/engine/rules/php/xss.js.map +1 -0
- package/dist/engine/rules/ruby/index.d.ts +6 -0
- package/dist/engine/rules/ruby/index.js +10 -0
- package/dist/engine/rules/ruby/index.js.map +1 -0
- package/dist/engine/rules/ruby/sqlInjection.d.ts +3 -0
- package/dist/engine/rules/ruby/sqlInjection.js +56 -0
- package/dist/engine/rules/ruby/sqlInjection.js.map +1 -0
- package/dist/engine/rules/ruby/strongParams.d.ts +3 -0
- package/dist/engine/rules/ruby/strongParams.js +35 -0
- package/dist/engine/rules/ruby/strongParams.js.map +1 -0
- package/dist/engine/rules/ruby/xss.d.ts +3 -0
- package/dist/engine/rules/ruby/xss.js +55 -0
- package/dist/engine/rules/ruby/xss.js.map +1 -0
- package/dist/engine/rules/rust/index.d.ts +6 -0
- package/dist/engine/rules/rust/index.js +10 -0
- package/dist/engine/rules/rust/index.js.map +1 -0
- package/dist/engine/rules/rust/secretInCode.d.ts +3 -0
- package/dist/engine/rules/rust/secretInCode.js +36 -0
- package/dist/engine/rules/rust/secretInCode.js.map +1 -0
- package/dist/engine/rules/rust/sqlInjection.d.ts +3 -0
- package/dist/engine/rules/rust/sqlInjection.js +55 -0
- package/dist/engine/rules/rust/sqlInjection.js.map +1 -0
- package/dist/engine/rules/rust/unsafeExpect.d.ts +3 -0
- package/dist/engine/rules/rust/unsafeExpect.js +56 -0
- package/dist/engine/rules/rust/unsafeExpect.js.map +1 -0
- package/dist/engine/scanner.d.ts +5 -0
- package/dist/engine/scanner.js +135 -0
- package/dist/engine/scanner.js.map +1 -0
- package/dist/engine/walker.d.ts +11 -0
- package/dist/engine/walker.js +90 -0
- package/dist/engine/walker.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.js +360 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +92 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { lineColumnFromIndex, snippetAt } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'KT-001',
|
|
4
|
+
title: 'Kotlin: SQL injection via string template in JPA/JDBC',
|
|
5
|
+
layer: 'backend',
|
|
6
|
+
severity: 'critical',
|
|
7
|
+
description: 'Kotlin string templates (`"SELECT * FROM users WHERE id = $id"`) and string concatenation passed to JPA native queries or JDBC allow SQL injection. Spring Data JPA with `@Query` parameterizes via `?1` / `:name`; raw concatenation bypasses that.',
|
|
8
|
+
threat: 'Database exfiltration, authentication bypass, data destruction',
|
|
9
|
+
remediation: '1) Use Spring Data JPA: `@Query("SELECT u FROM User u WHERE u.email = :email") fun findByEmail(@Param("email") email: String)`. ' +
|
|
10
|
+
'2) For native queries: `@Query(value = "SELECT * FROM users WHERE id = ?1", nativeQuery = true)`. ' +
|
|
11
|
+
'3) For raw JDBC: `PreparedStatement` with `?` placeholders, never `String.format` or `+`. ' +
|
|
12
|
+
'4) Use `org.springframework.jdbc.core.namedparam.MapSqlParameterSource` for named parameters. ' +
|
|
13
|
+
'5) NEVER use `"SELECT * FROM users WHERE id = $id"` with string templates.',
|
|
14
|
+
references: [
|
|
15
|
+
'https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query',
|
|
16
|
+
'https://kotlinlang.org/docs/reference/java-interop.html#string-templates',
|
|
17
|
+
],
|
|
18
|
+
cwe: 'CWE-89',
|
|
19
|
+
owasp: 'A03:2021 Injection',
|
|
20
|
+
languages: ['kotlin'],
|
|
21
|
+
check: (ctx) => {
|
|
22
|
+
const findings = [];
|
|
23
|
+
const patterns = [
|
|
24
|
+
/["']SELECT[^"']*\$[a-zA-Z]/gi,
|
|
25
|
+
/["']INSERT[^"']*\$[a-zA-Z]/gi,
|
|
26
|
+
/["']UPDATE[^"']*\$[a-zA-Z]/gi,
|
|
27
|
+
/["']DELETE[^"']*\$[a-zA-Z]/gi,
|
|
28
|
+
/createNativeQuery\s*\(\s*["'][^"']*\$/g,
|
|
29
|
+
/@Query\s*\(\s*["'][^"']*\$/g,
|
|
30
|
+
];
|
|
31
|
+
for (const re of patterns) {
|
|
32
|
+
for (const m of ctx.source.matchAll(re)) {
|
|
33
|
+
if (m.index === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
const { line } = lineColumnFromIndex(ctx.source, m.index);
|
|
36
|
+
findings.push({
|
|
37
|
+
id: `${rule.id}-${ctx.relativePath}-${line}`,
|
|
38
|
+
ruleId: rule.id,
|
|
39
|
+
title: rule.title,
|
|
40
|
+
layer: rule.layer,
|
|
41
|
+
severity: rule.severity,
|
|
42
|
+
file: ctx.relativePath,
|
|
43
|
+
match: { snippet: snippetAt(ctx.source, line), line, column: m.index },
|
|
44
|
+
description: rule.description,
|
|
45
|
+
impact: rule.threat,
|
|
46
|
+
remediation: rule.remediation,
|
|
47
|
+
references: rule.references,
|
|
48
|
+
cwe: rule.cwe,
|
|
49
|
+
owasp: rule.owasp,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return findings;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
export default rule;
|
|
57
|
+
//# sourceMappingURL=sqlInjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlInjection.js","sourceRoot":"","sources":["../../../../src/engine/rules/kotlin/sqlInjection.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,mBAAmB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE1E,MAAM,IAAI,GAAS;IACjB,EAAE,EAAE,QAAQ;IACZ,KAAK,EAAE,uDAAuD;IAC9D,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,UAAU;IACpB,WAAW,EACT,sPAAsP;IACxP,MAAM,EAAE,gEAAgE;IACxE,WAAW,EACT,kIAAkI;QAClI,oGAAoG;QACpG,4FAA4F;QAC5F,gGAAgG;QAChG,4EAA4E;IAC9E,UAAU,EAAE;QACV,gGAAgG;QAChG,0EAA0E;KAC3E;IACD,GAAG,EAAE,QAAQ;IACb,KAAK,EAAE,oBAAoB;IAC3B,SAAS,EAAE,CAAC,QAAQ,CAAC;IACrB,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG;YACf,8BAA8B;YAC9B,8BAA8B;YAC9B,8BAA8B;YAC9B,8BAA8B;YAC9B,wCAAwC;YACxC,6BAA6B;SAC9B,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;oBAAE,SAAS;gBACpC,MAAM,EAAE,IAAI,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC1D,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,YAAY,IAAI,IAAI,EAAE;oBAC5C,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,IAAI,EAAE,GAAG,CAAC,YAAY;oBACtB,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE;oBACtE,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { lineColumnFromIndex, snippetAt } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'NET-002',
|
|
4
|
+
title: 'Overly permissive CORS (wildcard or origin reflection)',
|
|
5
|
+
layer: 'network',
|
|
6
|
+
severity: 'high',
|
|
7
|
+
description: '`Access-Control-Allow-Origin: *` veya gelen `Origin` header\'inin dogrudan yansitilmasi, baska origin\'lerin API\'nize erismesine izin verir. Kimlik bilgisi (credentials) ile birlikteyse cross-origin veri hirsizligina yol acar.',
|
|
8
|
+
threat: 'Cross-origin data theft, CSRF, credential exfiltration',
|
|
9
|
+
remediation: '1) Wildcard (`*`) KULLANMAYIN. ' +
|
|
10
|
+
'2) Explicit bir whitelist tanimlayin: `const allowed = [\'https://app.example.com\', \'https://admin.example.com\']`. ' +
|
|
11
|
+
'3) Origin kontrolu yapip eslesiyorsa `Access-Control-Allow-Origin: <specific-origin>` donun. ' +
|
|
12
|
+
'4) Credentials ile birlikte `*` ASLA calismaz; gerekirse `Access-Control-Allow-Credentials: true` + explicit origin kullanin. ' +
|
|
13
|
+
'5) Preflight icin `Access-Control-Allow-Methods` ve `Access-Control-Allow-Headers`\'i da kisitlayin. ' +
|
|
14
|
+
'6) Express: `cors({ origin: allowed, credentials: true })`.',
|
|
15
|
+
references: [
|
|
16
|
+
'https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS',
|
|
17
|
+
'https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#cross-origin-resource-sharing',
|
|
18
|
+
],
|
|
19
|
+
cwe: 'CWE-942',
|
|
20
|
+
owasp: 'A05:2021 Security Misconfiguration',
|
|
21
|
+
languages: ['javascript', 'typescript'],
|
|
22
|
+
check: (ctx) => {
|
|
23
|
+
const isServerFile = /(?:server|app|main|index)\.(?:ts|js|tsx|jsx|mjs|cjs)$/i.test(ctx.relativePath) ||
|
|
24
|
+
/\/api\//i.test(ctx.relativePath) ||
|
|
25
|
+
/routes?\//i.test(ctx.relativePath);
|
|
26
|
+
if (!isServerFile)
|
|
27
|
+
return [];
|
|
28
|
+
const findings = [];
|
|
29
|
+
const wildcard = /Access-Control-Allow-Origin['"`\s]*,?\s*['"`]\*['"`]/gi;
|
|
30
|
+
for (const m of ctx.source.matchAll(wildcard)) {
|
|
31
|
+
if (m.index === undefined)
|
|
32
|
+
continue;
|
|
33
|
+
const { line } = lineColumnFromIndex(ctx.source, m.index);
|
|
34
|
+
findings.push({
|
|
35
|
+
id: `${rule.id}-${ctx.relativePath}-${line}-w`,
|
|
36
|
+
ruleId: rule.id,
|
|
37
|
+
title: rule.title,
|
|
38
|
+
layer: rule.layer,
|
|
39
|
+
severity: rule.severity,
|
|
40
|
+
file: ctx.relativePath,
|
|
41
|
+
match: { snippet: snippetAt(ctx.source, line), line, column: m.index },
|
|
42
|
+
description: rule.description,
|
|
43
|
+
impact: rule.threat,
|
|
44
|
+
remediation: rule.remediation,
|
|
45
|
+
references: rule.references,
|
|
46
|
+
cwe: rule.cwe,
|
|
47
|
+
owasp: rule.owasp,
|
|
48
|
+
fix: {
|
|
49
|
+
find: m[0],
|
|
50
|
+
replace: m[0].replace(/['"`]\*['"`]/, "'https://yourdomain.com'"),
|
|
51
|
+
description: 'Wildcard yerine explicit origin whitelist kullan (kendi domain\'ini yaz)',
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const reflect = /origin\s*:\s*req\.headers\.origin/g;
|
|
56
|
+
for (const m of ctx.source.matchAll(reflect)) {
|
|
57
|
+
if (m.index === undefined)
|
|
58
|
+
continue;
|
|
59
|
+
const { line } = lineColumnFromIndex(ctx.source, m.index);
|
|
60
|
+
findings.push({
|
|
61
|
+
id: `${rule.id}-${ctx.relativePath}-${line}-r`,
|
|
62
|
+
ruleId: rule.id,
|
|
63
|
+
title: rule.title,
|
|
64
|
+
layer: rule.layer,
|
|
65
|
+
severity: rule.severity,
|
|
66
|
+
file: ctx.relativePath,
|
|
67
|
+
match: { snippet: snippetAt(ctx.source, line), line, column: m.index },
|
|
68
|
+
description: rule.description,
|
|
69
|
+
impact: rule.threat,
|
|
70
|
+
remediation: rule.remediation,
|
|
71
|
+
references: rule.references,
|
|
72
|
+
cwe: rule.cwe,
|
|
73
|
+
owasp: rule.owasp,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const corsOrigin = /origin\s*:\s*['"`]\*['"`]/g;
|
|
77
|
+
for (const m of ctx.source.matchAll(corsOrigin)) {
|
|
78
|
+
if (m.index === undefined)
|
|
79
|
+
continue;
|
|
80
|
+
const { line } = lineColumnFromIndex(ctx.source, m.index);
|
|
81
|
+
findings.push({
|
|
82
|
+
id: `${rule.id}-${ctx.relativePath}-${line}-c`,
|
|
83
|
+
ruleId: rule.id,
|
|
84
|
+
title: rule.title,
|
|
85
|
+
layer: rule.layer,
|
|
86
|
+
severity: rule.severity,
|
|
87
|
+
file: ctx.relativePath,
|
|
88
|
+
match: { snippet: snippetAt(ctx.source, line), line, column: m.index },
|
|
89
|
+
description: rule.description,
|
|
90
|
+
impact: rule.threat,
|
|
91
|
+
remediation: rule.remediation,
|
|
92
|
+
references: rule.references,
|
|
93
|
+
cwe: rule.cwe,
|
|
94
|
+
owasp: rule.owasp,
|
|
95
|
+
fix: {
|
|
96
|
+
find: "origin: '*'",
|
|
97
|
+
replace: "origin: ['https://yourdomain.com']",
|
|
98
|
+
description: 'cors()\'a whitelist array\'i ver',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return findings;
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
export default rule;
|
|
106
|
+
//# sourceMappingURL=cors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../../../src/engine/rules/network/cors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { grepRule } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'NET-001',
|
|
4
|
+
title: 'Missing HTTP security headers (CSP, HSTS, nosniff, referrer-policy, permissions-policy)',
|
|
5
|
+
layer: 'network',
|
|
6
|
+
severity: 'medium',
|
|
7
|
+
description: 'HTTP response\'larinda `Content-Security-Policy`, `Strict-Transport-Security`, `X-Content-Type-Options: nosniff`, `Referrer-Policy` veya `Permissions-Policy` basliklari yoksa tarayici tabanli saldiri yuzeyi acilir: XSS, MIME sniffing, bilgi sizintisi, yetenek istismari.',
|
|
8
|
+
threat: 'XSS escalation, MIME sniffing, MITM downgrade, information leakage, feature abuse',
|
|
9
|
+
remediation: 'Asagidaki header\'lari TUM response\'lara ekleyin: ' +
|
|
10
|
+
'`Content-Security-Policy: default-src \'self\'; script-src \'self\'; object-src \'none\'; base-uri \'self\'` ' +
|
|
11
|
+
'`Strict-Transport-Security: max-age=31536000; includeSubDomains; preload` ' +
|
|
12
|
+
'`X-Content-Type-Options: nosniff` ' +
|
|
13
|
+
'`Referrer-Policy: strict-origin-when-cross-origin` ' +
|
|
14
|
+
'`Permissions-Policy: camera=(), microphone=(), geolocation=()` ' +
|
|
15
|
+
'Next.js: `next.config.js` headers; Nginx: `add_header ... always`; Express: `helmet()` middleware\'i.',
|
|
16
|
+
references: [
|
|
17
|
+
'https://owasp.org/www-project-secure-headers/',
|
|
18
|
+
'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers',
|
|
19
|
+
'https://securityheaders.com/',
|
|
20
|
+
'https://helmetjs.github.io/',
|
|
21
|
+
],
|
|
22
|
+
cwe: 'CWE-693',
|
|
23
|
+
owasp: 'A05:2021 Security Misconfiguration',
|
|
24
|
+
languages: ['javascript', 'typescript'],
|
|
25
|
+
check: (ctx) => {
|
|
26
|
+
const isConfig = /next\.config\.(js|mjs|ts)$/i.test(ctx.relativePath) ||
|
|
27
|
+
/vercel\.json$/i.test(ctx.relativePath) ||
|
|
28
|
+
/_headers$/i.test(ctx.relativePath) ||
|
|
29
|
+
/server\.(ts|js)$/i.test(ctx.relativePath) ||
|
|
30
|
+
/nginx\.conf$/i.test(ctx.relativePath) ||
|
|
31
|
+
/middleware\.(ts|js)$/i.test(ctx.relativePath);
|
|
32
|
+
if (!isConfig)
|
|
33
|
+
return [];
|
|
34
|
+
const requiredHeaders = [
|
|
35
|
+
'content-security-policy',
|
|
36
|
+
'strict-transport-security',
|
|
37
|
+
'x-content-type-options',
|
|
38
|
+
'referrer-policy',
|
|
39
|
+
'permissions-policy',
|
|
40
|
+
];
|
|
41
|
+
const missing = requiredHeaders.filter((h) => !new RegExp(h, 'i').test(ctx.source));
|
|
42
|
+
if (missing.length === 0)
|
|
43
|
+
return [];
|
|
44
|
+
const findings = [];
|
|
45
|
+
const re = /headers\s*\(\s*\)\s*[:=]/g;
|
|
46
|
+
findings.push(...grepRule(rule, ctx, re));
|
|
47
|
+
return findings;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
export default rule;
|
|
51
|
+
//# sourceMappingURL=headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/engine/rules/network/headers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,IAAI,GAAS;IACjB,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,yFAAyF;IAChG,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,QAAQ;IAClB,WAAW,EACT,gRAAgR;IAClR,MAAM,EAAE,mFAAmF;IAC3F,WAAW,EACT,qDAAqD;QACrD,+GAA+G;QAC/G,4EAA4E;QAC5E,oCAAoC;QACpC,qDAAqD;QACrD,iEAAiE;QACjE,uGAAuG;IACzG,UAAU,EAAE;QACV,+CAA+C;QAC/C,2DAA2D;QAC3D,8BAA8B;QAC9B,6BAA6B;KAC9B;IACD,GAAG,EAAE,SAAS;IACd,KAAK,EAAE,oCAAoC;IAC3C,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;IACvC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,QAAQ,GACZ,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YACpD,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YACvC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YACnC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YAC1C,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YACtC,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAEjD,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;QAEzB,MAAM,eAAe,GAAG;YACtB,yBAAyB;YACzB,2BAA2B;YAC3B,wBAAwB;YACxB,iBAAiB;YACjB,oBAAoB;SACrB,CAAC;QAEF,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAC5C,CAAC;QAEF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,EAAE,CAAC;QAChB,MAAM,EAAE,GAAG,2BAA2B,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QAC1C,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/engine/rules/network/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO;IACP,IAAI;IACJ,GAAG;CACJ,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { grepRule } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'NET-003',
|
|
4
|
+
title: 'Insecure transport — TLS downgrade or missing HTTPS enforcement',
|
|
5
|
+
layer: 'network',
|
|
6
|
+
severity: 'high',
|
|
7
|
+
description: 'TLS 1.0/1.1 destegi aciksa veya HTTP→HTTPS yonlendirmesi yoksa, ag seviyesi MITM saldirilari ile hassas veri sizdirilabilir.',
|
|
8
|
+
threat: 'Man-in-the-middle, credential interception, session theft',
|
|
9
|
+
remediation: '1) TLS 1.2+ zorunlu tutun; TLS 1.0/1.1\'i devre disi birakin. ' +
|
|
10
|
+
'2) `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload`. ' +
|
|
11
|
+
'3) Nginx: `ssl_protocols TLSv1.2 TLSv1.3;`. ' +
|
|
12
|
+
'4) Tum HTTP isteklerini 301 ile HTTPS\'e yonlendirin. ' +
|
|
13
|
+
'5) Sertifika otomasyonu icin Let\'s Encrypt + certbot veya cloud provider ACM kullanin. ' +
|
|
14
|
+
'6) HSTS preload listesi icin basvuru yapin.',
|
|
15
|
+
references: [
|
|
16
|
+
'https://wiki.mozilla.org/Security/Server_Side_TLS',
|
|
17
|
+
'https://datatracker.ietf.org/doc/html/rfc6797',
|
|
18
|
+
],
|
|
19
|
+
cwe: 'CWE-319',
|
|
20
|
+
owasp: 'A02:2021 Cryptographic Failures',
|
|
21
|
+
languages: ['javascript', 'typescript'],
|
|
22
|
+
check: (ctx) => {
|
|
23
|
+
const isConfig = /nginx\.conf$/i.test(ctx.relativePath) ||
|
|
24
|
+
/next\.config\.(js|mjs|ts)$/i.test(ctx.relativePath) ||
|
|
25
|
+
/server\.(ts|js)$/i.test(ctx.relativePath);
|
|
26
|
+
if (!isConfig)
|
|
27
|
+
return [];
|
|
28
|
+
const findings = [];
|
|
29
|
+
const tlsPattern = /ssl_protocols\s+([^;\n]+)/g;
|
|
30
|
+
for (const m of ctx.source.matchAll(tlsPattern)) {
|
|
31
|
+
if (m[1] && /TLSv1\.0|TLSv1\.1|SSLv[23]/.test(m[1])) {
|
|
32
|
+
findings.push(...grepRule(rule, ctx, tlsPattern));
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return findings;
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export default rule;
|
|
40
|
+
//# sourceMappingURL=tls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls.js","sourceRoot":"","sources":["../../../../src/engine/rules/network/tls.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,IAAI,GAAS;IACjB,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,iEAAiE;IACxE,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,MAAM;IAChB,WAAW,EACT,8HAA8H;IAChI,MAAM,EAAE,2DAA2D;IACnE,WAAW,EACT,gEAAgE;QAChE,gFAAgF;QAChF,8CAA8C;QAC9C,wDAAwD;QACxD,0FAA0F;QAC1F,6CAA6C;IAC/C,UAAU,EAAE;QACV,mDAAmD;QACnD,+CAA+C;KAChD;IACD,GAAG,EAAE,SAAS;IACd,KAAK,EAAE,iCAAiC;IACxC,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;IACvC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,QAAQ,GACZ,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YACtC,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YACpD,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAE7C,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;QAEzB,MAAM,QAAQ,GAAG,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,4BAA4B,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,4BAA4B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;gBAClD,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { grepRule } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'OBS-002',
|
|
4
|
+
title: 'Unhandled promise rejection / missing global error handler',
|
|
5
|
+
layer: 'observability',
|
|
6
|
+
severity: 'medium',
|
|
7
|
+
description: 'Node.js servislerinde `process.on(\'unhandledRejection\')` ve `process.on(\'uncaughtException\')` handler\'lari yoksa process crash\'ler sessizce olur, security event\'leri kaybolur, monitoring bos kalir.',
|
|
8
|
+
threat: 'Silent crashes, missed security signals, denial of service via uncaught errors',
|
|
9
|
+
remediation: 'Production\'da mutlaka global handler kurun: ' +
|
|
10
|
+
'`process.on(\'unhandledRejection\', (err) => { logger.error(err); metrics.increment(\'unhandled_rejection\'); })` ve ' +
|
|
11
|
+
'`process.on(\'uncaughtException\', (err) => { logger.fatal(err); process.exit(1); })`. ' +
|
|
12
|
+
'Express icin en sonda `app.use((err, req, res, next) => { ... })` error middleware. ' +
|
|
13
|
+
'Worker queue\'larda failed job\'lari retry queue\'ya yonlendirin.',
|
|
14
|
+
references: [
|
|
15
|
+
'https://nodejs.org/api/process.html#warning-using-uncaughtexception-correctly',
|
|
16
|
+
'https://expressjs.com/en/guide/error-handling.html',
|
|
17
|
+
],
|
|
18
|
+
cwe: 'CWE-754',
|
|
19
|
+
owasp: 'A09:2021 Security Logging and Monitoring Failures',
|
|
20
|
+
languages: ['javascript', 'typescript'],
|
|
21
|
+
check: (ctx) => {
|
|
22
|
+
const isServerEntry = /(?:server|app|main|index)\.(?:ts|js)$/i.test(ctx.relativePath);
|
|
23
|
+
if (!isServerEntry)
|
|
24
|
+
return [];
|
|
25
|
+
const hasUnhandled = /unhandledRejection|uncaughtException/.test(ctx.source);
|
|
26
|
+
if (hasUnhandled)
|
|
27
|
+
return [];
|
|
28
|
+
const findings = [];
|
|
29
|
+
findings.push(...grepRule(rule, ctx, /listen\s*\(\s*\d+/g));
|
|
30
|
+
return findings;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export default rule;
|
|
34
|
+
//# sourceMappingURL=errorHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../../../src/engine/rules/observability/errorHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,IAAI,GAAS;IACjB,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,4DAA4D;IACnE,KAAK,EAAE,eAAe;IACtB,QAAQ,EAAE,QAAQ;IAClB,WAAW,EACT,8MAA8M;IAChN,MAAM,EAAE,gFAAgF;IACxF,WAAW,EACT,+CAA+C;QAC/C,uHAAuH;QACvH,yFAAyF;QACzF,sFAAsF;QACtF,mEAAmE;IACrE,UAAU,EAAE;QACV,+EAA+E;QAC/E,oDAAoD;KACrD;IACD,GAAG,EAAE,SAAS;IACd,KAAK,EAAE,mDAAmD;IAC1D,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;IACvC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,aAAa,GAAG,wCAAwC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACtF,IAAI,CAAC,aAAa;YAAE,OAAO,EAAE,CAAC;QAE9B,MAAM,YAAY,GAAG,sCAAsC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7E,IAAI,YAAY;YAAE,OAAO,EAAE,CAAC;QAE5B,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,oBAAoB,CAAC,CAAC,CAAC;QAC5D,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/engine/rules/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO;IACP,YAAY;CACb,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { grepRule } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'OBS-001',
|
|
4
|
+
title: 'Sensitive data exposed via logs (PII / stack trace / console.log in prod)',
|
|
5
|
+
layer: 'observability',
|
|
6
|
+
severity: 'medium',
|
|
7
|
+
description: 'Log\'a parola, kart numarasi, token, session cookie veya kullanici kimlik bilgisi basilmasi, log toplayici sizintisinda GDPR/KVKK ihlali olusturur. Stack trace\'in production response\'una donmesi bilgi ifshasidir.',
|
|
8
|
+
threat: 'PII leakage via logs, information disclosure via error responses, compliance violation',
|
|
9
|
+
remediation: '1) Production response\'larinda ASLA stack trace / `error.stack` / ic detay donmeyin. Generic 500 + correlation id. ' +
|
|
10
|
+
'2) Log\'a PII gondermeden once redact edin (`***-mask`). ' +
|
|
11
|
+
'3) Parola, token, CVV, PAN gibi alanlari logger\'a gecmeyin. ' +
|
|
12
|
+
'4) Merkezi log (ELK, Datadog, Sentry) ile PII redaction rules kurun. ' +
|
|
13
|
+
'5) Anomali tespiti icin SIEM (Splunk, Sentinel) ile alerting. ' +
|
|
14
|
+
'6) `console.log` production\'da birakilabilir ama debug amacli PII tasimamali.',
|
|
15
|
+
references: [
|
|
16
|
+
'https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html',
|
|
17
|
+
'https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure',
|
|
18
|
+
],
|
|
19
|
+
cwe: 'CWE-532',
|
|
20
|
+
owasp: 'A09:2021 Security Logging and Monitoring Failures',
|
|
21
|
+
languages: ['javascript', 'typescript', 'python', 'java', 'go'],
|
|
22
|
+
check: (ctx) => {
|
|
23
|
+
const patterns = [
|
|
24
|
+
/console\.log\s*\([^)]*(?:password|passwd|pwd|token|secret|api[_-]?key|cvv|cardNumber|ssn|tcKimlik)/gi,
|
|
25
|
+
/logger?\.(?:info|debug|warn)\s*\([^)]*(?:password|passwd|pwd|token|secret|api[_-]?key|cvv|cardNumber|ssn|tcKimlik)/gi,
|
|
26
|
+
/res\.(?:send|json)\s*\(\s*\{\s*[^}]*error\s*:\s*err\.stack/gi,
|
|
27
|
+
/res\.(?:send|json)\s*\(\s*err\.stack/gi,
|
|
28
|
+
/print\s*\(\s*[^)]*(?:password|secret|token|api[_-]?key)/gi,
|
|
29
|
+
];
|
|
30
|
+
const findings = [];
|
|
31
|
+
for (const re of patterns) {
|
|
32
|
+
findings.push(...grepRule(rule, ctx, re));
|
|
33
|
+
}
|
|
34
|
+
return findings;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
export default rule;
|
|
38
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../../../src/engine/rules/observability/logging.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,IAAI,GAAS;IACjB,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,2EAA2E;IAClF,KAAK,EAAE,eAAe;IACtB,QAAQ,EAAE,QAAQ;IAClB,WAAW,EACT,wNAAwN;IAC1N,MAAM,EAAE,wFAAwF;IAChG,WAAW,EACT,sHAAsH;QACtH,2DAA2D;QAC3D,+DAA+D;QAC/D,uEAAuE;QACvE,gEAAgE;QAChE,gFAAgF;IAClF,UAAU,EAAE;QACV,yEAAyE;QACzE,4EAA4E;KAC7E;IACD,GAAG,EAAE,SAAS;IACd,KAAK,EAAE,mDAAmD;IAC1D,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC;IAC/D,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,QAAQ,GAAa;YAC/B,sGAAsG;YAChG,sHAAsH;YAC5H,8DAA8D;YACxD,wCAAwC;YAC9C,2DAA2D;SACtD,CAAC;QAEF,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/engine/rules/php/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,YAAY;IACZ,GAAG;IACH,WAAW;CACZ,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { lineColumnFromIndex, snippetAt } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'PHP-001',
|
|
4
|
+
title: 'PHP: SQL injection via string concatenation',
|
|
5
|
+
layer: 'backend',
|
|
6
|
+
severity: 'critical',
|
|
7
|
+
description: 'PHP mysqli / PDO queries built via string concatenation or interpolation allow attackers to inject SQL through any user-controlled parameter.',
|
|
8
|
+
threat: 'Database exfiltration, authentication bypass, data destruction, full server compromise',
|
|
9
|
+
remediation: '1) Use PDO prepared statements: `$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id])`. ' +
|
|
10
|
+
'2) Use mysqli prepared: `$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?"); $stmt->bind_param("i", $id)`. ' +
|
|
11
|
+
'3) For Eloquent / Laravel query builder: `User::where("id", $id)->first()`. ' +
|
|
12
|
+
'4) NEVER use `"SELECT * FROM users WHERE id = $id"` or `.="..."`. ' +
|
|
13
|
+
'5) For variable table/column names: validate against an allowlist.',
|
|
14
|
+
references: [
|
|
15
|
+
'https://www.php.net/manual/en/pdo.prepared-statements.php',
|
|
16
|
+
'https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php',
|
|
17
|
+
'https://owasp.org/www-community/attacks/SQL_Injection',
|
|
18
|
+
],
|
|
19
|
+
cwe: 'CWE-89',
|
|
20
|
+
owasp: 'A03:2021 Injection',
|
|
21
|
+
languages: ['php'],
|
|
22
|
+
check: (ctx) => {
|
|
23
|
+
const findings = [];
|
|
24
|
+
const patterns = [
|
|
25
|
+
/\$_(?:GET|POST|REQUEST|COOKIE|SERVER)\s*\[/g,
|
|
26
|
+
/\$this->input->get\(/g,
|
|
27
|
+
/\bquery\s*\(\s*["'][^"']*["']\s*\.\s*\$_/gi,
|
|
28
|
+
/->query\s*\(\s*["'][^"']*["']\s*\.\s*\$_/gi,
|
|
29
|
+
/->prepare\s*\(\s*["'][^"']*["']\s*\.\s*\$_/gi,
|
|
30
|
+
/mysqli_query\s*\(\s*[^,]+,\s*["'][^"']*["']\s*\.\s*\$_/gi,
|
|
31
|
+
];
|
|
32
|
+
for (const re of patterns) {
|
|
33
|
+
for (const m of ctx.source.matchAll(re)) {
|
|
34
|
+
if (m.index === undefined)
|
|
35
|
+
continue;
|
|
36
|
+
const { line } = lineColumnFromIndex(ctx.source, m.index);
|
|
37
|
+
findings.push({
|
|
38
|
+
id: `${rule.id}-${ctx.relativePath}-${line}`,
|
|
39
|
+
ruleId: rule.id,
|
|
40
|
+
title: rule.title,
|
|
41
|
+
layer: rule.layer,
|
|
42
|
+
severity: rule.severity,
|
|
43
|
+
file: ctx.relativePath,
|
|
44
|
+
match: { snippet: snippetAt(ctx.source, line), line, column: m.index },
|
|
45
|
+
description: rule.description,
|
|
46
|
+
impact: rule.threat,
|
|
47
|
+
remediation: rule.remediation,
|
|
48
|
+
references: rule.references,
|
|
49
|
+
cwe: rule.cwe,
|
|
50
|
+
owasp: rule.owasp,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return findings;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
export default rule;
|
|
58
|
+
//# sourceMappingURL=sqlInjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlInjection.js","sourceRoot":"","sources":["../../../../src/engine/rules/php/sqlInjection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhE,MAAM,IAAI,GAAS;IACjB,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,6CAA6C;IACpD,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,UAAU;IACpB,WAAW,EACT,+IAA+I;IACjJ,MAAM,EAAE,wFAAwF;IAChG,WAAW,EACT,sHAAsH;QACtH,uHAAuH;QACvH,8EAA8E;QAC9E,oEAAoE;QACpE,oEAAoE;IACtE,UAAU,EAAE;QACV,2DAA2D;QAC3D,yEAAyE;QACzE,uDAAuD;KACxD;IACD,GAAG,EAAE,QAAQ;IACb,KAAK,EAAE,oBAAoB;IAC3B,SAAS,EAAE,CAAC,KAAK,CAAC;IAClB,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG;YACf,6CAA6C;YAC7C,uBAAuB;YACvB,4CAA4C;YAC5C,4CAA4C;YAC5C,8CAA8C;YAC9C,0DAA0D;SAC3D,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;oBAAE,SAAS;gBACpC,MAAM,EAAE,IAAI,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC1D,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,YAAY,IAAI,IAAI,EAAE;oBAC5C,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,IAAI,EAAE,GAAG,CAAC,YAAY;oBACtB,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE;oBACtE,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { grepRule } from '../_helpers.js';
|
|
2
|
+
const rule = {
|
|
3
|
+
id: 'PHP-003',
|
|
4
|
+
title: 'PHP: weak password hashing (md5 / sha1 / sha256)',
|
|
5
|
+
layer: 'backend',
|
|
6
|
+
severity: 'critical',
|
|
7
|
+
description: 'Using `md5()`, `sha1()`, or `sha256()` for password hashing is broken — modern hardware cracks these in seconds. Use `password_hash($password, PASSWORD_BCRYPT)` or `PASSWORD_ARGON2ID`.',
|
|
8
|
+
threat: 'Mass credential disclosure if database leaks',
|
|
9
|
+
remediation: '1) Use `password_hash($pw, PASSWORD_BCRYPT, ["cost" => 12])` for bcrypt (PHP 5.5+). ' +
|
|
10
|
+
'2) Or `password_hash($pw, PASSWORD_ARGON2ID)` for Argon2id (PHP 7.2+). ' +
|
|
11
|
+
'3) Verify with `password_verify($pw, $hash)`. ' +
|
|
12
|
+
'4) NEVER use `md5`, `sha1`, `sha256`, `hash("md5", ...)` for passwords. ' +
|
|
13
|
+
'5) For legacy hashes, rehash on next successful login: if (password_verify(...)) { $new = password_hash(...) }.',
|
|
14
|
+
references: [
|
|
15
|
+
'https://www.php.net/manual/en/function.password-hash.php',
|
|
16
|
+
'https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html',
|
|
17
|
+
],
|
|
18
|
+
cwe: 'CWE-916',
|
|
19
|
+
owasp: 'A02:2021 Cryptographic Failures',
|
|
20
|
+
languages: ['php'],
|
|
21
|
+
check: (ctx) => {
|
|
22
|
+
const findings = [];
|
|
23
|
+
const patterns = [
|
|
24
|
+
/\bmd5\s*\(\s*\$_/gi,
|
|
25
|
+
/\bsha1\s*\(\s*\$_/gi,
|
|
26
|
+
/\bsha256\s*\(\s*\$_/gi,
|
|
27
|
+
/\bhash\s*\(\s*['"`](?:md5|sha1|sha256)['"`]/gi,
|
|
28
|
+
];
|
|
29
|
+
for (const re of patterns) {
|
|
30
|
+
findings.push(...grepRule(rule, ctx, re));
|
|
31
|
+
}
|
|
32
|
+
return findings;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export default rule;
|
|
36
|
+
//# sourceMappingURL=weakHashing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weakHashing.js","sourceRoot":"","sources":["../../../../src/engine/rules/php/weakHashing.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,IAAI,GAAS;IACjB,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,kDAAkD;IACzD,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,UAAU;IACpB,WAAW,EACT,0LAA0L;IAC5L,MAAM,EAAE,8CAA8C;IACtD,WAAW,EACT,sFAAsF;QACtF,yEAAyE;QACzE,gDAAgD;QAChD,0EAA0E;QAC1E,iHAAiH;IACnH,UAAU,EAAE;QACV,0DAA0D;QAC1D,kFAAkF;KACnF;IACD,GAAG,EAAE,SAAS;IACd,KAAK,EAAE,iCAAiC;IACxC,SAAS,EAAE,CAAC,KAAK,CAAC;IAClB,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG;YACf,oBAAoB;YACpB,qBAAqB;YACrB,uBAAuB;YACvB,+CAA+C;SAChD,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|