@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.
Files changed (164) hide show
  1. package/bin/dev-workflow.js +6 -4
  2. package/lib/init.js +28 -11
  3. package/package.json +1 -1
  4. package/scaffold/pt-br/commands/dw-analyze-project.md +3 -3
  5. package/scaffold/pt-br/commands/dw-bugfix.md +6 -6
  6. package/scaffold/pt-br/commands/dw-code-review.md +2 -2
  7. package/scaffold/pt-br/commands/dw-create-tasks.md +4 -4
  8. package/scaffold/pt-br/commands/dw-generate-pr.md +3 -3
  9. package/scaffold/pt-br/commands/dw-help.md +50 -50
  10. package/scaffold/pt-br/commands/dw-review-implementation.md +3 -3
  11. package/scaffold/pt-br/commands/dw-run-plan.md +8 -8
  12. package/scaffold/pt-br/commands/dw-run-task.md +3 -3
  13. package/scaffold/pt-br/templates/tasks-template.md +2 -2
  14. package/scaffold/skills/agent-browser/SKILL.md +750 -0
  15. package/scaffold/skills/agent-browser/references/authentication.md +303 -0
  16. package/scaffold/skills/agent-browser/references/commands.md +295 -0
  17. package/scaffold/skills/agent-browser/references/profiling.md +120 -0
  18. package/scaffold/skills/agent-browser/references/proxy-support.md +194 -0
  19. package/scaffold/skills/agent-browser/references/session-management.md +193 -0
  20. package/scaffold/skills/agent-browser/references/snapshot-refs.md +219 -0
  21. package/scaffold/skills/agent-browser/references/video-recording.md +173 -0
  22. package/scaffold/skills/agent-browser/templates/authenticated-session.sh +105 -0
  23. package/scaffold/skills/agent-browser/templates/capture-workflow.sh +69 -0
  24. package/scaffold/skills/agent-browser/templates/form-automation.sh +62 -0
  25. package/scaffold/skills/humanizer/README.md +143 -0
  26. package/scaffold/skills/humanizer/SKILL.md +488 -0
  27. package/scaffold/skills/humanizer/WARP.md +53 -0
  28. package/scaffold/skills/remotion-best-practices/SKILL.md +61 -0
  29. package/scaffold/skills/remotion-best-practices/rules/3d.md +86 -0
  30. package/scaffold/skills/remotion-best-practices/rules/animations.md +27 -0
  31. package/scaffold/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  32. package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  33. package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
  34. package/scaffold/skills/remotion-best-practices/rules/assets.md +78 -0
  35. package/scaffold/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
  36. package/scaffold/skills/remotion-best-practices/rules/audio.md +169 -0
  37. package/scaffold/skills/remotion-best-practices/rules/calculate-metadata.md +134 -0
  38. package/scaffold/skills/remotion-best-practices/rules/can-decode.md +75 -0
  39. package/scaffold/skills/remotion-best-practices/rules/charts.md +120 -0
  40. package/scaffold/skills/remotion-best-practices/rules/compositions.md +154 -0
  41. package/scaffold/skills/remotion-best-practices/rules/display-captions.md +184 -0
  42. package/scaffold/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  43. package/scaffold/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
  44. package/scaffold/skills/remotion-best-practices/rules/fonts.md +152 -0
  45. package/scaffold/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  46. package/scaffold/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  47. package/scaffold/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
  48. package/scaffold/skills/remotion-best-practices/rules/gifs.md +141 -0
  49. package/scaffold/skills/remotion-best-practices/rules/images.md +134 -0
  50. package/scaffold/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
  51. package/scaffold/skills/remotion-best-practices/rules/light-leaks.md +73 -0
  52. package/scaffold/skills/remotion-best-practices/rules/lottie.md +70 -0
  53. package/scaffold/skills/remotion-best-practices/rules/maps.md +412 -0
  54. package/scaffold/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  55. package/scaffold/skills/remotion-best-practices/rules/measuring-text.md +140 -0
  56. package/scaffold/skills/remotion-best-practices/rules/parameters.md +109 -0
  57. package/scaffold/skills/remotion-best-practices/rules/sequencing.md +118 -0
  58. package/scaffold/skills/remotion-best-practices/rules/sfx.md +26 -0
  59. package/scaffold/skills/remotion-best-practices/rules/subtitles.md +36 -0
  60. package/scaffold/skills/remotion-best-practices/rules/tailwind.md +11 -0
  61. package/scaffold/skills/remotion-best-practices/rules/text-animations.md +20 -0
  62. package/scaffold/skills/remotion-best-practices/rules/timing.md +179 -0
  63. package/scaffold/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
  64. package/scaffold/skills/remotion-best-practices/rules/transitions.md +197 -0
  65. package/scaffold/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
  66. package/scaffold/skills/remotion-best-practices/rules/trimming.md +51 -0
  67. package/scaffold/skills/remotion-best-practices/rules/videos.md +171 -0
  68. package/scaffold/skills/remotion-best-practices/rules/voiceover.md +99 -0
  69. package/scaffold/skills/security-review/LICENSE +22 -0
  70. package/scaffold/skills/security-review/SKILL.md +312 -0
  71. package/scaffold/skills/security-review/infrastructure/docker.md +432 -0
  72. package/scaffold/skills/security-review/languages/javascript.md +388 -0
  73. package/scaffold/skills/security-review/languages/python.md +363 -0
  74. package/scaffold/skills/security-review/references/api-security.md +519 -0
  75. package/scaffold/skills/security-review/references/authentication.md +353 -0
  76. package/scaffold/skills/security-review/references/authorization.md +372 -0
  77. package/scaffold/skills/security-review/references/business-logic.md +443 -0
  78. package/scaffold/skills/security-review/references/cryptography.md +329 -0
  79. package/scaffold/skills/security-review/references/csrf.md +398 -0
  80. package/scaffold/skills/security-review/references/data-protection.md +378 -0
  81. package/scaffold/skills/security-review/references/deserialization.md +410 -0
  82. package/scaffold/skills/security-review/references/error-handling.md +436 -0
  83. package/scaffold/skills/security-review/references/file-security.md +457 -0
  84. package/scaffold/skills/security-review/references/injection.md +259 -0
  85. package/scaffold/skills/security-review/references/logging.md +433 -0
  86. package/scaffold/skills/security-review/references/misconfiguration.md +435 -0
  87. package/scaffold/skills/security-review/references/modern-threats.md +475 -0
  88. package/scaffold/skills/security-review/references/ssrf.md +415 -0
  89. package/scaffold/skills/security-review/references/supply-chain.md +405 -0
  90. package/scaffold/skills/security-review/references/xss.md +336 -0
  91. package/scaffold/skills/vercel-react-best-practices/AGENTS.md +3648 -0
  92. package/scaffold/skills/vercel-react-best-practices/README.md +123 -0
  93. package/scaffold/skills/vercel-react-best-practices/SKILL.md +146 -0
  94. package/scaffold/skills/vercel-react-best-practices/rules/_sections.md +46 -0
  95. package/scaffold/skills/vercel-react-best-practices/rules/_template.md +28 -0
  96. package/scaffold/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  97. package/scaffold/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  98. package/scaffold/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  99. package/scaffold/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  100. package/scaffold/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  101. package/scaffold/skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
  102. package/scaffold/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  103. package/scaffold/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  104. package/scaffold/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  105. package/scaffold/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
  106. package/scaffold/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  107. package/scaffold/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  108. package/scaffold/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  109. package/scaffold/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  110. package/scaffold/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  111. package/scaffold/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  112. package/scaffold/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  113. package/scaffold/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  114. package/scaffold/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  115. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  116. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  117. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  118. package/scaffold/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  119. package/scaffold/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  120. package/scaffold/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
  121. package/scaffold/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  122. package/scaffold/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  123. package/scaffold/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  124. package/scaffold/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  125. package/scaffold/skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
  126. package/scaffold/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  127. package/scaffold/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  128. package/scaffold/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  129. package/scaffold/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  130. package/scaffold/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  131. package/scaffold/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  132. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  133. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  134. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  135. package/scaffold/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
  136. package/scaffold/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
  137. package/scaffold/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  138. package/scaffold/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  139. package/scaffold/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  140. package/scaffold/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  141. package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  142. package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  143. package/scaffold/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  144. package/scaffold/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  145. package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  146. package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  147. package/scaffold/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  148. package/scaffold/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
  149. package/scaffold/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  150. package/scaffold/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  151. package/scaffold/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  152. package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  153. package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  154. package/scaffold/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  155. package/scaffold/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  156. package/scaffold/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  157. package/scaffold/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  158. package/scaffold/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  159. package/scaffold/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
  160. package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  161. package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
  162. package/scaffold/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  163. package/scaffold/skills/webapp-testing/SKILL.md +133 -0
  164. package/scaffold/skills/webapp-testing/assets/test-helper.js +56 -0
@@ -0,0 +1,415 @@
1
+ # Server-Side Request Forgery (SSRF) Prevention Reference
2
+
3
+ ## Overview
4
+
5
+ SSRF vulnerabilities allow attackers to induce the server-side application to make HTTP requests to an arbitrary domain of the attacker's choosing. This can be used to:
6
+
7
+ - Access internal services not exposed to the internet
8
+ - Read cloud metadata (AWS, GCP, Azure credentials)
9
+ - Scan internal networks
10
+ - Bypass firewalls and access controls
11
+ - Exploit internal services with known vulnerabilities
12
+
13
+ ## Attack Scenarios
14
+
15
+ ### Cloud Metadata Access (AWS)
16
+
17
+ ```bash
18
+ # Attacker provides URL:
19
+ http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name
20
+
21
+ # Server fetches and returns AWS credentials:
22
+ {
23
+ "AccessKeyId": "ASIA...",
24
+ "SecretAccessKey": "...",
25
+ "Token": "..."
26
+ }
27
+ ```
28
+
29
+ ### Internal Service Access
30
+
31
+ ```bash
32
+ # Attacker provides URL:
33
+ http://localhost:8080/admin/delete-all
34
+ http://internal-service.local/sensitive-data
35
+
36
+ # Server makes request to internal service that trusts localhost
37
+ ```
38
+
39
+ ### Port Scanning
40
+
41
+ ```bash
42
+ # Attacker probes internal network:
43
+ http://192.168.1.1:22 # SSH
44
+ http://192.168.1.1:3306 # MySQL
45
+ http://192.168.1.1:6379 # Redis
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Prevention Strategies
51
+
52
+ ### 1. Input Validation (Allowlist)
53
+
54
+ **Preferred when target hosts are known.**
55
+
56
+ ```python
57
+ # VULNERABLE: No validation
58
+ def fetch_url(url):
59
+ return requests.get(url).content
60
+
61
+ # SAFE: Allowlist of permitted domains
62
+ ALLOWED_DOMAINS = {'api.example.com', 'cdn.example.com'}
63
+
64
+ def fetch_url(url):
65
+ parsed = urlparse(url)
66
+
67
+ # Validate scheme
68
+ if parsed.scheme not in ('http', 'https'):
69
+ raise ValueError("Invalid URL scheme")
70
+
71
+ # Validate domain against allowlist
72
+ if parsed.hostname not in ALLOWED_DOMAINS:
73
+ raise ValueError("Domain not allowed")
74
+
75
+ return requests.get(url).content
76
+ ```
77
+
78
+ ### 2. Block Internal Networks (Denylist)
79
+
80
+ **Additional defense layer when allowlist isn't practical.**
81
+
82
+ ```python
83
+ import ipaddress
84
+ import socket
85
+
86
+ BLOCKED_RANGES = [
87
+ ipaddress.ip_network('127.0.0.0/8'), # Loopback
88
+ ipaddress.ip_network('10.0.0.0/8'), # Private
89
+ ipaddress.ip_network('172.16.0.0/12'), # Private
90
+ ipaddress.ip_network('192.168.0.0/16'), # Private
91
+ ipaddress.ip_network('169.254.0.0/16'), # Link-local (metadata)
92
+ ipaddress.ip_network('0.0.0.0/8'), # Current network
93
+ ipaddress.ip_network('100.64.0.0/10'), # Shared address space
94
+ ipaddress.ip_network('192.0.0.0/24'), # IETF Protocol
95
+ ipaddress.ip_network('192.0.2.0/24'), # Documentation
96
+ ipaddress.ip_network('198.51.100.0/24'), # Documentation
97
+ ipaddress.ip_network('203.0.113.0/24'), # Documentation
98
+ ipaddress.ip_network('224.0.0.0/4'), # Multicast
99
+ ipaddress.ip_network('240.0.0.0/4'), # Reserved
100
+ ]
101
+
102
+ def is_internal_ip(ip_str):
103
+ try:
104
+ ip = ipaddress.ip_address(ip_str)
105
+ return any(ip in network for network in BLOCKED_RANGES)
106
+ except ValueError:
107
+ return True # Invalid IP, block it
108
+
109
+ def validate_url(url):
110
+ parsed = urlparse(url)
111
+
112
+ # Validate scheme
113
+ if parsed.scheme not in ('http', 'https'):
114
+ raise ValueError("Invalid URL scheme")
115
+
116
+ # Resolve hostname to IP
117
+ hostname = parsed.hostname
118
+ if not hostname:
119
+ raise ValueError("Invalid URL")
120
+
121
+ # Check for IP address directly in URL
122
+ try:
123
+ ip = ipaddress.ip_address(hostname)
124
+ if is_internal_ip(str(ip)):
125
+ raise ValueError("Internal IP addresses not allowed")
126
+ except ValueError:
127
+ # It's a hostname, resolve it
128
+ try:
129
+ ip = socket.gethostbyname(hostname)
130
+ if is_internal_ip(ip):
131
+ raise ValueError("Domain resolves to internal IP")
132
+ except socket.gaierror:
133
+ raise ValueError("Could not resolve hostname")
134
+
135
+ return True
136
+ ```
137
+
138
+ ### 3. Disable Redirects
139
+
140
+ ```python
141
+ # VULNERABLE: Follows redirects (can bypass IP checks)
142
+ response = requests.get(url, allow_redirects=True)
143
+ # Attacker: http://attacker.com/redirect -> http://169.254.169.254/
144
+
145
+ # SAFE: Don't follow redirects automatically
146
+ response = requests.get(url, allow_redirects=False)
147
+
148
+ # If redirects needed, validate each location
149
+ def safe_fetch(url, max_redirects=5):
150
+ for _ in range(max_redirects):
151
+ validate_url(url) # Validate before each request
152
+ response = requests.get(url, allow_redirects=False)
153
+
154
+ if response.status_code in (301, 302, 303, 307, 308):
155
+ url = response.headers.get('Location')
156
+ if not url:
157
+ raise ValueError("Redirect without Location")
158
+ continue
159
+
160
+ return response
161
+
162
+ raise ValueError("Too many redirects")
163
+ ```
164
+
165
+ ### 4. DNS Rebinding Protection
166
+
167
+ ```python
168
+ import socket
169
+ import time
170
+
171
+ def safe_fetch_with_dns_pinning(url):
172
+ parsed = urlparse(url)
173
+ hostname = parsed.hostname
174
+
175
+ # Resolve DNS and pin the IP
176
+ ip = socket.gethostbyname(hostname)
177
+
178
+ # Validate IP is not internal
179
+ if is_internal_ip(ip):
180
+ raise ValueError("Internal IP not allowed")
181
+
182
+ # Make request directly to IP with Host header
183
+ # This prevents DNS rebinding attacks
184
+ modified_url = url.replace(hostname, ip)
185
+ headers = {'Host': hostname}
186
+
187
+ response = requests.get(
188
+ modified_url,
189
+ headers=headers,
190
+ allow_redirects=False,
191
+ verify=True # Still verify TLS with original hostname
192
+ )
193
+
194
+ return response
195
+ ```
196
+
197
+ ### 5. Cloud Metadata Protection
198
+
199
+ #### AWS IMDSv2
200
+
201
+ ```bash
202
+ # Require IMDSv2 (token-based) - mitigates SSRF
203
+ aws ec2 modify-instance-metadata-options \
204
+ --instance-id i-1234567890abcdef0 \
205
+ --http-tokens required \
206
+ --http-endpoint enabled
207
+ ```
208
+
209
+ ```python
210
+ # With IMDSv2, attacker would need two requests:
211
+ # 1. PUT to get token (SSRF usually only does GET)
212
+ # 2. GET with token in header
213
+
214
+ # Block metadata IP regardless
215
+ if '169.254.169.254' in url or '169.254.170.2' in url:
216
+ raise ValueError("Metadata endpoints not allowed")
217
+ ```
218
+
219
+ #### GCP
220
+
221
+ ```python
222
+ # Block GCP metadata
223
+ BLOCKED_HOSTS = [
224
+ 'metadata.google.internal',
225
+ 'metadata.google.com',
226
+ '169.254.169.254'
227
+ ]
228
+ ```
229
+
230
+ #### Azure
231
+
232
+ ```python
233
+ # Block Azure metadata
234
+ BLOCKED_HOSTS = [
235
+ '169.254.169.254',
236
+ 'management.azure.com'
237
+ ]
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Framework-Specific Mitigations
243
+
244
+ ### Python (requests)
245
+
246
+ ```python
247
+ from urllib.parse import urlparse
248
+ import requests
249
+
250
+ class SafeRequests:
251
+ @staticmethod
252
+ def get(url, **kwargs):
253
+ validate_url(url)
254
+ kwargs['allow_redirects'] = False
255
+ kwargs['timeout'] = (5, 30) # Connect and read timeout
256
+ return requests.get(url, **kwargs)
257
+ ```
258
+
259
+ ### Node.js
260
+
261
+ ```javascript
262
+ const axios = require('axios');
263
+ const url = require('url');
264
+ const dns = require('dns').promises;
265
+
266
+ async function safeFetch(targetUrl) {
267
+ const parsed = new URL(targetUrl);
268
+
269
+ // Validate scheme
270
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
271
+ throw new Error('Invalid scheme');
272
+ }
273
+
274
+ // Resolve and check IP
275
+ const addresses = await dns.lookup(parsed.hostname);
276
+ if (isInternalIP(addresses.address)) {
277
+ throw new Error('Internal IP not allowed');
278
+ }
279
+
280
+ return axios.get(targetUrl, {
281
+ maxRedirects: 0,
282
+ timeout: 30000
283
+ });
284
+ }
285
+ ```
286
+
287
+ ### Java
288
+
289
+ ```java
290
+ public class SafeURLConnection {
291
+ private static final Set<String> ALLOWED_PROTOCOLS = Set.of("http", "https");
292
+
293
+ public static URLConnection openConnection(String urlString) throws IOException {
294
+ URL url = new URL(urlString);
295
+
296
+ if (!ALLOWED_PROTOCOLS.contains(url.getProtocol())) {
297
+ throw new SecurityException("Protocol not allowed");
298
+ }
299
+
300
+ InetAddress address = InetAddress.getByName(url.getHost());
301
+ if (isInternalIP(address)) {
302
+ throw new SecurityException("Internal IP not allowed");
303
+ }
304
+
305
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
306
+ connection.setInstanceFollowRedirects(false);
307
+ connection.setConnectTimeout(5000);
308
+ connection.setReadTimeout(30000);
309
+
310
+ return connection;
311
+ }
312
+ }
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Common Bypass Techniques to Block
318
+
319
+ ### URL Encoding
320
+
321
+ ```python
322
+ # Bypasses:
323
+ http://169.254.169.254/ # Normal
324
+ http://169%2e254%2e169%2e254/ # URL encoded dots
325
+ http://0251.0376.0251.0376/ # Octal
326
+ http://0xa9fea9fe/ # Hex
327
+ http://2852039166/ # Decimal
328
+
329
+ # Defense: Normalize and decode URL before validation
330
+ from urllib.parse import unquote
331
+
332
+ def normalize_url(url):
333
+ return unquote(url)
334
+ ```
335
+
336
+ ### DNS Rebinding
337
+
338
+ ```python
339
+ # Attack: Domain initially resolves to public IP, then internal IP
340
+ # First request: attacker.com -> 1.2.3.4 (passes validation)
341
+ # DNS changes: attacker.com -> 192.168.1.1
342
+ # Second request goes to internal IP
343
+
344
+ # Defense: Pin DNS resolution and re-validate
345
+ ```
346
+
347
+ ### IPv6
348
+
349
+ ```python
350
+ # Bypasses:
351
+ http://[::1]/ # localhost
352
+ http://[::ffff:127.0.0.1]/ # IPv4-mapped IPv6
353
+ http://[0:0:0:0:0:ffff:169.254.169.254]/
354
+
355
+ # Defense: Check both IPv4 and IPv6 ranges
356
+ BLOCKED_RANGES.extend([
357
+ ipaddress.ip_network('::1/128'), # IPv6 loopback
358
+ ipaddress.ip_network('fc00::/7'), # IPv6 private
359
+ ipaddress.ip_network('fe80::/10'), # IPv6 link-local
360
+ ])
361
+ ```
362
+
363
+ ### Alternate Representations
364
+
365
+ ```python
366
+ # localhost alternatives:
367
+ localhost
368
+ 127.0.0.1
369
+ 127.0.0.2 # Any 127.x.x.x is loopback
370
+ 2130706433 # Decimal for 127.0.0.1
371
+ 0x7f000001 # Hex
372
+ 0177.0.0.1 # Octal
373
+ 127.1 # Short form
374
+ ```
375
+
376
+ ---
377
+
378
+ ## Grep Patterns for Detection
379
+
380
+ ```bash
381
+ # URL fetching functions
382
+ grep -rn "requests\.get\|requests\.post\|urllib\.request\|urlopen\|fetch\|axios" --include="*.py" --include="*.js"
383
+
384
+ # URL from user input
385
+ grep -rn "request\.args\|request\.form\|request\.json\|req\.query\|req\.body" --include="*.py" --include="*.js" | grep -i "url"
386
+
387
+ # Potential SSRF sinks
388
+ grep -rn "curl_exec\|file_get_contents\|fopen\|readfile" --include="*.php"
389
+
390
+ # Missing validation
391
+ grep -rn "requests\.get(url\|fetch(url" --include="*.py" --include="*.js"
392
+ ```
393
+
394
+ ---
395
+
396
+ ## Testing Checklist
397
+
398
+ - [ ] User-controlled URLs validated against allowlist
399
+ - [ ] Internal IP ranges blocked (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
400
+ - [ ] Cloud metadata IPs blocked (169.254.169.254)
401
+ - [ ] IPv6 internal addresses blocked
402
+ - [ ] URL redirects not followed blindly
403
+ - [ ] DNS rebinding protected against
404
+ - [ ] URL encoding/alternate representations handled
405
+ - [ ] IMDSv2 required (AWS environments)
406
+ - [ ] Timeouts configured to prevent DoS
407
+
408
+ ---
409
+
410
+ ## References
411
+
412
+ - [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)
413
+ - [CWE-918: Server-Side Request Forgery](https://cwe.mitre.org/data/definitions/918.html)
414
+ - [AWS IMDSv2 Documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)
415
+ - [PortSwigger SSRF Guide](https://portswigger.net/web-security/ssrf)