@profullstack/threatcrush 0.9.0 → 0.10.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/dist/daemon.js CHANGED
@@ -5135,6 +5135,155 @@ var CODE_RULES = [
5135
5135
  // constant the author wrote and is not a finding.
5136
5136
  pattern: /\btemplate\s*\.\s*(?:HTML|JS|CSS|HTMLAttr|URL|Srcset)\s*\(\s*(?!\s*[`"])/,
5137
5137
  needsContext: true
5138
+ },
5139
+ // ── Misconfiguration, weak crypto and the rest of the injection family ────
5140
+ //
5141
+ // Each of these is a defect the *line* shows — a debug flag left on, a
5142
+ // wildcard CORS origin, a key literal, a fast password hash — so the safe
5143
+ // counterpart in the corpus differs on something visible here, not three
5144
+ // functions away. The classes that genuinely need whole-function reasoning
5145
+ // (CSRF, IDOR, TOCTOU, missing authorization) are deliberately still absent;
5146
+ // see KNOWN_GAPS.
5147
+ {
5148
+ id: "py-framework-debug-enabled",
5149
+ title: "debug mode enabled",
5150
+ consequence: "Framework debug mode serves an interactive traceback console on any error \u2014 arbitrary code execution to whoever triggers it \u2014 and leaks source and configuration.",
5151
+ cwe: "CWE-489",
5152
+ severity: "high",
5153
+ languages: ["python"],
5154
+ pattern: /\bDEBUG['"\]]*\s*[=:]\s*True\b|\.\s*run\s*\([^)\n]*\bdebug\s*=\s*True\b/,
5155
+ inherent: true
5156
+ },
5157
+ {
5158
+ id: "js-cors-wildcard-credentials",
5159
+ title: "wildcard CORS origin with credentials",
5160
+ consequence: "A `*` origin combined with credentials lets any site read authenticated responses on the victim\u2019s behalf: the browser attaches their cookies and hands the result to the attacker\u2019s page.",
5161
+ cwe: "CWE-942",
5162
+ severity: "high",
5163
+ languages: ["javascript", "typescript"],
5164
+ pattern: /origin\s*:\s*['"`]\*['"`][^\n]*credentials\s*:\s*true|credentials\s*:\s*true[^\n]*origin\s*:\s*['"`]\*['"`]/,
5165
+ inherent: true
5166
+ },
5167
+ {
5168
+ id: "js-cookie-insecure-flag",
5169
+ title: "cookie set with Secure disabled",
5170
+ consequence: "Without Secure the cookie travels over plain HTTP, where anyone on the path reads it. A session cookie set this way is a session anyone can lift.",
5171
+ cwe: "CWE-614",
5172
+ severity: "medium",
5173
+ languages: ["javascript", "typescript"],
5174
+ pattern: /\.\s*cookie\s*\([^\n]*\bsecure\s*:\s*false\b/i
5175
+ },
5176
+ {
5177
+ id: "js-hardcoded-crypto-key",
5178
+ title: "hardcoded key material",
5179
+ consequence: "A key committed to source is a key everyone with the repo has. The encryption it backs protects nothing once the source is shared, forked or leaked.",
5180
+ cwe: "CWE-321",
5181
+ severity: "high",
5182
+ languages: ["javascript", "typescript"],
5183
+ pattern: /\b(?:key|secret|iv|passphrase|salt|hmac)\w*\s*=\s*Buffer\s*\.\s*from\s*\(\s*['"`]/i,
5184
+ fileRequires: /\bcrypto\b|createCipheriv|createDecipheriv|createHmac/
5185
+ },
5186
+ {
5187
+ id: "py-hardcoded-secret-key",
5188
+ title: "hardcoded application secret",
5189
+ consequence: "A signing secret in source lets anyone with the code forge what it signs \u2014 session cookies, tokens, password-reset links.",
5190
+ cwe: "CWE-798",
5191
+ severity: "high",
5192
+ languages: ["python"],
5193
+ // Assigned a *string literal*. A value from a provider call (`os.environ`,
5194
+ // `secret_provider(...)`) is the correct shape and starts with an
5195
+ // identifier after the `=`, not a quote.
5196
+ pattern: /\b(?:SECRET_KEY|JWT_SECRET|SIGNING_KEY|SESSION_SECRET|PRIVATE_KEY)['"\]]*\s*[=:]\s*['"`][^'"`\n]{6,}/
5197
+ },
5198
+ {
5199
+ id: "py-ldap-injection",
5200
+ title: "LDAP filter built by interpolation",
5201
+ consequence: "Unescaped input in an LDAP filter lets an attacker rewrite the query \u2014 widening a match, bypassing a check, or enumerating the directory.",
5202
+ cwe: "CWE-90",
5203
+ severity: "high",
5204
+ languages: ["python"],
5205
+ // An f-string whose content is an LDAP filter (`(&…` / `(|…`) with an
5206
+ // interpolation. The safe form escapes, so the window carries an escaper.
5207
+ pattern: /\bf['"][^'"\n]*\([&|][^'"\n]*\{[^}\n]+\}/,
5208
+ guard: /escap/i
5209
+ },
5210
+ {
5211
+ id: "py-xpath-injection",
5212
+ title: "XPath built by interpolation",
5213
+ consequence: "Unescaped input in an XPath expression lets an attacker rewrite the query and read nodes it was meant to exclude.",
5214
+ cwe: "CWE-643",
5215
+ severity: "high",
5216
+ languages: ["python"],
5217
+ pattern: /\bf['"][^'"\n]*(?:\/\/|\/\w+\[)[^'"\n]*\{[^}\n]+\}/
5218
+ },
5219
+ {
5220
+ id: "py-fast-password-hash",
5221
+ title: "password hashed with a fast digest",
5222
+ consequence: "SHA-2 is built to be fast, which is exactly wrong for a password: a leaked hash is brute-forced at billions of guesses a second. Passwords need a slow, salted KDF (bcrypt, scrypt, argon2, PBKDF2).",
5223
+ cwe: "CWE-759",
5224
+ severity: "high",
5225
+ languages: ["python"],
5226
+ pattern: /\bhashlib\s*\.\s*(?:sha224|sha256|sha384|sha512)\s*\([^)\n]*(?:password|passwd|passphrase|pwd)/i,
5227
+ guard: /pbkdf2|scrypt|bcrypt|argon/i
5228
+ },
5229
+ {
5230
+ id: "py-plaintext-password-retained",
5231
+ title: "plaintext password stored",
5232
+ consequence: "A record that keeps the password itself, not a hash, turns one database leak into every user\u2019s credential \u2014 reused across every other site they log into.",
5233
+ cwe: "CWE-256",
5234
+ severity: "high",
5235
+ languages: ["python"],
5236
+ pattern: /['"]password['"]\s*:\s*(?:form|request|req|data|payload|body|params)\b/i
5237
+ },
5238
+ {
5239
+ id: "js-timing-unsafe-mac-compare",
5240
+ title: "MAC or signature compared with ==",
5241
+ consequence: "`===` on a signature returns the moment a byte differs, so response time leaks how much of a forged signature is correct \u2014 enough to recover a valid one byte by byte. Use `crypto.timingSafeEqual`.",
5242
+ cwe: "CWE-208",
5243
+ severity: "medium",
5244
+ languages: ["javascript", "typescript"],
5245
+ pattern: /\b\w*(?:[Ss]ignature|[Hh]mac|[Dd]igest)\s*===?\s*\w|\w\s*===?\s*\w*(?:[Ss]ignature|[Hh]mac|[Dd]igest)\b/,
5246
+ // Comparing `.length` is the *safe* preamble to a constant-time check, not
5247
+ // the timing-unsafe value comparison this rule is about — and the
5248
+ // `timingSafeEqual` that follows it sits forward of the line, out of the
5249
+ // backward guard window.
5250
+ lineGuard: /\.\s*length\b/,
5251
+ guard: /timingSafeEqual/
5252
+ },
5253
+ {
5254
+ id: "js-predictable-cipher-iv",
5255
+ title: "static initialization vector",
5256
+ consequence: "A fixed IV reused across encryptions leaks whether two plaintexts are equal and, in CBC/CTR, breaks confidentiality outright. The IV must be random per message.",
5257
+ cwe: "CWE-329",
5258
+ severity: "high",
5259
+ languages: ["javascript", "typescript"],
5260
+ pattern: /\b\w*[Ii][Vv]\s*=\s*Buffer\s*\.\s*(?:alloc|from)\s*\(/,
5261
+ fileRequires: /createCipheriv|\bcrypto\b/,
5262
+ guard: /randomBytes|randomFill/
5263
+ },
5264
+ // A rule for `Math.random().toString(36)` was tried and dropped: the exact
5265
+ // shape generates security tokens *and* benign callback/correlation ids
5266
+ // (Capacitor's native bridge uses it for the latter), with no line-visible
5267
+ // signal between them. The credential-scoped `insecure-randomness-for-secret`
5268
+ // above still catches the `token = …Math.random…` case; the bare shape is
5269
+ // left alone rather than flagged on every id generator.
5270
+ {
5271
+ id: "js-mass-assignment",
5272
+ title: "mass assignment from request data",
5273
+ consequence: "Copying the whole request body onto a record lets a caller set fields you never exposed \u2014 `isAdmin`, `role`, `balance` \u2014 because nothing stands between the input and the object.",
5274
+ cwe: "CWE-915",
5275
+ severity: "high",
5276
+ languages: ["javascript", "typescript"],
5277
+ pattern: /\bObject\s*\.\s*assign\s*\([^,\n]+,\s*(?:req|request|ctx)\s*\.\s*(?:body|query|params)\b/
5278
+ },
5279
+ {
5280
+ id: "js-header-injection",
5281
+ title: "response header set from request input",
5282
+ consequence: "A CR/LF in the value splits the response \u2014 the attacker injects headers or a whole second response (cache poisoning, a forged Set-Cookie).",
5283
+ cwe: "CWE-113",
5284
+ severity: "high",
5285
+ languages: ["javascript", "typescript"],
5286
+ pattern: /\.\s*(?:setHeader|header|set)\s*\(\s*['"`][^'"`\n]+['"`]\s*,\s*(?:req|request|ctx)\s*\.\s*(?:query|body|params|headers)\b/
5138
5287
  }
5139
5288
  ];
5140
5289
  var COMMENT_PREFIX = /^\s*(?:\/\/|\/\*|\*|#|--|<!--)/;