@brunosps00/dev-workflow 0.0.5 → 0.0.6
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/bin/dev-workflow.js +6 -4
- package/lib/init.js +28 -11
- package/package.json +1 -1
- package/scaffold/pt-br/commands/dw-analyze-project.md +3 -3
- package/scaffold/pt-br/commands/dw-bugfix.md +6 -6
- package/scaffold/pt-br/commands/dw-code-review.md +2 -2
- package/scaffold/pt-br/commands/dw-create-tasks.md +4 -4
- package/scaffold/pt-br/commands/dw-generate-pr.md +3 -3
- package/scaffold/pt-br/commands/dw-help.md +50 -50
- package/scaffold/pt-br/commands/dw-review-implementation.md +3 -3
- package/scaffold/pt-br/commands/dw-run-plan.md +8 -8
- package/scaffold/pt-br/commands/dw-run-task.md +3 -3
- package/scaffold/pt-br/templates/tasks-template.md +2 -2
- package/scaffold/skills/agent-browser/SKILL.md +750 -0
- package/scaffold/skills/agent-browser/references/authentication.md +303 -0
- package/scaffold/skills/agent-browser/references/commands.md +295 -0
- package/scaffold/skills/agent-browser/references/profiling.md +120 -0
- package/scaffold/skills/agent-browser/references/proxy-support.md +194 -0
- package/scaffold/skills/agent-browser/references/session-management.md +193 -0
- package/scaffold/skills/agent-browser/references/snapshot-refs.md +219 -0
- package/scaffold/skills/agent-browser/references/video-recording.md +173 -0
- package/scaffold/skills/agent-browser/templates/authenticated-session.sh +105 -0
- package/scaffold/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/scaffold/skills/agent-browser/templates/form-automation.sh +62 -0
- package/scaffold/skills/humanizer/README.md +143 -0
- package/scaffold/skills/humanizer/SKILL.md +488 -0
- package/scaffold/skills/humanizer/WARP.md +53 -0
- package/scaffold/skills/remotion-best-practices/SKILL.md +61 -0
- package/scaffold/skills/remotion-best-practices/rules/3d.md +86 -0
- package/scaffold/skills/remotion-best-practices/rules/animations.md +27 -0
- package/scaffold/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
- package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
- package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
- package/scaffold/skills/remotion-best-practices/rules/assets.md +78 -0
- package/scaffold/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
- package/scaffold/skills/remotion-best-practices/rules/audio.md +169 -0
- package/scaffold/skills/remotion-best-practices/rules/calculate-metadata.md +134 -0
- package/scaffold/skills/remotion-best-practices/rules/can-decode.md +75 -0
- package/scaffold/skills/remotion-best-practices/rules/charts.md +120 -0
- package/scaffold/skills/remotion-best-practices/rules/compositions.md +154 -0
- package/scaffold/skills/remotion-best-practices/rules/display-captions.md +184 -0
- package/scaffold/skills/remotion-best-practices/rules/extract-frames.md +229 -0
- package/scaffold/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
- package/scaffold/skills/remotion-best-practices/rules/fonts.md +152 -0
- package/scaffold/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
- package/scaffold/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
- package/scaffold/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
- package/scaffold/skills/remotion-best-practices/rules/gifs.md +141 -0
- package/scaffold/skills/remotion-best-practices/rules/images.md +134 -0
- package/scaffold/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
- package/scaffold/skills/remotion-best-practices/rules/light-leaks.md +73 -0
- package/scaffold/skills/remotion-best-practices/rules/lottie.md +70 -0
- package/scaffold/skills/remotion-best-practices/rules/maps.md +412 -0
- package/scaffold/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
- package/scaffold/skills/remotion-best-practices/rules/measuring-text.md +140 -0
- package/scaffold/skills/remotion-best-practices/rules/parameters.md +109 -0
- package/scaffold/skills/remotion-best-practices/rules/sequencing.md +118 -0
- package/scaffold/skills/remotion-best-practices/rules/sfx.md +26 -0
- package/scaffold/skills/remotion-best-practices/rules/subtitles.md +36 -0
- package/scaffold/skills/remotion-best-practices/rules/tailwind.md +11 -0
- package/scaffold/skills/remotion-best-practices/rules/text-animations.md +20 -0
- package/scaffold/skills/remotion-best-practices/rules/timing.md +179 -0
- package/scaffold/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
- package/scaffold/skills/remotion-best-practices/rules/transitions.md +197 -0
- package/scaffold/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
- package/scaffold/skills/remotion-best-practices/rules/trimming.md +51 -0
- package/scaffold/skills/remotion-best-practices/rules/videos.md +171 -0
- package/scaffold/skills/remotion-best-practices/rules/voiceover.md +99 -0
- package/scaffold/skills/security-review/LICENSE +22 -0
- package/scaffold/skills/security-review/SKILL.md +312 -0
- package/scaffold/skills/security-review/infrastructure/docker.md +432 -0
- package/scaffold/skills/security-review/languages/javascript.md +388 -0
- package/scaffold/skills/security-review/languages/python.md +363 -0
- package/scaffold/skills/security-review/references/api-security.md +519 -0
- package/scaffold/skills/security-review/references/authentication.md +353 -0
- package/scaffold/skills/security-review/references/authorization.md +372 -0
- package/scaffold/skills/security-review/references/business-logic.md +443 -0
- package/scaffold/skills/security-review/references/cryptography.md +329 -0
- package/scaffold/skills/security-review/references/csrf.md +398 -0
- package/scaffold/skills/security-review/references/data-protection.md +378 -0
- package/scaffold/skills/security-review/references/deserialization.md +410 -0
- package/scaffold/skills/security-review/references/error-handling.md +436 -0
- package/scaffold/skills/security-review/references/file-security.md +457 -0
- package/scaffold/skills/security-review/references/injection.md +259 -0
- package/scaffold/skills/security-review/references/logging.md +433 -0
- package/scaffold/skills/security-review/references/misconfiguration.md +435 -0
- package/scaffold/skills/security-review/references/modern-threats.md +475 -0
- package/scaffold/skills/security-review/references/ssrf.md +415 -0
- package/scaffold/skills/security-review/references/supply-chain.md +405 -0
- package/scaffold/skills/security-review/references/xss.md +336 -0
- package/scaffold/skills/vercel-react-best-practices/AGENTS.md +3648 -0
- package/scaffold/skills/vercel-react-best-practices/README.md +123 -0
- package/scaffold/skills/vercel-react-best-practices/SKILL.md +146 -0
- package/scaffold/skills/vercel-react-best-practices/rules/_sections.md +46 -0
- package/scaffold/skills/vercel-react-best-practices/rules/_template.md +28 -0
- package/scaffold/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/scaffold/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/scaffold/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/scaffold/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
- package/scaffold/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/scaffold/skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
- package/scaffold/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
- package/scaffold/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
- package/scaffold/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/scaffold/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/scaffold/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
- package/scaffold/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/scaffold/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/scaffold/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
- package/scaffold/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
- package/scaffold/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/scaffold/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/scaffold/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/scaffold/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/scaffold/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/scaffold/skills/webapp-testing/SKILL.md +133 -0
- package/scaffold/skills/webapp-testing/assets/test-helper.js +56 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
# File Security Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
File operations present multiple security risks: path traversal attacks, malicious file uploads, XML External Entity (XXE) attacks, and insecure file permissions. This reference covers secure patterns for handling files.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Path Traversal Prevention
|
|
10
|
+
|
|
11
|
+
### The Vulnerability
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
# VULNERABLE: User-controlled path
|
|
15
|
+
@app.route('/download')
|
|
16
|
+
def download():
|
|
17
|
+
filename = request.args.get('file')
|
|
18
|
+
return send_file(f'/uploads/{filename}')
|
|
19
|
+
|
|
20
|
+
# Attack: ?file=../../../etc/passwd
|
|
21
|
+
# Results in: /uploads/../../../etc/passwd → /etc/passwd
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Prevention Techniques
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
import os
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
# Method 1: Validate and canonicalize path
|
|
31
|
+
def safe_join(base_directory, user_path):
|
|
32
|
+
"""Safely join paths, preventing traversal."""
|
|
33
|
+
# Resolve to absolute path
|
|
34
|
+
base = Path(base_directory).resolve()
|
|
35
|
+
target = (base / user_path).resolve()
|
|
36
|
+
|
|
37
|
+
# Verify target is under base
|
|
38
|
+
if not str(target).startswith(str(base)):
|
|
39
|
+
raise ValueError("Path traversal detected")
|
|
40
|
+
|
|
41
|
+
return str(target)
|
|
42
|
+
|
|
43
|
+
# Method 2: Use allowlist of files
|
|
44
|
+
ALLOWED_FILES = {'report.pdf', 'manual.pdf', 'readme.txt'}
|
|
45
|
+
|
|
46
|
+
def download_file(filename):
|
|
47
|
+
if filename not in ALLOWED_FILES:
|
|
48
|
+
raise ValueError("File not allowed")
|
|
49
|
+
return send_file(os.path.join(UPLOAD_DIR, filename))
|
|
50
|
+
|
|
51
|
+
# Method 3: Use indirect references
|
|
52
|
+
def get_file_by_id(file_id):
|
|
53
|
+
# Map ID to filename in database
|
|
54
|
+
file_record = File.query.get(file_id)
|
|
55
|
+
if not file_record or file_record.user_id != current_user.id:
|
|
56
|
+
raise PermissionError()
|
|
57
|
+
return send_file(file_record.storage_path)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Characters to Block
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
# Dangerous path patterns
|
|
64
|
+
BLOCKED_PATTERNS = [
|
|
65
|
+
'..', # Parent directory
|
|
66
|
+
'~', # Home directory
|
|
67
|
+
'%2e%2e', # URL-encoded ..
|
|
68
|
+
'%252e%252e', # Double-encoded ..
|
|
69
|
+
'..\\', # Windows backslash
|
|
70
|
+
'..%5c', # URL-encoded Windows
|
|
71
|
+
'%00', # Null byte (older systems)
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
def contains_traversal(path):
|
|
75
|
+
path_lower = path.lower()
|
|
76
|
+
return any(pattern in path_lower for pattern in BLOCKED_PATTERNS)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## File Upload Security
|
|
82
|
+
|
|
83
|
+
### Defense in Depth Approach
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import magic
|
|
87
|
+
import hashlib
|
|
88
|
+
import uuid
|
|
89
|
+
from pathlib import Path
|
|
90
|
+
|
|
91
|
+
# Configuration
|
|
92
|
+
ALLOWED_EXTENSIONS = {'pdf', 'png', 'jpg', 'jpeg', 'gif'}
|
|
93
|
+
ALLOWED_MIMETYPES = {
|
|
94
|
+
'application/pdf',
|
|
95
|
+
'image/png',
|
|
96
|
+
'image/jpeg',
|
|
97
|
+
'image/gif'
|
|
98
|
+
}
|
|
99
|
+
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
|
|
100
|
+
UPLOAD_DIR = '/var/uploads' # Outside webroot
|
|
101
|
+
|
|
102
|
+
def secure_upload(file):
|
|
103
|
+
"""Comprehensive file upload validation."""
|
|
104
|
+
|
|
105
|
+
# 1. Check file size
|
|
106
|
+
file.seek(0, 2) # Seek to end
|
|
107
|
+
size = file.tell()
|
|
108
|
+
file.seek(0) # Reset
|
|
109
|
+
if size > MAX_FILE_SIZE:
|
|
110
|
+
raise ValueError(f"File too large: {size} bytes")
|
|
111
|
+
|
|
112
|
+
# 2. Validate extension
|
|
113
|
+
original_filename = file.filename
|
|
114
|
+
extension = Path(original_filename).suffix.lower().lstrip('.')
|
|
115
|
+
if extension not in ALLOWED_EXTENSIONS:
|
|
116
|
+
raise ValueError(f"Extension not allowed: {extension}")
|
|
117
|
+
|
|
118
|
+
# 3. Validate MIME type (don't trust Content-Type header)
|
|
119
|
+
mime = magic.from_buffer(file.read(2048), mime=True)
|
|
120
|
+
file.seek(0)
|
|
121
|
+
if mime not in ALLOWED_MIMETYPES:
|
|
122
|
+
raise ValueError(f"MIME type not allowed: {mime}")
|
|
123
|
+
|
|
124
|
+
# 4. Validate extension matches content
|
|
125
|
+
expected_extensions = get_extensions_for_mime(mime)
|
|
126
|
+
if extension not in expected_extensions:
|
|
127
|
+
raise ValueError("Extension doesn't match content type")
|
|
128
|
+
|
|
129
|
+
# 5. Generate safe filename (ignore user input)
|
|
130
|
+
safe_filename = f"{uuid.uuid4().hex}.{extension}"
|
|
131
|
+
|
|
132
|
+
# 6. Store outside webroot
|
|
133
|
+
storage_path = os.path.join(UPLOAD_DIR, safe_filename)
|
|
134
|
+
file.save(storage_path)
|
|
135
|
+
|
|
136
|
+
# 7. Set restrictive permissions
|
|
137
|
+
os.chmod(storage_path, 0o640)
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
'original_name': original_filename,
|
|
141
|
+
'stored_name': safe_filename,
|
|
142
|
+
'storage_path': storage_path,
|
|
143
|
+
'size': size,
|
|
144
|
+
'mime_type': mime
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Filename Sanitization
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
import re
|
|
152
|
+
import unicodedata
|
|
153
|
+
|
|
154
|
+
def sanitize_filename(filename):
|
|
155
|
+
"""Sanitize filename for safe storage."""
|
|
156
|
+
# Normalize unicode
|
|
157
|
+
filename = unicodedata.normalize('NFKD', filename)
|
|
158
|
+
|
|
159
|
+
# Remove path components
|
|
160
|
+
filename = os.path.basename(filename)
|
|
161
|
+
|
|
162
|
+
# Remove null bytes
|
|
163
|
+
filename = filename.replace('\x00', '')
|
|
164
|
+
|
|
165
|
+
# Allow only safe characters
|
|
166
|
+
filename = re.sub(r'[^a-zA-Z0-9._-]', '_', filename)
|
|
167
|
+
|
|
168
|
+
# Prevent hidden files
|
|
169
|
+
filename = filename.lstrip('.')
|
|
170
|
+
|
|
171
|
+
# Limit length
|
|
172
|
+
if len(filename) > 255:
|
|
173
|
+
name, ext = os.path.splitext(filename)
|
|
174
|
+
filename = name[:255-len(ext)] + ext
|
|
175
|
+
|
|
176
|
+
return filename or 'unnamed'
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Image Validation
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from PIL import Image
|
|
183
|
+
import io
|
|
184
|
+
|
|
185
|
+
def validate_image(file_data):
|
|
186
|
+
"""Validate and reprocess image to strip metadata/payloads."""
|
|
187
|
+
try:
|
|
188
|
+
# Verify it's a valid image
|
|
189
|
+
img = Image.open(io.BytesIO(file_data))
|
|
190
|
+
img.verify()
|
|
191
|
+
|
|
192
|
+
# Reopen for processing (verify closes the file)
|
|
193
|
+
img = Image.open(io.BytesIO(file_data))
|
|
194
|
+
|
|
195
|
+
# Convert to remove potential embedded content
|
|
196
|
+
output = io.BytesIO()
|
|
197
|
+
img.save(output, format=img.format)
|
|
198
|
+
output.seek(0)
|
|
199
|
+
|
|
200
|
+
return output.read()
|
|
201
|
+
|
|
202
|
+
except Exception as e:
|
|
203
|
+
raise ValueError(f"Invalid image: {e}")
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Dangerous File Types
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
# Never allow execution
|
|
210
|
+
DANGEROUS_EXTENSIONS = {
|
|
211
|
+
# Executables
|
|
212
|
+
'exe', 'dll', 'so', 'dylib', 'bin',
|
|
213
|
+
# Scripts
|
|
214
|
+
'php', 'php3', 'php4', 'php5', 'phtml',
|
|
215
|
+
'asp', 'aspx', 'ascx', 'ashx',
|
|
216
|
+
'jsp', 'jspx',
|
|
217
|
+
'cgi', 'pl', 'py', 'rb', 'sh', 'bash',
|
|
218
|
+
# Server config
|
|
219
|
+
'htaccess', 'htpasswd',
|
|
220
|
+
'config', 'ini',
|
|
221
|
+
# HTML (XSS risk)
|
|
222
|
+
'html', 'htm', 'xhtml', 'svg',
|
|
223
|
+
# Office macros
|
|
224
|
+
'docm', 'xlsm', 'pptm',
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
# Dangerous MIME types
|
|
228
|
+
DANGEROUS_MIMETYPES = {
|
|
229
|
+
'application/x-executable',
|
|
230
|
+
'application/x-msdownload',
|
|
231
|
+
'application/x-php',
|
|
232
|
+
'text/html',
|
|
233
|
+
'image/svg+xml', # Can contain scripts
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## XML External Entity (XXE) Prevention
|
|
240
|
+
|
|
241
|
+
### The Vulnerability
|
|
242
|
+
|
|
243
|
+
```xml
|
|
244
|
+
<!-- Malicious XML -->
|
|
245
|
+
<?xml version="1.0"?>
|
|
246
|
+
<!DOCTYPE foo [
|
|
247
|
+
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
248
|
+
]>
|
|
249
|
+
<data>&xxe;</data>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Python Prevention
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
# VULNERABLE: Default lxml settings
|
|
256
|
+
from lxml import etree
|
|
257
|
+
doc = etree.parse(untrusted_file) # XXE enabled by default
|
|
258
|
+
|
|
259
|
+
# SAFE: Disable external entities
|
|
260
|
+
from lxml import etree
|
|
261
|
+
parser = etree.XMLParser(
|
|
262
|
+
resolve_entities=False,
|
|
263
|
+
no_network=True,
|
|
264
|
+
dtd_validation=False,
|
|
265
|
+
load_dtd=False
|
|
266
|
+
)
|
|
267
|
+
doc = etree.parse(untrusted_file, parser)
|
|
268
|
+
|
|
269
|
+
# SAFE: defusedxml library (recommended)
|
|
270
|
+
import defusedxml.ElementTree as ET
|
|
271
|
+
doc = ET.parse(untrusted_file) # XXE disabled by default
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Java Prevention
|
|
275
|
+
|
|
276
|
+
```java
|
|
277
|
+
// VULNERABLE: Default DocumentBuilder
|
|
278
|
+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
279
|
+
DocumentBuilder db = dbf.newDocumentBuilder();
|
|
280
|
+
Document doc = db.parse(untrustedFile);
|
|
281
|
+
|
|
282
|
+
// SAFE: Disable dangerous features
|
|
283
|
+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
|
284
|
+
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
|
285
|
+
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
286
|
+
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
287
|
+
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
|
288
|
+
dbf.setXIncludeAware(false);
|
|
289
|
+
dbf.setExpandEntityReferences(false);
|
|
290
|
+
DocumentBuilder db = dbf.newDocumentBuilder();
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### .NET Prevention
|
|
294
|
+
|
|
295
|
+
```csharp
|
|
296
|
+
// SAFE in .NET 4.5.2+: XmlReader is safe by default
|
|
297
|
+
XmlReader reader = XmlReader.Create(stream);
|
|
298
|
+
|
|
299
|
+
// For older versions, explicitly disable
|
|
300
|
+
XmlReaderSettings settings = new XmlReaderSettings();
|
|
301
|
+
settings.DtdProcessing = DtdProcessing.Prohibit;
|
|
302
|
+
settings.XmlResolver = null;
|
|
303
|
+
XmlReader reader = XmlReader.Create(stream, settings);
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Archive (ZIP) Handling
|
|
309
|
+
|
|
310
|
+
### Zip Slip Prevention
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
import zipfile
|
|
314
|
+
import os
|
|
315
|
+
|
|
316
|
+
def safe_extract(zip_path, extract_dir):
|
|
317
|
+
"""Safely extract ZIP, preventing path traversal."""
|
|
318
|
+
extract_dir = os.path.abspath(extract_dir)
|
|
319
|
+
|
|
320
|
+
with zipfile.ZipFile(zip_path, 'r') as zf:
|
|
321
|
+
for member in zf.namelist():
|
|
322
|
+
# Get absolute path of extracted file
|
|
323
|
+
member_path = os.path.abspath(os.path.join(extract_dir, member))
|
|
324
|
+
|
|
325
|
+
# Verify it's under extract directory
|
|
326
|
+
if not member_path.startswith(extract_dir + os.sep):
|
|
327
|
+
raise ValueError(f"Path traversal in ZIP: {member}")
|
|
328
|
+
|
|
329
|
+
# Check for symlinks (additional safety)
|
|
330
|
+
if member.endswith('/'):
|
|
331
|
+
os.makedirs(member_path, exist_ok=True)
|
|
332
|
+
else:
|
|
333
|
+
os.makedirs(os.path.dirname(member_path), exist_ok=True)
|
|
334
|
+
with zf.open(member) as source, open(member_path, 'wb') as target:
|
|
335
|
+
target.write(source.read())
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Zip Bomb Prevention
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
MAX_UNCOMPRESSED_SIZE = 100 * 1024 * 1024 # 100MB
|
|
342
|
+
MAX_COMPRESSION_RATIO = 100
|
|
343
|
+
|
|
344
|
+
def check_zip_bomb(zip_path):
|
|
345
|
+
"""Detect potential zip bombs."""
|
|
346
|
+
compressed_size = os.path.getsize(zip_path)
|
|
347
|
+
|
|
348
|
+
with zipfile.ZipFile(zip_path, 'r') as zf:
|
|
349
|
+
uncompressed_size = sum(info.file_size for info in zf.infolist())
|
|
350
|
+
|
|
351
|
+
# Check total size
|
|
352
|
+
if uncompressed_size > MAX_UNCOMPRESSED_SIZE:
|
|
353
|
+
raise ValueError(f"Uncompressed size too large: {uncompressed_size}")
|
|
354
|
+
|
|
355
|
+
# Check compression ratio
|
|
356
|
+
if compressed_size > 0:
|
|
357
|
+
ratio = uncompressed_size / compressed_size
|
|
358
|
+
if ratio > MAX_COMPRESSION_RATIO:
|
|
359
|
+
raise ValueError(f"Suspicious compression ratio: {ratio}")
|
|
360
|
+
|
|
361
|
+
return True
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## File Permissions
|
|
367
|
+
|
|
368
|
+
### Secure Defaults
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
import os
|
|
372
|
+
import stat
|
|
373
|
+
|
|
374
|
+
# Uploaded files: readable by app, not executable
|
|
375
|
+
def secure_file_permissions(path):
|
|
376
|
+
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP) # 640
|
|
377
|
+
|
|
378
|
+
# Directories: accessible by app
|
|
379
|
+
def secure_directory_permissions(path):
|
|
380
|
+
os.chmod(path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP) # 750
|
|
381
|
+
|
|
382
|
+
# Sensitive files: only owner
|
|
383
|
+
def sensitive_file_permissions(path):
|
|
384
|
+
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR) # 600
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Temporary Files
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
import tempfile
|
|
391
|
+
import os
|
|
392
|
+
|
|
393
|
+
# VULNERABLE: Predictable temp file
|
|
394
|
+
with open('/tmp/myapp_temp.txt', 'w') as f:
|
|
395
|
+
f.write(sensitive_data)
|
|
396
|
+
|
|
397
|
+
# SAFE: Secure temp file
|
|
398
|
+
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
|
|
399
|
+
f.write(sensitive_data)
|
|
400
|
+
temp_path = f.name
|
|
401
|
+
# File has restrictive permissions automatically
|
|
402
|
+
|
|
403
|
+
# SAFE: Temp directory
|
|
404
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
405
|
+
# Directory and contents deleted on exit
|
|
406
|
+
pass
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Grep Patterns for Detection
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
# Path traversal risks
|
|
415
|
+
grep -rn "open(.*request\|send_file(.*request" --include="*.py"
|
|
416
|
+
grep -rn "fs\.readFile.*req\|fs\.writeFile.*req" --include="*.js"
|
|
417
|
+
|
|
418
|
+
# Dangerous file operations
|
|
419
|
+
grep -rn "os\.system.*file\|subprocess.*file" --include="*.py"
|
|
420
|
+
|
|
421
|
+
# XML parsing (XXE risk)
|
|
422
|
+
grep -rn "etree\.parse\|xml\.parse\|DOM\.parse" --include="*.py" --include="*.java"
|
|
423
|
+
grep -rn "XMLReader\|DocumentBuilder" --include="*.java"
|
|
424
|
+
|
|
425
|
+
# ZIP handling
|
|
426
|
+
grep -rn "zipfile\|ZipFile\|extractall" --include="*.py" --include="*.java"
|
|
427
|
+
|
|
428
|
+
# File permissions
|
|
429
|
+
grep -rn "chmod 777\|chmod 666\|chmod 755" --include="*.py" --include="*.sh"
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## Testing Checklist
|
|
435
|
+
|
|
436
|
+
- [ ] Path traversal prevented (canonicalization + validation)
|
|
437
|
+
- [ ] File extensions validated against allowlist
|
|
438
|
+
- [ ] MIME types validated (not just Content-Type header)
|
|
439
|
+
- [ ] Filenames sanitized (don't use user input directly)
|
|
440
|
+
- [ ] Files stored outside webroot
|
|
441
|
+
- [ ] Restrictive file permissions set
|
|
442
|
+
- [ ] Upload size limits enforced
|
|
443
|
+
- [ ] Dangerous file types blocked
|
|
444
|
+
- [ ] XML parsing has XXE disabled
|
|
445
|
+
- [ ] ZIP extraction validates paths
|
|
446
|
+
- [ ] ZIP bomb detection in place
|
|
447
|
+
- [ ] Temporary files handled securely
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## References
|
|
452
|
+
|
|
453
|
+
- [OWASP File Upload Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html)
|
|
454
|
+
- [OWASP XXE Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html)
|
|
455
|
+
- [CWE-22: Path Traversal](https://cwe.mitre.org/data/definitions/22.html)
|
|
456
|
+
- [CWE-434: Unrestricted File Upload](https://cwe.mitre.org/data/definitions/434.html)
|
|
457
|
+
- [CWE-611: XXE](https://cwe.mitre.org/data/definitions/611.html)
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Injection Prevention Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Injection flaws occur when untrusted data is sent to an interpreter as part of a command or query. The attacker's hostile data tricks the interpreter into executing unintended commands or accessing data without proper authorization.
|
|
6
|
+
|
|
7
|
+
## SQL Injection
|
|
8
|
+
|
|
9
|
+
### Primary Defenses
|
|
10
|
+
|
|
11
|
+
**1. Prepared Statements (Parameterized Queries) - REQUIRED**
|
|
12
|
+
|
|
13
|
+
The database distinguishes between code and data regardless of user input.
|
|
14
|
+
|
|
15
|
+
```java
|
|
16
|
+
// SAFE: Parameterized query
|
|
17
|
+
String query = "SELECT * FROM users WHERE username = ?";
|
|
18
|
+
PreparedStatement pstmt = connection.prepareStatement(query);
|
|
19
|
+
pstmt.setString(1, userInput);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
# SAFE: Parameterized query
|
|
24
|
+
cursor.execute("SELECT * FROM users WHERE username = %s", (user_input,))
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// SAFE: Parameterized query (node-postgres)
|
|
29
|
+
const result = await client.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**2. Stored Procedures**
|
|
33
|
+
|
|
34
|
+
Safe when implemented without dynamic SQL construction.
|
|
35
|
+
|
|
36
|
+
```java
|
|
37
|
+
// SAFE: Stored procedure
|
|
38
|
+
CallableStatement cs = connection.prepareCall("{call sp_getUser(?)}");
|
|
39
|
+
cs.setString(1, username);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**3. Allow-list Input Validation**
|
|
43
|
+
|
|
44
|
+
For elements that cannot be parameterized (table names, column names, sort order).
|
|
45
|
+
|
|
46
|
+
```java
|
|
47
|
+
// SAFE: Allowlist for table names
|
|
48
|
+
switch(tableName) {
|
|
49
|
+
case "users": return "users";
|
|
50
|
+
case "orders": return "orders";
|
|
51
|
+
default: throw new InputValidationException("Invalid table");
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Vulnerable Patterns to Find
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
# VULNERABLE: String concatenation
|
|
59
|
+
query = "SELECT * FROM users WHERE name = '" + user_input + "'"
|
|
60
|
+
|
|
61
|
+
# VULNERABLE: f-string interpolation
|
|
62
|
+
query = f"SELECT * FROM users WHERE id = {user_id}"
|
|
63
|
+
|
|
64
|
+
# VULNERABLE: format() method
|
|
65
|
+
query = "SELECT * FROM users WHERE name = '{}'".format(user_input)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
// VULNERABLE: Template literal
|
|
70
|
+
const query = `SELECT * FROM users WHERE id = ${userId}`;
|
|
71
|
+
|
|
72
|
+
// VULNERABLE: String concatenation
|
|
73
|
+
const query = "SELECT * FROM users WHERE name = '" + userName + "'";
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### ORM Safety Considerations
|
|
77
|
+
|
|
78
|
+
**Django ORM**
|
|
79
|
+
```python
|
|
80
|
+
# SAFE: ORM methods
|
|
81
|
+
User.objects.filter(username=user_input)
|
|
82
|
+
|
|
83
|
+
# VULNERABLE: raw() with interpolation
|
|
84
|
+
User.objects.raw(f"SELECT * FROM users WHERE name = '{user_input}'")
|
|
85
|
+
|
|
86
|
+
# VULNERABLE: extra() with unvalidated input
|
|
87
|
+
User.objects.extra(where=[f"name = '{user_input}'"])
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**SQLAlchemy**
|
|
91
|
+
```python
|
|
92
|
+
# SAFE: ORM methods
|
|
93
|
+
session.query(User).filter(User.name == user_input)
|
|
94
|
+
|
|
95
|
+
# VULNERABLE: text() with interpolation
|
|
96
|
+
session.execute(text(f"SELECT * FROM users WHERE name = '{user_input}'"))
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## NoSQL Injection
|
|
102
|
+
|
|
103
|
+
### MongoDB Injection Patterns
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
// VULNERABLE: User-controlled query operators
|
|
107
|
+
db.users.find({ username: req.body.username, password: req.body.password });
|
|
108
|
+
// Attack: { "username": "admin", "password": { "$gt": "" } }
|
|
109
|
+
|
|
110
|
+
// SAFE: Explicit type checking
|
|
111
|
+
const username = String(req.body.username);
|
|
112
|
+
const password = String(req.body.password);
|
|
113
|
+
db.users.find({ username: username, password: password });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Dangerous Operators**
|
|
117
|
+
- `$where` - Allows JavaScript execution
|
|
118
|
+
- `$regex` - Can be used for ReDoS
|
|
119
|
+
- `$gt`, `$ne`, `$in` - Query manipulation when user-controlled
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## OS Command Injection
|
|
124
|
+
|
|
125
|
+
### Primary Defenses
|
|
126
|
+
|
|
127
|
+
**1. Avoid Shell Commands - PREFERRED**
|
|
128
|
+
|
|
129
|
+
Use language built-in functions instead of shell commands.
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# VULNERABLE: Shell command
|
|
133
|
+
os.system(f"mkdir {directory_name}")
|
|
134
|
+
|
|
135
|
+
# SAFE: Built-in function
|
|
136
|
+
os.makedirs(directory_name, exist_ok=True)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**2. Parameterization**
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
# VULNERABLE: Shell=True with user input
|
|
143
|
+
subprocess.run(f"convert {input_file} {output_file}", shell=True)
|
|
144
|
+
|
|
145
|
+
# SAFE: List of arguments, shell=False
|
|
146
|
+
subprocess.run(["convert", input_file, output_file], shell=False)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**3. Input Validation**
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
# Allowlist for permitted commands
|
|
153
|
+
ALLOWED_COMMANDS = {"convert", "resize", "rotate"}
|
|
154
|
+
if command not in ALLOWED_COMMANDS:
|
|
155
|
+
raise ValueError("Invalid command")
|
|
156
|
+
|
|
157
|
+
# Validate arguments against safe patterns
|
|
158
|
+
if not re.match(r'^[a-zA-Z0-9_\-\.]+$', filename):
|
|
159
|
+
raise ValueError("Invalid filename")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Dangerous Characters
|
|
163
|
+
|
|
164
|
+
Block or escape: `& | ; $ > < \ ! ' " ( ) { } [ ] \n \r`
|
|
165
|
+
|
|
166
|
+
### Language-Specific Dangerous Functions
|
|
167
|
+
|
|
168
|
+
| Language | Dangerous Functions |
|
|
169
|
+
|----------|-------------------|
|
|
170
|
+
| Python | `os.system()`, `subprocess.run(shell=True)`, `os.popen()`, `eval()`, `exec()` |
|
|
171
|
+
| JavaScript | `child_process.exec()`, `eval()` |
|
|
172
|
+
| PHP | `exec()`, `shell_exec()`, `system()`, `passthru()`, backticks |
|
|
173
|
+
| Ruby | `system()`, `exec()`, backticks, `%x{}` |
|
|
174
|
+
| Java | `Runtime.exec()`, `ProcessBuilder` with shell |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## LDAP Injection
|
|
179
|
+
|
|
180
|
+
### Prevention
|
|
181
|
+
|
|
182
|
+
```java
|
|
183
|
+
// SAFE: Escape special characters
|
|
184
|
+
String safeName = LdapEncoder.filterEncode(userName);
|
|
185
|
+
String filter = "(&(uid=" + safeName + ")(userPassword=" + safePassword + "))";
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Characters to Escape in LDAP**
|
|
189
|
+
- Filter context: `* ( ) \ NUL`
|
|
190
|
+
- DN context: `\ # + < > ; " = /`
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Template Injection
|
|
195
|
+
|
|
196
|
+
### Server-Side Template Injection (SSTI)
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
# VULNERABLE: User input in template
|
|
200
|
+
template = Template(f"Hello {user_input}")
|
|
201
|
+
|
|
202
|
+
# SAFE: Pass user input as variable
|
|
203
|
+
template = Template("Hello {{ name }}")
|
|
204
|
+
template.render(name=user_input)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Detection Payloads**
|
|
208
|
+
- Jinja2: `{{7*7}}` → `49`
|
|
209
|
+
- FreeMarker: `${7*7}` → `49`
|
|
210
|
+
- Thymeleaf: `[[${7*7}]]` → `49`
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## XPath Injection
|
|
215
|
+
|
|
216
|
+
### Prevention
|
|
217
|
+
|
|
218
|
+
```java
|
|
219
|
+
// VULNERABLE: String concatenation
|
|
220
|
+
String query = "//users/user[name='" + userName + "']";
|
|
221
|
+
|
|
222
|
+
// SAFE: Use parameterized XPath
|
|
223
|
+
XPathExpression expr = xpath.compile("//users/user[name=$name]");
|
|
224
|
+
expr.setVariable("name", userName);
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Key Grep Patterns for Detection
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
# SQL Injection
|
|
233
|
+
grep -rn "execute.*+" --include="*.py"
|
|
234
|
+
grep -rn "raw_sql\|rawQuery\|raw(" --include="*.py" --include="*.js"
|
|
235
|
+
grep -rn "\\.query\\(.*\\+" --include="*.js"
|
|
236
|
+
grep -rn "\\$.*\\+" --include="*.php"
|
|
237
|
+
|
|
238
|
+
# Command Injection
|
|
239
|
+
grep -rn "os\\.system\\|subprocess\\.run.*shell=True\\|os\\.popen" --include="*.py"
|
|
240
|
+
grep -rn "child_process\\.exec" --include="*.js"
|
|
241
|
+
grep -rn "system(\\|exec(\\|shell_exec(" --include="*.php"
|
|
242
|
+
|
|
243
|
+
# Template Injection
|
|
244
|
+
grep -rn "Template(.*\\+" --include="*.py"
|
|
245
|
+
grep -rn "render_template_string" --include="*.py"
|
|
246
|
+
|
|
247
|
+
# LDAP Injection
|
|
248
|
+
grep -rn "ldap_search\\|ldap_bind" --include="*.py" --include="*.php"
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## References
|
|
254
|
+
|
|
255
|
+
- [OWASP SQL Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)
|
|
256
|
+
- [OWASP OS Command Injection Defense](https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html)
|
|
257
|
+
- [OWASP LDAP Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html)
|
|
258
|
+
- [CWE-89: SQL Injection](https://cwe.mitre.org/data/definitions/89.html)
|
|
259
|
+
- [CWE-78: OS Command Injection](https://cwe.mitre.org/data/definitions/78.html)
|