@vetala/vetala 0.1.0-beta
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.
Potentially problematic release.
This version of @vetala/vetala might be problematic. Click here for more details.
- package/CONTRIBUTING.md +77 -0
- package/LICENSE +184 -0
- package/README.md +136 -0
- package/THIRD_PARTY_LICENSES.md +17 -0
- package/dist/src/agent.d.ts +30 -0
- package/dist/src/agent.js +216 -0
- package/dist/src/agent.js.map +1 -0
- package/dist/src/approvals.d.ts +18 -0
- package/dist/src/approvals.js +81 -0
- package/dist/src/approvals.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +87 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts +12 -0
- package/dist/src/config.js +183 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/context-memory.d.ts +7 -0
- package/dist/src/context-memory.js +96 -0
- package/dist/src/context-memory.js.map +1 -0
- package/dist/src/ink/command-suggestions.d.ts +7 -0
- package/dist/src/ink/command-suggestions.js +179 -0
- package/dist/src/ink/command-suggestions.js.map +1 -0
- package/dist/src/ink/ink-terminal-ui.d.ts +36 -0
- package/dist/src/ink/ink-terminal-ui.js +79 -0
- package/dist/src/ink/ink-terminal-ui.js.map +1 -0
- package/dist/src/ink/repl-app.d.ts +9 -0
- package/dist/src/ink/repl-app.js +789 -0
- package/dist/src/ink/repl-app.js.map +1 -0
- package/dist/src/ink/transcript-cards.d.ts +6 -0
- package/dist/src/ink/transcript-cards.js +24 -0
- package/dist/src/ink/transcript-cards.js.map +1 -0
- package/dist/src/path-policy.d.ts +11 -0
- package/dist/src/path-policy.js +67 -0
- package/dist/src/path-policy.js.map +1 -0
- package/dist/src/process-utils.d.ts +13 -0
- package/dist/src/process-utils.js +52 -0
- package/dist/src/process-utils.js.map +1 -0
- package/dist/src/repl.d.ts +9 -0
- package/dist/src/repl.js +13 -0
- package/dist/src/repl.js.map +1 -0
- package/dist/src/sarvam/client.d.ts +15 -0
- package/dist/src/sarvam/client.js +208 -0
- package/dist/src/sarvam/client.js.map +1 -0
- package/dist/src/sarvam/models.d.ts +2 -0
- package/dist/src/sarvam/models.js +7 -0
- package/dist/src/sarvam/models.js.map +1 -0
- package/dist/src/search-provider.d.ts +6 -0
- package/dist/src/search-provider.js +8 -0
- package/dist/src/search-provider.js.map +1 -0
- package/dist/src/session-store.d.ts +19 -0
- package/dist/src/session-store.js +318 -0
- package/dist/src/session-store.js.map +1 -0
- package/dist/src/skills/runtime.d.ts +26 -0
- package/dist/src/skills/runtime.js +317 -0
- package/dist/src/skills/runtime.js.map +1 -0
- package/dist/src/skills/types.d.ts +25 -0
- package/dist/src/skills/types.js +2 -0
- package/dist/src/skills/types.js.map +1 -0
- package/dist/src/terminal-ui.d.ts +29 -0
- package/dist/src/terminal-ui.js +236 -0
- package/dist/src/terminal-ui.js.map +1 -0
- package/dist/src/tools/filesystem.d.ts +2 -0
- package/dist/src/tools/filesystem.js +622 -0
- package/dist/src/tools/filesystem.js.map +1 -0
- package/dist/src/tools/git.d.ts +2 -0
- package/dist/src/tools/git.js +326 -0
- package/dist/src/tools/git.js.map +1 -0
- package/dist/src/tools/index.d.ts +6 -0
- package/dist/src/tools/index.js +21 -0
- package/dist/src/tools/index.js.map +1 -0
- package/dist/src/tools/registry.d.ts +15 -0
- package/dist/src/tools/registry.js +59 -0
- package/dist/src/tools/registry.js.map +1 -0
- package/dist/src/tools/shell.d.ts +2 -0
- package/dist/src/tools/shell.js +97 -0
- package/dist/src/tools/shell.js.map +1 -0
- package/dist/src/tools/skill.d.ts +3 -0
- package/dist/src/tools/skill.js +130 -0
- package/dist/src/tools/skill.js.map +1 -0
- package/dist/src/tools/web.d.ts +3 -0
- package/dist/src/tools/web.js +144 -0
- package/dist/src/tools/web.js.map +1 -0
- package/dist/src/types.d.ts +236 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/workspace-trust.d.ts +3 -0
- package/dist/src/workspace-trust.js +31 -0
- package/dist/src/workspace-trust.js.map +1 -0
- package/dist/src/xdg.d.ts +9 -0
- package/dist/src/xdg.js +77 -0
- package/dist/src/xdg.js.map +1 -0
- package/package.json +57 -0
- package/skill/agents-md-generator/SKILL.md +75 -0
- package/skill/agents-md-generator/references/agents_md_template.md +160 -0
- package/skill/agents-md-generator/references/loc_measurement.md +67 -0
- package/skill/agents-md-generator/references/monorepo_detection.md +78 -0
- package/skill/agents-md-generator/references/monorepo_strategy.md +60 -0
- package/skill/agents-md-generator/references/read_only_commands.md +151 -0
- package/skill/agents-md-generator/references/update_strategy.md +160 -0
- package/skill/agents-md-generator/references/working_agreements.md +53 -0
- package/skill/biz-opportunity-scout/SKILL.md +53 -0
- package/skill/biz-opportunity-scout/references/competitive_analysis.md +84 -0
- package/skill/biz-opportunity-scout/references/market_sizing.md +68 -0
- package/skill/biz-opportunity-scout/references/pmf_indicators.md +94 -0
- package/skill/biz-opportunity-scout/references/report_template.md +243 -0
- package/skill/biz-opportunity-scout/references/unit_economics.md +97 -0
- package/skill/code-review/SKILL.md +86 -0
- package/skill/code-review/references/change_analysis.md +116 -0
- package/skill/code-review/references/git_operations.md +115 -0
- package/skill/code-review/references/impact_detection.md +149 -0
- package/skill/code-review/references/output_format.md +137 -0
- package/skill/code-review/references/severity_criteria.md +100 -0
- package/skill/code-security-audit/SKILL.md +123 -0
- package/skill/code-security-audit/references/audit_process.md +277 -0
- package/skill/code-security-audit/references/remediation_patterns.md +599 -0
- package/skill/code-security-audit/references/report_format.md +391 -0
- package/skill/code-security-audit/references/security_domains.md +830 -0
- package/skill/code-security-audit/references/vulnerability_patterns.md +813 -0
- package/skill/composition-patterns/SKILL.md +83 -0
- package/skill/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skill/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skill/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skill/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skill/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skill/composition-patterns/rules/state-context-interface.md +191 -0
- package/skill/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skill/composition-patterns/rules/state-lift-state.md +125 -0
- package/skill/deploy-to-vercel/SKILL.md +293 -0
- package/skill/deploy-to-vercel/resources/deploy-sandbox.sh +301 -0
- package/skill/deploy-to-vercel/resources/deploy.sh +301 -0
- package/skill/doc/SKILL_GUIDELINES.md +138 -0
- package/skill/git-workflow/SKILL.md +94 -0
- package/skill/git-workflow/references/advanced-git.md +632 -0
- package/skill/git-workflow/references/branching-strategies.md +344 -0
- package/skill/git-workflow/references/ci-cd-integration.md +683 -0
- package/skill/git-workflow/references/code-quality-tools.md +351 -0
- package/skill/git-workflow/references/commit-conventions.md +439 -0
- package/skill/git-workflow/references/github-releases.md +288 -0
- package/skill/git-workflow/references/pull-request-workflow.md +773 -0
- package/skill/git-workflow/scripts/verify-git-workflow.sh +263 -0
- package/skill/jetbrains-vmoptions/SKILL.md +51 -0
- package/skill/jetbrains-vmoptions/references/common-options.md +357 -0
- package/skill/jetbrains-vmoptions/references/gc-options.md +350 -0
- package/skill/jetbrains-vmoptions/references/memory-options.md +339 -0
- package/skill/jetbrains-vmoptions/references/prerequisite-check.md +65 -0
- package/skill/kysely-converter/SKILL.md +62 -0
- package/skill/kysely-converter/references/delete.md +323 -0
- package/skill/kysely-converter/references/insert.md +386 -0
- package/skill/kysely-converter/references/operators.md +331 -0
- package/skill/kysely-converter/references/select.md +1000 -0
- package/skill/kysely-converter/references/update.md +349 -0
- package/skill/kysely-converter/references/window_function.md +537 -0
- package/skill/react-best-practices/SKILL.md +131 -0
- package/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skill/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skill/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skill/react-best-practices/rules/async-api-routes.md +38 -0
- package/skill/react-best-practices/rules/async-defer-await.md +80 -0
- package/skill/react-best-practices/rules/async-dependencies.md +51 -0
- package/skill/react-best-practices/rules/async-parallel.md +28 -0
- package/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skill/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skill/react-best-practices/rules/bundle-preload.md +50 -0
- package/skill/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skill/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skill/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skill/react-best-practices/rules/js-early-exit.md +50 -0
- package/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skill/react-best-practices/rules/js-index-maps.md +37 -0
- package/skill/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skill/react-best-practices/rules/rendering-activity.md +26 -0
- package/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skill/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skill/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skill/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skill/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skill/react-best-practices/rules/rerender-memo.md +44 -0
- package/skill/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skill/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skill/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skill/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skill/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skill/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skill/react-best-practices/rules/server-cache-react.md +76 -0
- package/skill/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skill/react-best-practices/rules/server-hoist-static-io.md +142 -0
- package/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skill/react-best-practices/rules/server-serialization.md +38 -0
- package/skill/react-native-skills/SKILL.md +115 -0
- package/skill/react-native-skills/rules/animation-derived-value.md +53 -0
- package/skill/react-native-skills/rules/animation-gesture-detector-press.md +95 -0
- package/skill/react-native-skills/rules/animation-gpu-properties.md +65 -0
- package/skill/react-native-skills/rules/design-system-compound-components.md +66 -0
- package/skill/react-native-skills/rules/fonts-config-plugin.md +71 -0
- package/skill/react-native-skills/rules/imports-design-system-folder.md +68 -0
- package/skill/react-native-skills/rules/js-hoist-intl.md +61 -0
- package/skill/react-native-skills/rules/list-performance-callbacks.md +44 -0
- package/skill/react-native-skills/rules/list-performance-function-references.md +132 -0
- package/skill/react-native-skills/rules/list-performance-images.md +53 -0
- package/skill/react-native-skills/rules/list-performance-inline-objects.md +97 -0
- package/skill/react-native-skills/rules/list-performance-item-expensive.md +94 -0
- package/skill/react-native-skills/rules/list-performance-item-memo.md +82 -0
- package/skill/react-native-skills/rules/list-performance-item-types.md +104 -0
- package/skill/react-native-skills/rules/list-performance-virtualize.md +67 -0
- package/skill/react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
- package/skill/react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
- package/skill/react-native-skills/rules/navigation-native-navigators.md +188 -0
- package/skill/react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
- package/skill/react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
- package/skill/react-native-skills/rules/react-state-dispatcher.md +91 -0
- package/skill/react-native-skills/rules/react-state-fallback.md +56 -0
- package/skill/react-native-skills/rules/react-state-minimize.md +65 -0
- package/skill/react-native-skills/rules/rendering-no-falsy-and.md +74 -0
- package/skill/react-native-skills/rules/rendering-text-in-text-component.md +36 -0
- package/skill/react-native-skills/rules/scroll-position-no-state.md +82 -0
- package/skill/react-native-skills/rules/state-ground-truth.md +80 -0
- package/skill/react-native-skills/rules/ui-expo-image.md +66 -0
- package/skill/react-native-skills/rules/ui-image-gallery.md +104 -0
- package/skill/react-native-skills/rules/ui-measure-views.md +78 -0
- package/skill/react-native-skills/rules/ui-menus.md +174 -0
- package/skill/react-native-skills/rules/ui-native-modals.md +77 -0
- package/skill/react-native-skills/rules/ui-pressable.md +61 -0
- package/skill/react-native-skills/rules/ui-safe-area-scroll.md +65 -0
- package/skill/react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
- package/skill/react-native-skills/rules/ui-styling.md +87 -0
- package/skill/react-vite-guide/SKILL.md +101 -0
- package/skill/react-vite-guide/references/composition-patterns.md +709 -0
- package/skill/react-vite-guide/references/performance-optimization.md +1222 -0
- package/skill/react-vite-guide/references/vite-specific.md +385 -0
- package/skill/react-vite-guide/references/web-interface.md +146 -0
- package/skill/skill-maker/SKILL.md +52 -0
- package/skill/skill-maker/references/content_spec.md +67 -0
- package/skill/skill-maker/references/frontmatter_spec.md +96 -0
- package/skill/skill-maker/references/input_validation.md +90 -0
- package/skill/skill-maker/references/skill_structure.md +74 -0
- package/skill/system-prompt-creator/SKILL.md +50 -0
- package/skill/system-prompt-creator/references/data_format_selection.md +135 -0
- package/skill/system-prompt-creator/references/multi_prompt_architecture.md +386 -0
- package/skill/system-prompt-creator/references/prompt_structure.md +140 -0
- package/skill/system-prompt-creator/references/quality_criteria.md +83 -0
- package/skill/typst-creator/SKILL.md +51 -0
- package/skill/typst-creator/references/layout.md +401 -0
- package/skill/typst-creator/references/math.md +297 -0
- package/skill/typst-creator/references/scripting.md +237 -0
- package/skill/typst-creator/references/styling.md +217 -0
- package/skill/typst-creator/references/syntax.md +234 -0
- package/skill/web-design-guidelines/SKILL.md +35 -0
- package/terminal.png +0 -0
|
@@ -0,0 +1,813 @@
|
|
|
1
|
+
# Vulnerability Patterns
|
|
2
|
+
|
|
3
|
+
Concrete code-level vulnerability patterns organized by category. Synthesized from OWASP ASVS 5.0.0, API Security Top 10 2023, CheatSheet Series, and WSTG test scenarios.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [1. Injection](#1-injection)
|
|
8
|
+
- [2. Broken Authentication](#2-broken-authentication)
|
|
9
|
+
- [3. Broken Authorization](#3-broken-authorization)
|
|
10
|
+
- [4. Sensitive Data Exposure](#4-sensitive-data-exposure)
|
|
11
|
+
- [5. Security Misconfiguration](#5-security-misconfiguration)
|
|
12
|
+
- [6. Cross-Site Scripting (XSS)](#6-cross-site-scripting-xss)
|
|
13
|
+
- [7. Insecure Deserialization](#7-insecure-deserialization)
|
|
14
|
+
- [8. Server-Side Request Forgery (SSRF)](#8-server-side-request-forgery-ssrf)
|
|
15
|
+
- [9. Cryptographic Failures](#9-cryptographic-failures)
|
|
16
|
+
- [10. Mass Assignment](#10-mass-assignment)
|
|
17
|
+
- [11. File Handling](#11-file-handling)
|
|
18
|
+
- [12. Business Logic](#12-business-logic)
|
|
19
|
+
- [13. Prototype Pollution](#13-prototype-pollution)
|
|
20
|
+
- [14. Server-Side Template Injection](#14-server-side-template-injection)
|
|
21
|
+
- [15. Improper API Inventory](#15-improper-api-inventory)
|
|
22
|
+
- [16. Cross-Site Request Forgery (CSRF)](#16-cross-site-request-forgery-csrf)
|
|
23
|
+
- [17. XML External Entity (XXE)](#17-xml-external-entity-xxe)
|
|
24
|
+
- [18. Open Redirect](#18-open-redirect)
|
|
25
|
+
- [19. GraphQL Security](#19-graphql-security)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 1. Injection
|
|
30
|
+
|
|
31
|
+
**ASVS**: V1.2 | **API Top 10**: API10:2023 | **WSTG**: WSTG-INPV-05, WSTG-INPV-06, WSTG-INPV-07, WSTG-INPV-12
|
|
32
|
+
|
|
33
|
+
### SQL Injection
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
vulnerable_patterns:
|
|
37
|
+
- pattern: "String concatenation in SQL queries"
|
|
38
|
+
indicators:
|
|
39
|
+
- "\"SELECT * FROM users WHERE id = \" + userId"
|
|
40
|
+
- "f\"SELECT * FROM {table} WHERE id = {id}\""
|
|
41
|
+
- "`SELECT * FROM users WHERE id = ${req.params.id}`"
|
|
42
|
+
- "\"SELECT * FROM users WHERE id = '\" + request.getParameter(\"id\") + \"'\""
|
|
43
|
+
languages: [JavaScript, Python, Java, PHP, C#, Ruby, Go]
|
|
44
|
+
|
|
45
|
+
- pattern: "Dynamic table/column names from user input"
|
|
46
|
+
indicators:
|
|
47
|
+
- "ORDER BY {user_input}"
|
|
48
|
+
- "SELECT {user_columns} FROM"
|
|
49
|
+
- "table name from request parameter"
|
|
50
|
+
|
|
51
|
+
- pattern: "ORM raw query methods with interpolation"
|
|
52
|
+
indicators:
|
|
53
|
+
- "sequelize.query(`SELECT ... ${input}`)"
|
|
54
|
+
- "ActiveRecord.execute(\"SELECT ... #{input}\")"
|
|
55
|
+
- "EntityManager.createNativeQuery(\"SELECT ... \" + input)"
|
|
56
|
+
- "db.raw(`SELECT ... ${input}`)"
|
|
57
|
+
|
|
58
|
+
safe_patterns:
|
|
59
|
+
- "Parameterized queries: db.query('SELECT * FROM users WHERE id = $1', [userId])"
|
|
60
|
+
- "ORM methods: User.findById(userId), User.where(id: userId)"
|
|
61
|
+
- "Query builder: knex('users').where('id', userId)"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### NoSQL Injection
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
vulnerable_patterns:
|
|
68
|
+
- pattern: "User input directly in NoSQL query objects"
|
|
69
|
+
indicators:
|
|
70
|
+
- "db.collection.find({ username: req.body.username, password: req.body.password })"
|
|
71
|
+
- "$where with user input"
|
|
72
|
+
- "JSON.parse(user_input) used in query"
|
|
73
|
+
attack: "{ \"password\": { \"$ne\": \"\" } } bypasses password check"
|
|
74
|
+
|
|
75
|
+
safe_patterns:
|
|
76
|
+
- "Explicit field extraction: { username: String(req.body.username) }"
|
|
77
|
+
- "Schema validation before query construction"
|
|
78
|
+
- "mongo-sanitize or similar input sanitization library"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### OS Command Injection
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
vulnerable_patterns:
|
|
85
|
+
- pattern: "Shell command with user input"
|
|
86
|
+
indicators:
|
|
87
|
+
- "exec(`ping ${host}`)"
|
|
88
|
+
- "os.system(f'ping {host}')"
|
|
89
|
+
- "Runtime.exec(\"ping \" + host)"
|
|
90
|
+
- "shell_exec('ping ' . $host)"
|
|
91
|
+
- "subprocess.call(cmd, shell=True) with user data in cmd"
|
|
92
|
+
|
|
93
|
+
safe_patterns:
|
|
94
|
+
- "subprocess.run(['ping', host], shell=False)"
|
|
95
|
+
- "execFile('ping', [host]) instead of exec()"
|
|
96
|
+
- "ProcessBuilder with argument list"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### LDAP Injection
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
vulnerable_patterns:
|
|
103
|
+
- pattern: "String concatenation in LDAP filter"
|
|
104
|
+
indicators:
|
|
105
|
+
- "\"(uid=\" + username + \")\""
|
|
106
|
+
- "f\"(cn={name})\""
|
|
107
|
+
|
|
108
|
+
safe_patterns:
|
|
109
|
+
- "LDAP filter escaping: ldap.filter.escape_filter_chars(username)"
|
|
110
|
+
- "Parameterized LDAP search libraries"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 2. Broken Authentication
|
|
116
|
+
|
|
117
|
+
**ASVS**: V6, V7, V9 | **API Top 10**: API2:2023 | **WSTG**: WSTG-ATHN-01 to WSTG-ATHN-10
|
|
118
|
+
|
|
119
|
+
### Weak Password Storage
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
vulnerable_patterns:
|
|
123
|
+
- pattern: "Plaintext or weak hash for passwords"
|
|
124
|
+
indicators:
|
|
125
|
+
- "password = req.body.password (stored directly)"
|
|
126
|
+
- "md5(password), sha1(password), sha256(password) for password storage"
|
|
127
|
+
- "hashlib.md5(password.encode()).hexdigest()"
|
|
128
|
+
- "DigestUtils.md5Hex(password)"
|
|
129
|
+
- "No salt used with hash function"
|
|
130
|
+
|
|
131
|
+
safe_patterns:
|
|
132
|
+
- "bcrypt.hash(password, saltRounds)"
|
|
133
|
+
- "argon2.hash(password)"
|
|
134
|
+
- "PBKDF2 with >= 600,000 iterations for SHA-256"
|
|
135
|
+
- "scrypt with appropriate parameters"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### JWT Vulnerabilities
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
vulnerable_patterns:
|
|
142
|
+
- pattern: "Algorithm confusion / none algorithm"
|
|
143
|
+
indicators:
|
|
144
|
+
- "jwt.decode(token, algorithms=['none'])"
|
|
145
|
+
- "jwt.verify(token, secret) without specifying algorithms"
|
|
146
|
+
- "{\"alg\":\"none\"} accepted"
|
|
147
|
+
|
|
148
|
+
- pattern: "Weak signing secret"
|
|
149
|
+
indicators:
|
|
150
|
+
- "jwt.sign(payload, 'secret')"
|
|
151
|
+
- "Short or guessable JWT secret"
|
|
152
|
+
- "Hardcoded JWT secret in source code"
|
|
153
|
+
|
|
154
|
+
- pattern: "Missing validation"
|
|
155
|
+
indicators:
|
|
156
|
+
- "jwt.decode without verify=True"
|
|
157
|
+
- "Expiration (exp) not checked"
|
|
158
|
+
- "Issuer (iss) or audience (aud) not validated"
|
|
159
|
+
|
|
160
|
+
safe_patterns:
|
|
161
|
+
- "jwt.verify(token, publicKey, { algorithms: ['RS256'], issuer: 'expected', audience: 'expected' })"
|
|
162
|
+
- "Strong secret from environment variable, >= 256 bits"
|
|
163
|
+
- "Short expiration time (15 min for access tokens)"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Brute Force / Rate Limiting Gaps
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
vulnerable_patterns:
|
|
170
|
+
- pattern: "No rate limiting on authentication endpoints"
|
|
171
|
+
indicators:
|
|
172
|
+
- "Login endpoint without rate limiter middleware"
|
|
173
|
+
- "Password reset without throttling"
|
|
174
|
+
- "OTP verification without attempt limiting"
|
|
175
|
+
- "GraphQL batching bypasses rate limit (multiple login mutations in one request)"
|
|
176
|
+
|
|
177
|
+
safe_patterns:
|
|
178
|
+
- "express-rate-limit or similar middleware on /login, /register, /reset-password"
|
|
179
|
+
- "Account lockout after N failed attempts"
|
|
180
|
+
- "CAPTCHA after repeated failures"
|
|
181
|
+
- "GraphQL query complexity/depth limiting"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 3. Broken Authorization
|
|
187
|
+
|
|
188
|
+
**ASVS**: V8 | **API Top 10**: API1:2023, API3:2023, API5:2023 | **WSTG**: WSTG-ATHZ-01 to WSTG-ATHZ-04
|
|
189
|
+
|
|
190
|
+
### Missing Object-Level Authorization (BOLA)
|
|
191
|
+
|
|
192
|
+
```yaml
|
|
193
|
+
vulnerable_patterns:
|
|
194
|
+
- pattern: "Data accessed by user-supplied ID without ownership check"
|
|
195
|
+
indicators:
|
|
196
|
+
- "User.findById(req.params.id) without checking req.user.id === record.ownerId"
|
|
197
|
+
- "GET /api/users/:id returns any user's data"
|
|
198
|
+
- "DELETE /api/orders/:orderId without verifying order belongs to requester"
|
|
199
|
+
- "GraphQL resolver fetches by ID without authorization filter"
|
|
200
|
+
|
|
201
|
+
safe_patterns:
|
|
202
|
+
- "User.findOne({ _id: req.params.id, ownerId: req.user.id })"
|
|
203
|
+
- "Policy/guard layer that checks resource ownership before handler"
|
|
204
|
+
- "WHERE user_id = :currentUserId in every data query"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Missing Function-Level Authorization (BFLA)
|
|
208
|
+
|
|
209
|
+
```yaml
|
|
210
|
+
vulnerable_patterns:
|
|
211
|
+
- pattern: "Administrative endpoints without role checks"
|
|
212
|
+
indicators:
|
|
213
|
+
- "/api/admin/* routes without admin middleware"
|
|
214
|
+
- "HTTP method change bypasses auth (GET allowed but DELETE also works)"
|
|
215
|
+
- "Route exists but no @Authorize, @Roles, or guard decorator"
|
|
216
|
+
- "Admin check only on frontend, not backend"
|
|
217
|
+
|
|
218
|
+
safe_patterns:
|
|
219
|
+
- "router.use('/admin', requireRole('admin'))"
|
|
220
|
+
- "@PreAuthorize('hasRole(\"ADMIN\")')"
|
|
221
|
+
- "Centralized authorization middleware applied to all routes"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Broken Object Property Level Authorization
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
vulnerable_patterns:
|
|
228
|
+
- pattern: "Full object returned without field filtering"
|
|
229
|
+
indicators:
|
|
230
|
+
- "res.json(user) — returns all fields including password hash, role, internal IDs"
|
|
231
|
+
- "to_json(), to_dict(), serialize() without field selection"
|
|
232
|
+
- "GraphQL type exposes all model fields"
|
|
233
|
+
|
|
234
|
+
- pattern: "Mass assignment via unfiltered request body"
|
|
235
|
+
indicators:
|
|
236
|
+
- "User.create(req.body) — attacker can set role: 'admin'"
|
|
237
|
+
- "Object.assign(user, req.body)"
|
|
238
|
+
- "user.update(request.data) without field allowlist"
|
|
239
|
+
|
|
240
|
+
safe_patterns:
|
|
241
|
+
- "Explicit field selection: { name: user.name, email: user.email }"
|
|
242
|
+
- "DTO/serializer pattern with allowed fields"
|
|
243
|
+
- "Allowlist: const allowed = pick(req.body, ['name', 'email'])"
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 4. Sensitive Data Exposure
|
|
249
|
+
|
|
250
|
+
**ASVS**: V14, V12 | **API Top 10**: API3:2023 | **WSTG**: WSTG-ATHN-01, WSTG-CONF-09
|
|
251
|
+
|
|
252
|
+
```yaml
|
|
253
|
+
vulnerable_patterns:
|
|
254
|
+
- pattern: "Secrets in source code"
|
|
255
|
+
indicators:
|
|
256
|
+
- "const API_KEY = 'sk-live-...'"
|
|
257
|
+
- "password = 'hardcoded_password'"
|
|
258
|
+
- "AWS_SECRET_ACCESS_KEY in code file"
|
|
259
|
+
- ".env file committed to git"
|
|
260
|
+
search: ["API_KEY", "SECRET", "PASSWORD", "TOKEN", "PRIVATE_KEY", "AWS_", "sk-live", "ghp_"]
|
|
261
|
+
|
|
262
|
+
- pattern: "Sensitive data in logs"
|
|
263
|
+
indicators:
|
|
264
|
+
- "console.log('User login:', { username, password })"
|
|
265
|
+
- "logger.info(f'Request body: {request.body}')"
|
|
266
|
+
- "Log.d(\"Token: \" + authToken)"
|
|
267
|
+
|
|
268
|
+
- pattern: "Sensitive data in URLs"
|
|
269
|
+
indicators:
|
|
270
|
+
- "GET /api/users?token=abc123"
|
|
271
|
+
- "redirect_url contains session token"
|
|
272
|
+
- "API key in query string"
|
|
273
|
+
|
|
274
|
+
- pattern: "Disabled TLS verification"
|
|
275
|
+
indicators:
|
|
276
|
+
- "verify=False (Python requests)"
|
|
277
|
+
- "rejectUnauthorized: false (Node.js)"
|
|
278
|
+
- "InsecureSkipVerify: true (Go)"
|
|
279
|
+
- "CURLOPT_SSL_VERIFYPEER => false (PHP)"
|
|
280
|
+
|
|
281
|
+
safe_patterns:
|
|
282
|
+
- "Environment variables or secrets manager for all credentials"
|
|
283
|
+
- "Structured logging with sensitive field redaction"
|
|
284
|
+
- "Sensitive data in request body (POST), not URL"
|
|
285
|
+
- "TLS verification always enabled"
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## 5. Security Misconfiguration
|
|
291
|
+
|
|
292
|
+
**ASVS**: V13, V3 | **API Top 10**: API8:2023 | **WSTG**: WSTG-CONF-01 to WSTG-CONF-11
|
|
293
|
+
|
|
294
|
+
```yaml
|
|
295
|
+
vulnerable_patterns:
|
|
296
|
+
- pattern: "Debug mode in production"
|
|
297
|
+
indicators:
|
|
298
|
+
- "DEBUG = True (Django)"
|
|
299
|
+
- "app.debug = True (Flask)"
|
|
300
|
+
- "NODE_ENV not set to 'production'"
|
|
301
|
+
- "Spring Boot actuator endpoints exposed"
|
|
302
|
+
|
|
303
|
+
- pattern: "CORS misconfiguration"
|
|
304
|
+
indicators:
|
|
305
|
+
- "Access-Control-Allow-Origin: *"
|
|
306
|
+
- "cors({ origin: true }) — allows any origin"
|
|
307
|
+
- "Origin header reflected without validation"
|
|
308
|
+
- "Access-Control-Allow-Credentials: true with wildcard origin"
|
|
309
|
+
|
|
310
|
+
- pattern: "Missing security headers"
|
|
311
|
+
indicators:
|
|
312
|
+
- "No X-Content-Type-Options header"
|
|
313
|
+
- "No Content-Security-Policy header"
|
|
314
|
+
- "No Strict-Transport-Security header"
|
|
315
|
+
- "X-Powered-By header present (framework fingerprinting)"
|
|
316
|
+
|
|
317
|
+
- pattern: "Verbose error responses"
|
|
318
|
+
indicators:
|
|
319
|
+
- "Stack trace in HTTP response"
|
|
320
|
+
- "Database error details in API response"
|
|
321
|
+
- "Framework default error page in production"
|
|
322
|
+
|
|
323
|
+
safe_patterns:
|
|
324
|
+
- "helmet() middleware (Express), SecurityMiddleware (Django)"
|
|
325
|
+
- "Custom error handler returning generic messages"
|
|
326
|
+
- "CORS with explicit origin allowlist"
|
|
327
|
+
- "X-Powered-By header removed"
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 6. Cross-Site Scripting (XSS)
|
|
333
|
+
|
|
334
|
+
**ASVS**: V1.2, V3.5 | **API Top 10**: API8:2023 | **WSTG**: WSTG-INPV-01, WSTG-INPV-02
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
vulnerable_patterns:
|
|
338
|
+
- pattern: "Reflected/Stored XSS"
|
|
339
|
+
indicators:
|
|
340
|
+
- "innerHTML = userInput"
|
|
341
|
+
- "dangerouslySetInnerHTML={{ __html: userInput }}"
|
|
342
|
+
- "document.write(location.hash)"
|
|
343
|
+
- "<%- userInput %> (EJS unescaped)"
|
|
344
|
+
- "{{ userInput | safe }} (Jinja2/Nunjucks raw)"
|
|
345
|
+
- "|raw (Twig), Html.Raw() (Razor), {!! $var !!} (Blade)"
|
|
346
|
+
- "v-html=\"userInput\" (Vue)"
|
|
347
|
+
|
|
348
|
+
- pattern: "DOM-based XSS"
|
|
349
|
+
indicators:
|
|
350
|
+
- "element.innerHTML = location.search"
|
|
351
|
+
- "document.write(document.referrer)"
|
|
352
|
+
- "eval(window.name)"
|
|
353
|
+
- "setTimeout(userInput)"
|
|
354
|
+
- "jQuery.html(userInput), $(selector).append(userInput)"
|
|
355
|
+
|
|
356
|
+
- pattern: "XSS in URL context"
|
|
357
|
+
indicators:
|
|
358
|
+
- "href=\"javascript:\" + userInput"
|
|
359
|
+
- "<a href={userInput}> without protocol validation"
|
|
360
|
+
- "window.location = userInput"
|
|
361
|
+
|
|
362
|
+
safe_patterns:
|
|
363
|
+
- "textContent instead of innerHTML"
|
|
364
|
+
- "Framework auto-escaping (React JSX, Angular templates, Vue {{ }})"
|
|
365
|
+
- "DOMPurify.sanitize(userInput) for rich text"
|
|
366
|
+
- "URL validation: only http/https protocols allowed"
|
|
367
|
+
- "CSP header restricting inline scripts"
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## 7. Insecure Deserialization
|
|
373
|
+
|
|
374
|
+
**ASVS**: V1.3.2 | **WSTG**: WSTG-INPV-11
|
|
375
|
+
|
|
376
|
+
```yaml
|
|
377
|
+
vulnerable_patterns:
|
|
378
|
+
- pattern: "Untrusted deserialization"
|
|
379
|
+
indicators:
|
|
380
|
+
- "pickle.loads(user_data) (Python)"
|
|
381
|
+
- "yaml.load(user_data) without SafeLoader (Python)"
|
|
382
|
+
- "ObjectInputStream.readObject() on untrusted data (Java)"
|
|
383
|
+
- "unserialize($user_data) (PHP)"
|
|
384
|
+
- "JSON.parse() on large or deeply nested data without limits"
|
|
385
|
+
- "Marshal.load(user_data) (Ruby)"
|
|
386
|
+
- "BinaryFormatter.Deserialize (C#)"
|
|
387
|
+
|
|
388
|
+
safe_patterns:
|
|
389
|
+
- "yaml.safe_load() (Python)"
|
|
390
|
+
- "JSON with schema validation and size limits"
|
|
391
|
+
- "Typed deserialization with allowlist of classes"
|
|
392
|
+
- "No native serialization for untrusted input"
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## 8. Server-Side Request Forgery (SSRF)
|
|
398
|
+
|
|
399
|
+
**ASVS**: V1.3.6, V15.3.2 | **API Top 10**: API7:2023 | **WSTG**: WSTG-INPV-19
|
|
400
|
+
|
|
401
|
+
```yaml
|
|
402
|
+
vulnerable_patterns:
|
|
403
|
+
- pattern: "URL from user input used in server-side request"
|
|
404
|
+
indicators:
|
|
405
|
+
- "fetch(req.body.url)"
|
|
406
|
+
- "requests.get(user_provided_url)"
|
|
407
|
+
- "HttpClient.GetAsync(url_from_input)"
|
|
408
|
+
- "Image download from user-provided URL"
|
|
409
|
+
- "Webhook URL provided by user"
|
|
410
|
+
- "URL preview/unfurl feature"
|
|
411
|
+
targets:
|
|
412
|
+
- "http://169.254.169.254/latest/meta-data/ (cloud metadata)"
|
|
413
|
+
- "http://localhost:PORT (internal services)"
|
|
414
|
+
- "file:///etc/passwd (local files)"
|
|
415
|
+
|
|
416
|
+
safe_patterns:
|
|
417
|
+
- "URL allowlist for permitted domains"
|
|
418
|
+
- "DNS resolution check (reject private IP ranges: 10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x)"
|
|
419
|
+
- "Disable HTTP redirects on server-side requests"
|
|
420
|
+
- "Separate network zone for URL fetching service"
|
|
421
|
+
- "Protocol allowlist (only http/https)"
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## 9. Cryptographic Failures
|
|
427
|
+
|
|
428
|
+
**ASVS**: V11 | **WSTG**: WSTG-CRYP-01 to WSTG-CRYP-04
|
|
429
|
+
|
|
430
|
+
```yaml
|
|
431
|
+
vulnerable_patterns:
|
|
432
|
+
- pattern: "Weak or deprecated algorithms"
|
|
433
|
+
indicators:
|
|
434
|
+
- "DES, 3DES, RC4, Blowfish for encryption"
|
|
435
|
+
- "MD5, SHA-1 for security-sensitive hashing"
|
|
436
|
+
- "RSA with key < 2048 bits"
|
|
437
|
+
- "ECB mode for block cipher"
|
|
438
|
+
|
|
439
|
+
- pattern: "Hardcoded cryptographic material"
|
|
440
|
+
indicators:
|
|
441
|
+
- "const key = Buffer.from('0123456789abcdef')"
|
|
442
|
+
- "iv = b'\\x00' * 16"
|
|
443
|
+
- "Hardcoded salt value"
|
|
444
|
+
|
|
445
|
+
- pattern: "Insecure random number generation"
|
|
446
|
+
indicators:
|
|
447
|
+
- "Math.random() for tokens/secrets"
|
|
448
|
+
- "random.random() for security (Python)"
|
|
449
|
+
- "java.util.Random for security (Java)"
|
|
450
|
+
- "rand() for crypto (C/C++)"
|
|
451
|
+
|
|
452
|
+
safe_patterns:
|
|
453
|
+
- "AES-256-GCM, ChaCha20-Poly1305"
|
|
454
|
+
- "crypto.randomBytes(32) (Node.js), secrets.token_hex(32) (Python)"
|
|
455
|
+
- "SecureRandom (Java), crypto/rand (Go)"
|
|
456
|
+
- "Keys from KMS or secure key store"
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## 10. Mass Assignment
|
|
462
|
+
|
|
463
|
+
**ASVS**: V15.3.3 | **API Top 10**: API3:2023 | **WSTG**: WSTG-INPV-20
|
|
464
|
+
|
|
465
|
+
```yaml
|
|
466
|
+
vulnerable_patterns:
|
|
467
|
+
- pattern: "Direct binding of request body to model"
|
|
468
|
+
indicators:
|
|
469
|
+
- "User.create(req.body)"
|
|
470
|
+
- "user.update_attributes(params)"
|
|
471
|
+
- "Object.assign(model, req.body)"
|
|
472
|
+
- "spread operator: { ...existingData, ...req.body }"
|
|
473
|
+
- "@RequestBody User user without @JsonIgnore on sensitive fields"
|
|
474
|
+
- "form.populate_obj(model) without field restriction"
|
|
475
|
+
|
|
476
|
+
- pattern: "Dangerous fields not protected"
|
|
477
|
+
dangerous_fields: [role, isAdmin, is_staff, is_superuser, verified, email_verified, balance, permissions, password_hash]
|
|
478
|
+
|
|
479
|
+
safe_patterns:
|
|
480
|
+
- "Explicit allowlist: const { name, email } = req.body"
|
|
481
|
+
- "DTO pattern with only permitted fields"
|
|
482
|
+
- "Rails strong parameters: params.require(:user).permit(:name, :email)"
|
|
483
|
+
- "Mongoose select: User.findByIdAndUpdate(id, { $set: { name, email } })"
|
|
484
|
+
- "@JsonIgnoreProperties on sensitive model fields"
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## 11. File Handling
|
|
490
|
+
|
|
491
|
+
**ASVS**: V5 | **API Top 10**: API4:2023 | **WSTG**: WSTG-BUSL-08, WSTG-BUSL-09
|
|
492
|
+
|
|
493
|
+
```yaml
|
|
494
|
+
vulnerable_patterns:
|
|
495
|
+
- pattern: "Path traversal in file operations"
|
|
496
|
+
indicators:
|
|
497
|
+
- "fs.readFile(req.params.filename)"
|
|
498
|
+
- "open(os.path.join(base_dir, user_input))"
|
|
499
|
+
- "File download: '../../../etc/passwd' in filename param"
|
|
500
|
+
|
|
501
|
+
- pattern: "Unrestricted file upload"
|
|
502
|
+
indicators:
|
|
503
|
+
- "No file type validation (extension or content)"
|
|
504
|
+
- "Uploaded file served from web-accessible directory"
|
|
505
|
+
- "No file size limit"
|
|
506
|
+
- "Original filename used for storage"
|
|
507
|
+
|
|
508
|
+
- pattern: "File type validation by extension only"
|
|
509
|
+
indicators:
|
|
510
|
+
- "if filename.endswith('.jpg') — easily bypassed with .jpg.php"
|
|
511
|
+
- "Content-Type header trusted without content inspection"
|
|
512
|
+
|
|
513
|
+
safe_patterns:
|
|
514
|
+
- "path.resolve() with base directory check"
|
|
515
|
+
- "Magic bytes validation (file-type library)"
|
|
516
|
+
- "Randomized storage filename, original name in metadata"
|
|
517
|
+
- "Separate storage domain for uploaded files"
|
|
518
|
+
- "File size limits in both server config and application code"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## 12. Business Logic
|
|
524
|
+
|
|
525
|
+
**ASVS**: V2.2 | **API Top 10**: API6:2023 | **WSTG**: WSTG-BUSL-01 to WSTG-BUSL-09
|
|
526
|
+
|
|
527
|
+
```yaml
|
|
528
|
+
vulnerable_patterns:
|
|
529
|
+
- pattern: "Missing rate limiting on sensitive business flows"
|
|
530
|
+
indicators:
|
|
531
|
+
- "Purchase/checkout endpoint without rate limit"
|
|
532
|
+
- "Referral/coupon endpoint abusable in bulk"
|
|
533
|
+
- "Reservation system without per-user limits"
|
|
534
|
+
|
|
535
|
+
- pattern: "Step skipping in multi-step flows"
|
|
536
|
+
indicators:
|
|
537
|
+
- "Payment confirmation endpoint callable without prior cart validation"
|
|
538
|
+
- "Account verification step bypassable by direct API call"
|
|
539
|
+
|
|
540
|
+
- pattern: "Negative number / boundary abuse"
|
|
541
|
+
indicators:
|
|
542
|
+
- "Negative quantity in purchase (credit instead of charge)"
|
|
543
|
+
- "Integer overflow in amount calculation"
|
|
544
|
+
- "Discount applied multiple times"
|
|
545
|
+
|
|
546
|
+
safe_patterns:
|
|
547
|
+
- "Server-side state machine for multi-step flows"
|
|
548
|
+
- "Rate limiting per user per endpoint for business operations"
|
|
549
|
+
- "Positive value validation on all financial inputs"
|
|
550
|
+
- "Idempotency keys for critical operations"
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
---
|
|
554
|
+
|
|
555
|
+
## 13. Prototype Pollution
|
|
556
|
+
|
|
557
|
+
**ASVS**: V15.3.6 | **CheatSheet**: Prototype_Pollution_Prevention
|
|
558
|
+
|
|
559
|
+
```yaml
|
|
560
|
+
vulnerable_patterns:
|
|
561
|
+
- pattern: "Deep merge/extend with user input"
|
|
562
|
+
indicators:
|
|
563
|
+
- "_.merge({}, userInput)"
|
|
564
|
+
- "$.extend(true, {}, userInput)"
|
|
565
|
+
- "Recursive Object.assign with nested user input"
|
|
566
|
+
- "JSON.parse(userInput) with __proto__ key"
|
|
567
|
+
|
|
568
|
+
- pattern: "Direct property setting from user keys"
|
|
569
|
+
indicators:
|
|
570
|
+
- "obj[userKey] = userValue (if userKey = '__proto__')"
|
|
571
|
+
- "for (key in userInput) target[key] = userInput[key]"
|
|
572
|
+
|
|
573
|
+
safe_patterns:
|
|
574
|
+
- "Object.create(null) for dictionary objects"
|
|
575
|
+
- "Map/Set instead of plain objects for user-keyed data"
|
|
576
|
+
- "Key validation: reject '__proto__', 'constructor', 'prototype'"
|
|
577
|
+
- "Object.freeze(Object.prototype) in startup (defense-in-depth)"
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## 14. Server-Side Template Injection
|
|
583
|
+
|
|
584
|
+
**ASVS**: V1.2.11 | **WSTG**: WSTG-INPV-18
|
|
585
|
+
|
|
586
|
+
```yaml
|
|
587
|
+
vulnerable_patterns:
|
|
588
|
+
- pattern: "User input in template string"
|
|
589
|
+
indicators:
|
|
590
|
+
- "render_template_string(user_input) (Jinja2)"
|
|
591
|
+
- "new Template(user_input).render() (Freemarker)"
|
|
592
|
+
- "Handlebars.compile(user_input)"
|
|
593
|
+
- "ERB.new(user_input).result"
|
|
594
|
+
- "Template engine with user-controlled template name"
|
|
595
|
+
|
|
596
|
+
- pattern: "Template sandbox bypass"
|
|
597
|
+
indicators:
|
|
598
|
+
- "{{ config.items() }} (Jinja2 config access)"
|
|
599
|
+
- "{{ ''.__class__.__mro__[1].__subclasses__() }} (Python class traversal)"
|
|
600
|
+
|
|
601
|
+
safe_patterns:
|
|
602
|
+
- "User data passed as template context, never as template source"
|
|
603
|
+
- "Logic-less templates (Mustache) for user-customizable templates"
|
|
604
|
+
- "Sandboxed template environment (Jinja2 SandboxedEnvironment)"
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
---
|
|
608
|
+
|
|
609
|
+
## 15. Improper API Inventory
|
|
610
|
+
|
|
611
|
+
**ASVS**: V13, V15.2 | **API Top 10**: API9:2023 | **WSTG**: WSTG-CONF-05, WSTG-CONF-06
|
|
612
|
+
|
|
613
|
+
```yaml
|
|
614
|
+
vulnerable_patterns:
|
|
615
|
+
- pattern: "Deprecated or undocumented API endpoints still active"
|
|
616
|
+
indicators:
|
|
617
|
+
- "Routes prefixed with /v1/, /old/, /legacy/ still reachable"
|
|
618
|
+
- "Commented-out routes re-enabled without review"
|
|
619
|
+
- "API version mismatch between documentation and deployed routes"
|
|
620
|
+
- "Swagger/OpenAPI spec does not match actual route definitions"
|
|
621
|
+
|
|
622
|
+
- pattern: "Shadow APIs and debug endpoints in production"
|
|
623
|
+
indicators:
|
|
624
|
+
- "/api/debug/*, /api/test/*, /api/internal/* accessible externally"
|
|
625
|
+
- "Spring Boot Actuator endpoints exposed (/actuator/env, /actuator/heapdump)"
|
|
626
|
+
- "GraphQL introspection enabled in production"
|
|
627
|
+
- "Admin endpoints without authentication or network restriction"
|
|
628
|
+
- "Health check endpoints leaking environment details"
|
|
629
|
+
|
|
630
|
+
- pattern: "Unmanaged API surface expansion"
|
|
631
|
+
indicators:
|
|
632
|
+
- "Dynamic route registration from user input or database"
|
|
633
|
+
- "Wildcard route handlers: app.all('*', handler)"
|
|
634
|
+
- "Auto-generated CRUD endpoints without explicit allowlist (e.g., Strapi, Hasura defaults)"
|
|
635
|
+
- "Third-party middleware exposing additional routes not in documentation"
|
|
636
|
+
|
|
637
|
+
safe_patterns:
|
|
638
|
+
- "Centralized route registry with explicit endpoint declaration"
|
|
639
|
+
- "API gateway with route allowlist and version management"
|
|
640
|
+
- "OpenAPI/Swagger spec as single source of truth, validated against code"
|
|
641
|
+
- "Automated route inventory comparison in CI pipeline"
|
|
642
|
+
- "Network-level isolation for internal/debug endpoints"
|
|
643
|
+
- "Deprecation headers (Sunset, Deprecation) on phased-out endpoints"
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## 16. Cross-Site Request Forgery (CSRF)
|
|
649
|
+
|
|
650
|
+
**ASVS**: V3.5.1, V3.5.2, V3.5.3 | **API Top 10**: API8:2023 | **WSTG**: WSTG-SESS-05
|
|
651
|
+
|
|
652
|
+
```yaml
|
|
653
|
+
vulnerable_patterns:
|
|
654
|
+
- pattern: "Cookie-based session without CSRF protection"
|
|
655
|
+
indicators:
|
|
656
|
+
- "Session cookie set without SameSite attribute"
|
|
657
|
+
- "POST/PUT/DELETE routes without CSRF token middleware"
|
|
658
|
+
- "csrf_exempt decorator on state-changing endpoints (Django)"
|
|
659
|
+
- "csurf middleware not applied (Express)"
|
|
660
|
+
- "@EnableWebSecurity without CsrfConfigurer (Spring)"
|
|
661
|
+
- "VerifyCsrfToken middleware excluded for routes (Laravel)"
|
|
662
|
+
|
|
663
|
+
- pattern: "CSRF token not validated server-side"
|
|
664
|
+
indicators:
|
|
665
|
+
- "CSRF token generated but never checked on submission"
|
|
666
|
+
- "Token comparison using timing-unsafe equality (== instead of constant-time)"
|
|
667
|
+
- "CSRF token stored in cookie without double-submit validation"
|
|
668
|
+
|
|
669
|
+
- pattern: "State-changing operations on safe HTTP methods"
|
|
670
|
+
indicators:
|
|
671
|
+
- "GET /api/transfer?amount=1000&to=attacker"
|
|
672
|
+
- "GET request triggers data deletion or modification"
|
|
673
|
+
- "Link-based actions that mutate server state"
|
|
674
|
+
|
|
675
|
+
safe_patterns:
|
|
676
|
+
- "SameSite=Lax or Strict on session cookies"
|
|
677
|
+
- "CSRF token middleware: csurf (Express), CsrfViewMiddleware (Django), CsrfConfigurer (Spring)"
|
|
678
|
+
- "Double-submit cookie pattern with server-side validation"
|
|
679
|
+
- "Custom header requirement (X-Requested-With) for AJAX APIs"
|
|
680
|
+
- "State-changing operations use POST/PUT/PATCH/DELETE only"
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## 17. XML External Entity (XXE)
|
|
686
|
+
|
|
687
|
+
**ASVS**: V1.5.1 | **WSTG**: WSTG-INPV-07
|
|
688
|
+
|
|
689
|
+
```yaml
|
|
690
|
+
vulnerable_patterns:
|
|
691
|
+
- pattern: "XML parser with external entity resolution enabled"
|
|
692
|
+
indicators:
|
|
693
|
+
java:
|
|
694
|
+
- "DocumentBuilderFactory without setFeature('http://apache.org/xml/features/disallow-doctype-decl', true)"
|
|
695
|
+
- "SAXParserFactory without disabling external entities"
|
|
696
|
+
- "XMLInputFactory without XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES set to false"
|
|
697
|
+
- "TransformerFactory without ACCESS_EXTERNAL_DTD set to empty string"
|
|
698
|
+
- "Unmarshaller (JAXB) processing untrusted XML without secure parser"
|
|
699
|
+
python:
|
|
700
|
+
- "lxml.etree.parse(user_input) with resolve_entities=True (default)"
|
|
701
|
+
- "xml.etree.ElementTree.parse(user_input) — safe by default, but xml.sax is not"
|
|
702
|
+
- "defusedxml not used for untrusted XML input"
|
|
703
|
+
php:
|
|
704
|
+
- "libxml_disable_entity_loader(false) or not called before parsing"
|
|
705
|
+
- "simplexml_load_string($user_input) without LIBXML_NOENT protection"
|
|
706
|
+
- "DOMDocument->loadXML($user_input) without disabling entity loading"
|
|
707
|
+
javascript:
|
|
708
|
+
- "xml2js parseString with default options (safe by default, but check for custom options)"
|
|
709
|
+
- "libxmljs.parseXml(input, { noent: true }) — enables entity expansion"
|
|
710
|
+
- "fast-xml-parser with entity processing enabled"
|
|
711
|
+
csharp:
|
|
712
|
+
- "XmlDocument.LoadXml(input) without XmlResolver set to null"
|
|
713
|
+
- "XmlTextReader without ProhibitDtd = true (older .NET)"
|
|
714
|
+
- "XmlReaderSettings without DtdProcessing = DtdProcessing.Prohibit"
|
|
715
|
+
|
|
716
|
+
- pattern: "SOAP/XML web service accepting raw XML"
|
|
717
|
+
indicators:
|
|
718
|
+
- "XML body parsed without schema validation"
|
|
719
|
+
- "SOAP endpoint accepting DTD declarations in request"
|
|
720
|
+
|
|
721
|
+
safe_patterns:
|
|
722
|
+
- "Java: factory.setFeature('http://apache.org/xml/features/disallow-doctype-decl', true)"
|
|
723
|
+
- "Python: defusedxml.ElementTree.parse() or lxml with resolve_entities=False"
|
|
724
|
+
- "PHP: libxml_disable_entity_loader(true) before parsing"
|
|
725
|
+
- "C#: XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit }"
|
|
726
|
+
- "General: reject XML input containing <!DOCTYPE or <!ENTITY declarations"
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
---
|
|
730
|
+
|
|
731
|
+
## 18. Open Redirect
|
|
732
|
+
|
|
733
|
+
**ASVS**: V3.7.2 | **WSTG**: WSTG-CLNT-04
|
|
734
|
+
|
|
735
|
+
```yaml
|
|
736
|
+
vulnerable_patterns:
|
|
737
|
+
- pattern: "Redirect destination from user input without validation"
|
|
738
|
+
indicators:
|
|
739
|
+
- "res.redirect(req.query.url) (Express)"
|
|
740
|
+
- "redirect(request.GET['next']) (Django)"
|
|
741
|
+
- "Response.Redirect(Request.QueryString['returnUrl']) (ASP.NET)"
|
|
742
|
+
- "response.sendRedirect(request.getParameter('redirect')) (Java)"
|
|
743
|
+
- "header('Location: ' . $_GET['url']) (PHP)"
|
|
744
|
+
- "redirect_to(params[:return_to]) (Rails)"
|
|
745
|
+
|
|
746
|
+
- pattern: "URL validation bypass"
|
|
747
|
+
indicators:
|
|
748
|
+
- "url.startsWith('/') — bypassed with //evil.com (protocol-relative URL)"
|
|
749
|
+
- "url.includes('trusted.com') — bypassed with trusted.com.evil.com"
|
|
750
|
+
- "Regex matching hostname without anchoring: /trusted\\.com/"
|
|
751
|
+
- "Allowlist check on full URL instead of parsed hostname"
|
|
752
|
+
|
|
753
|
+
- pattern: "Indirect redirect via stored URL"
|
|
754
|
+
indicators:
|
|
755
|
+
- "User profile contains callback URL used in redirect after action"
|
|
756
|
+
- "OAuth redirect_uri not validated against registered URLs"
|
|
757
|
+
- "Email verification link with user-controlled return URL"
|
|
758
|
+
|
|
759
|
+
safe_patterns:
|
|
760
|
+
- "Redirect only to relative paths: url.startsWith('/') && !url.startsWith('//')"
|
|
761
|
+
- "Allowlist of permitted redirect hostnames with URL parsing"
|
|
762
|
+
- "Parse URL and validate hostname against trusted domains: new URL(input).hostname"
|
|
763
|
+
- "Map-based redirect: redirect keys instead of raw URLs (e.g., ?next=dashboard → map['dashboard'])"
|
|
764
|
+
- "Warning page before external redirect"
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
---
|
|
768
|
+
|
|
769
|
+
## 19. GraphQL Security
|
|
770
|
+
|
|
771
|
+
**ASVS**: V4.3 | **API Top 10**: API4:2023, API8:2023 | **WSTG**: WSTG-APIT-01
|
|
772
|
+
|
|
773
|
+
```yaml
|
|
774
|
+
vulnerable_patterns:
|
|
775
|
+
- pattern: "Introspection enabled in production"
|
|
776
|
+
indicators:
|
|
777
|
+
- "introspection: true in GraphQL server config"
|
|
778
|
+
- "No conditional disabling based on NODE_ENV or environment variable"
|
|
779
|
+
- "__schema and __type queries return results in production"
|
|
780
|
+
|
|
781
|
+
- pattern: "No query depth or complexity limiting"
|
|
782
|
+
indicators:
|
|
783
|
+
- "graphql-depth-limit or equivalent library not installed"
|
|
784
|
+
- "No depthLimit, costLimit, or complexityLimit in server config"
|
|
785
|
+
- "Deeply nested queries possible: { user { friends { friends { friends { ... } } } } }"
|
|
786
|
+
|
|
787
|
+
- pattern: "Alias-based batching abuse"
|
|
788
|
+
indicators:
|
|
789
|
+
- "No limit on number of aliases per query"
|
|
790
|
+
- "Rate limiting bypassed via aliased mutations: { a1: login(...), a2: login(...), ... }"
|
|
791
|
+
- "Batch queries not counted individually for rate limiting"
|
|
792
|
+
|
|
793
|
+
- pattern: "Missing field-level authorization"
|
|
794
|
+
indicators:
|
|
795
|
+
- "Resolvers return full database objects without field filtering"
|
|
796
|
+
- "No @auth or @Authorized directive on sensitive fields"
|
|
797
|
+
- "User type exposes email, role, or internal IDs to all authenticated users"
|
|
798
|
+
- "Mutation resolvers lack ownership or role checks"
|
|
799
|
+
|
|
800
|
+
- pattern: "Information leakage via suggestions"
|
|
801
|
+
indicators:
|
|
802
|
+
- "GraphQL error messages suggest valid field names: 'Did you mean X?'"
|
|
803
|
+
- "Detailed validation errors expose schema structure"
|
|
804
|
+
|
|
805
|
+
safe_patterns:
|
|
806
|
+
- "Disable introspection: introspection: process.env.NODE_ENV !== 'production'"
|
|
807
|
+
- "graphql-depth-limit: depthLimit(10)"
|
|
808
|
+
- "graphql-query-complexity: limit per query (e.g., max cost 1000)"
|
|
809
|
+
- "Alias/batch limiting: max aliases per query, count each operation for rate limiting"
|
|
810
|
+
- "Field-level auth: @auth directives, resolver-level permission checks"
|
|
811
|
+
- "Persisted queries: reject arbitrary queries in production, only accept pre-registered query hashes"
|
|
812
|
+
- "Disable field suggestions in production error messages"
|
|
813
|
+
```
|