@brunosps00/dev-workflow 0.0.5 → 0.0.7

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 (166) hide show
  1. package/bin/dev-workflow.js +6 -4
  2. package/lib/constants.js +11 -0
  3. package/lib/init.js +36 -12
  4. package/lib/wrappers.js +8 -2
  5. package/package.json +1 -1
  6. package/scaffold/pt-br/commands/dw-analyze-project.md +3 -3
  7. package/scaffold/pt-br/commands/dw-bugfix.md +6 -6
  8. package/scaffold/pt-br/commands/dw-code-review.md +2 -2
  9. package/scaffold/pt-br/commands/dw-create-tasks.md +4 -4
  10. package/scaffold/pt-br/commands/dw-generate-pr.md +3 -3
  11. package/scaffold/pt-br/commands/dw-help.md +50 -50
  12. package/scaffold/pt-br/commands/dw-review-implementation.md +3 -3
  13. package/scaffold/pt-br/commands/dw-run-plan.md +8 -8
  14. package/scaffold/pt-br/commands/dw-run-task.md +3 -3
  15. package/scaffold/pt-br/templates/tasks-template.md +2 -2
  16. package/scaffold/skills/agent-browser/SKILL.md +750 -0
  17. package/scaffold/skills/agent-browser/references/authentication.md +303 -0
  18. package/scaffold/skills/agent-browser/references/commands.md +295 -0
  19. package/scaffold/skills/agent-browser/references/profiling.md +120 -0
  20. package/scaffold/skills/agent-browser/references/proxy-support.md +194 -0
  21. package/scaffold/skills/agent-browser/references/session-management.md +193 -0
  22. package/scaffold/skills/agent-browser/references/snapshot-refs.md +219 -0
  23. package/scaffold/skills/agent-browser/references/video-recording.md +173 -0
  24. package/scaffold/skills/agent-browser/templates/authenticated-session.sh +105 -0
  25. package/scaffold/skills/agent-browser/templates/capture-workflow.sh +69 -0
  26. package/scaffold/skills/agent-browser/templates/form-automation.sh +62 -0
  27. package/scaffold/skills/humanizer/README.md +143 -0
  28. package/scaffold/skills/humanizer/SKILL.md +488 -0
  29. package/scaffold/skills/humanizer/WARP.md +53 -0
  30. package/scaffold/skills/remotion-best-practices/SKILL.md +61 -0
  31. package/scaffold/skills/remotion-best-practices/rules/3d.md +86 -0
  32. package/scaffold/skills/remotion-best-practices/rules/animations.md +27 -0
  33. package/scaffold/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  34. package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  35. package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
  36. package/scaffold/skills/remotion-best-practices/rules/assets.md +78 -0
  37. package/scaffold/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
  38. package/scaffold/skills/remotion-best-practices/rules/audio.md +169 -0
  39. package/scaffold/skills/remotion-best-practices/rules/calculate-metadata.md +134 -0
  40. package/scaffold/skills/remotion-best-practices/rules/can-decode.md +75 -0
  41. package/scaffold/skills/remotion-best-practices/rules/charts.md +120 -0
  42. package/scaffold/skills/remotion-best-practices/rules/compositions.md +154 -0
  43. package/scaffold/skills/remotion-best-practices/rules/display-captions.md +184 -0
  44. package/scaffold/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  45. package/scaffold/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
  46. package/scaffold/skills/remotion-best-practices/rules/fonts.md +152 -0
  47. package/scaffold/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  48. package/scaffold/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  49. package/scaffold/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
  50. package/scaffold/skills/remotion-best-practices/rules/gifs.md +141 -0
  51. package/scaffold/skills/remotion-best-practices/rules/images.md +134 -0
  52. package/scaffold/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
  53. package/scaffold/skills/remotion-best-practices/rules/light-leaks.md +73 -0
  54. package/scaffold/skills/remotion-best-practices/rules/lottie.md +70 -0
  55. package/scaffold/skills/remotion-best-practices/rules/maps.md +412 -0
  56. package/scaffold/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  57. package/scaffold/skills/remotion-best-practices/rules/measuring-text.md +140 -0
  58. package/scaffold/skills/remotion-best-practices/rules/parameters.md +109 -0
  59. package/scaffold/skills/remotion-best-practices/rules/sequencing.md +118 -0
  60. package/scaffold/skills/remotion-best-practices/rules/sfx.md +26 -0
  61. package/scaffold/skills/remotion-best-practices/rules/subtitles.md +36 -0
  62. package/scaffold/skills/remotion-best-practices/rules/tailwind.md +11 -0
  63. package/scaffold/skills/remotion-best-practices/rules/text-animations.md +20 -0
  64. package/scaffold/skills/remotion-best-practices/rules/timing.md +179 -0
  65. package/scaffold/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
  66. package/scaffold/skills/remotion-best-practices/rules/transitions.md +197 -0
  67. package/scaffold/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
  68. package/scaffold/skills/remotion-best-practices/rules/trimming.md +51 -0
  69. package/scaffold/skills/remotion-best-practices/rules/videos.md +171 -0
  70. package/scaffold/skills/remotion-best-practices/rules/voiceover.md +99 -0
  71. package/scaffold/skills/security-review/LICENSE +22 -0
  72. package/scaffold/skills/security-review/SKILL.md +312 -0
  73. package/scaffold/skills/security-review/infrastructure/docker.md +432 -0
  74. package/scaffold/skills/security-review/languages/javascript.md +388 -0
  75. package/scaffold/skills/security-review/languages/python.md +363 -0
  76. package/scaffold/skills/security-review/references/api-security.md +519 -0
  77. package/scaffold/skills/security-review/references/authentication.md +353 -0
  78. package/scaffold/skills/security-review/references/authorization.md +372 -0
  79. package/scaffold/skills/security-review/references/business-logic.md +443 -0
  80. package/scaffold/skills/security-review/references/cryptography.md +329 -0
  81. package/scaffold/skills/security-review/references/csrf.md +398 -0
  82. package/scaffold/skills/security-review/references/data-protection.md +378 -0
  83. package/scaffold/skills/security-review/references/deserialization.md +410 -0
  84. package/scaffold/skills/security-review/references/error-handling.md +436 -0
  85. package/scaffold/skills/security-review/references/file-security.md +457 -0
  86. package/scaffold/skills/security-review/references/injection.md +259 -0
  87. package/scaffold/skills/security-review/references/logging.md +433 -0
  88. package/scaffold/skills/security-review/references/misconfiguration.md +435 -0
  89. package/scaffold/skills/security-review/references/modern-threats.md +475 -0
  90. package/scaffold/skills/security-review/references/ssrf.md +415 -0
  91. package/scaffold/skills/security-review/references/supply-chain.md +405 -0
  92. package/scaffold/skills/security-review/references/xss.md +336 -0
  93. package/scaffold/skills/vercel-react-best-practices/AGENTS.md +3648 -0
  94. package/scaffold/skills/vercel-react-best-practices/README.md +123 -0
  95. package/scaffold/skills/vercel-react-best-practices/SKILL.md +146 -0
  96. package/scaffold/skills/vercel-react-best-practices/rules/_sections.md +46 -0
  97. package/scaffold/skills/vercel-react-best-practices/rules/_template.md +28 -0
  98. package/scaffold/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  99. package/scaffold/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  100. package/scaffold/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  101. package/scaffold/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  102. package/scaffold/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  103. package/scaffold/skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
  104. package/scaffold/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  105. package/scaffold/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  106. package/scaffold/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  107. package/scaffold/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
  108. package/scaffold/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  109. package/scaffold/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  110. package/scaffold/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  111. package/scaffold/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  112. package/scaffold/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  113. package/scaffold/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  114. package/scaffold/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  115. package/scaffold/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  116. package/scaffold/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  117. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  118. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  119. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  120. package/scaffold/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  121. package/scaffold/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  122. package/scaffold/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
  123. package/scaffold/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  124. package/scaffold/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  125. package/scaffold/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  126. package/scaffold/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  127. package/scaffold/skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
  128. package/scaffold/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  129. package/scaffold/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  130. package/scaffold/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  131. package/scaffold/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  132. package/scaffold/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  133. package/scaffold/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  134. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  135. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  136. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  137. package/scaffold/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
  138. package/scaffold/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
  139. package/scaffold/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  140. package/scaffold/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  141. package/scaffold/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  142. package/scaffold/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  143. package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  144. package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  145. package/scaffold/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  146. package/scaffold/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  147. package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  148. package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  149. package/scaffold/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  150. package/scaffold/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
  151. package/scaffold/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  152. package/scaffold/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  153. package/scaffold/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  154. package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  155. package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  156. package/scaffold/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  157. package/scaffold/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  158. package/scaffold/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  159. package/scaffold/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  160. package/scaffold/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  161. package/scaffold/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
  162. package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  163. package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
  164. package/scaffold/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  165. package/scaffold/skills/webapp-testing/SKILL.md +133 -0
  166. package/scaffold/skills/webapp-testing/assets/test-helper.js +56 -0
@@ -0,0 +1,436 @@
1
+ # Error Handling Security Reference
2
+
3
+ ## Overview
4
+
5
+ Improper error handling can lead to information disclosure, denial of service, or security bypasses. This includes verbose error messages exposing internals, fail-open patterns that skip security checks on errors, and unhandled exceptions that crash services or leave systems in insecure states.
6
+
7
+ ---
8
+
9
+ ## Information Disclosure
10
+
11
+ ### Stack Traces in Responses
12
+
13
+ ```python
14
+ # VULNERABLE: Stack trace exposed to users
15
+ @app.errorhandler(Exception)
16
+ def handle_error(e):
17
+ return f"Error: {traceback.format_exc()}", 500
18
+
19
+ # VULNERABLE: Detailed exception info
20
+ @app.route('/api/user/<id>')
21
+ def get_user(id):
22
+ try:
23
+ return User.query.get(id).to_dict()
24
+ except Exception as e:
25
+ return jsonify({
26
+ 'error': str(e),
27
+ 'type': type(e).__name__,
28
+ 'args': e.args
29
+ }), 500
30
+ ```
31
+
32
+ ### Secure Error Handling
33
+
34
+ ```python
35
+ # SAFE: Generic messages, detailed logging
36
+ import logging
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+ @app.errorhandler(Exception)
41
+ def handle_error(e):
42
+ # Log full details server-side
43
+ logger.error(f"Unhandled exception: {e}", exc_info=True)
44
+
45
+ # Return generic message to client
46
+ return jsonify({'error': 'An internal error occurred'}), 500
47
+
48
+ # SAFE: Custom exceptions with safe messages
49
+ class UserNotFoundError(Exception):
50
+ pass
51
+
52
+ @app.route('/api/user/<id>')
53
+ def get_user(id):
54
+ try:
55
+ user = User.query.get(id)
56
+ if not user:
57
+ raise UserNotFoundError()
58
+ return user.to_dict()
59
+ except UserNotFoundError:
60
+ return jsonify({'error': 'User not found'}), 404
61
+ except Exception:
62
+ logger.exception("Error fetching user")
63
+ return jsonify({'error': 'Internal error'}), 500
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Fail-Open Patterns
69
+
70
+ ### Authentication Bypass on Error
71
+
72
+ ```python
73
+ # VULNERABLE: Fail-open authentication
74
+ def authenticate(token):
75
+ try:
76
+ user = verify_token(token)
77
+ return user
78
+ except Exception:
79
+ return None # Returns None, might be treated as valid
80
+
81
+ # VULNERABLE: Exception allows bypass
82
+ def check_permission(user, resource):
83
+ try:
84
+ return permission_service.check(user, resource)
85
+ except ServiceUnavailable:
86
+ return True # DANGEROUS: Allows access on service failure
87
+
88
+ # VULNERABLE: Default to authorized on error
89
+ @app.route('/admin')
90
+ def admin():
91
+ try:
92
+ if not is_admin(current_user):
93
+ abort(403)
94
+ except Exception:
95
+ pass # Silently continues to admin page
96
+ return render_admin_panel()
97
+ ```
98
+
99
+ ### Secure Fail-Closed Patterns
100
+
101
+ ```python
102
+ # SAFE: Fail-closed authentication
103
+ def authenticate(token):
104
+ try:
105
+ user = verify_token(token)
106
+ if user is None:
107
+ raise AuthenticationError("Invalid token")
108
+ return user
109
+ except Exception as e:
110
+ logger.error(f"Auth error: {e}")
111
+ raise AuthenticationError("Authentication failed")
112
+
113
+ # SAFE: Deny on service unavailable
114
+ def check_permission(user, resource):
115
+ try:
116
+ return permission_service.check(user, resource)
117
+ except ServiceUnavailable:
118
+ logger.error("Permission service unavailable")
119
+ return False # Deny access when unable to verify
120
+
121
+ # SAFE: Explicit denial on error
122
+ @app.route('/admin')
123
+ def admin():
124
+ try:
125
+ if not is_admin(current_user):
126
+ abort(403)
127
+ except Exception as e:
128
+ logger.error(f"Admin check failed: {e}")
129
+ abort(500) # Don't proceed on error
130
+ return render_admin_panel()
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Exception Swallowing
136
+
137
+ ### Dangerous Patterns
138
+
139
+ ```python
140
+ # VULNERABLE: Silent exception swallowing
141
+ try:
142
+ validate_input(user_input)
143
+ except:
144
+ pass # Validation skipped entirely
145
+
146
+ # VULNERABLE: Catch-all hides security issues
147
+ try:
148
+ result = dangerous_operation(user_data)
149
+ except Exception:
150
+ result = default_value # May hide injection attempts
151
+
152
+ # VULNERABLE: Empty except block
153
+ try:
154
+ decrypt_sensitive_data(data)
155
+ except:
156
+ pass # Continues with encrypted/invalid data
157
+ ```
158
+
159
+ ### Secure Exception Handling
160
+
161
+ ```python
162
+ # SAFE: Handle specific exceptions
163
+ try:
164
+ validate_input(user_input)
165
+ except ValidationError as e:
166
+ logger.warning(f"Validation failed: {e}")
167
+ return jsonify({'error': 'Invalid input'}), 400
168
+ except Exception as e:
169
+ logger.error(f"Unexpected validation error: {e}")
170
+ return jsonify({'error': 'Validation error'}), 500
171
+
172
+ # SAFE: Never silently swallow security-critical exceptions
173
+ try:
174
+ result = dangerous_operation(user_data)
175
+ except SecurityException as e:
176
+ logger.error(f"Security exception: {e}")
177
+ raise # Re-raise security exceptions
178
+ except ValueError as e:
179
+ logger.warning(f"Invalid data: {e}")
180
+ result = None
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Differential Error Messages
186
+
187
+ ### User Enumeration via Errors
188
+
189
+ ```python
190
+ # VULNERABLE: Different messages reveal user existence
191
+ @app.route('/login', methods=['POST'])
192
+ def login():
193
+ user = User.query.filter_by(email=email).first()
194
+ if not user:
195
+ return jsonify({'error': 'User not found'}), 401 # Reveals user doesn't exist
196
+ if not check_password(password, user.password):
197
+ return jsonify({'error': 'Wrong password'}), 401 # Reveals user exists
198
+ return create_session(user)
199
+
200
+ # VULNERABLE: Timing difference reveals user existence
201
+ def login(email, password):
202
+ user = User.query.filter_by(email=email).first()
203
+ if not user:
204
+ return False # Fast return
205
+ return check_password(password, user.password) # Slow hash check
206
+ ```
207
+
208
+ ### Secure Consistent Errors
209
+
210
+ ```python
211
+ # SAFE: Consistent error messages
212
+ @app.route('/login', methods=['POST'])
213
+ def login():
214
+ user = User.query.filter_by(email=email).first()
215
+ if not user or not check_password(password, user.password):
216
+ return jsonify({'error': 'Invalid credentials'}), 401 # Same message
217
+ return create_session(user)
218
+
219
+ # SAFE: Constant-time comparison with dummy hash
220
+ DUMMY_HASH = generate_password_hash('dummy')
221
+
222
+ def login(email, password):
223
+ user = User.query.filter_by(email=email).first()
224
+ if user:
225
+ valid = check_password(password, user.password)
226
+ else:
227
+ check_password(password, DUMMY_HASH) # Constant time even if user not found
228
+ valid = False
229
+ return valid
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Resource Exhaustion via Errors
235
+
236
+ ### Uncontrolled Exception Logging
237
+
238
+ ```python
239
+ # VULNERABLE: Attacker can fill logs
240
+ @app.route('/api/data')
241
+ def get_data():
242
+ try:
243
+ return process_data(request.json)
244
+ except Exception as e:
245
+ # Logs entire request body - attacker sends huge payloads
246
+ logger.error(f"Error processing: {request.json}")
247
+ return jsonify({'error': 'Error'}), 500
248
+ ```
249
+
250
+ ### Secure Logging
251
+
252
+ ```python
253
+ # SAFE: Limit logged data
254
+ @app.route('/api/data')
255
+ def get_data():
256
+ try:
257
+ return process_data(request.json)
258
+ except Exception as e:
259
+ # Log limited info, not full payload
260
+ logger.error(f"Error processing request from {request.remote_addr}")
261
+ return jsonify({'error': 'Error'}), 500
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Unhandled Async Exceptions
267
+
268
+ ### Dangerous Patterns
269
+
270
+ ```javascript
271
+ // VULNERABLE: Unhandled promise rejection
272
+ async function processUser(userId) {
273
+ const user = await fetchUser(userId); // No catch
274
+ return user;
275
+ }
276
+
277
+ // VULNERABLE: Missing error handler
278
+ app.get('/api/data', async (req, res) => {
279
+ const data = await fetchData(); // Unhandled rejection crashes server
280
+ res.json(data);
281
+ });
282
+ ```
283
+
284
+ ### Secure Async Handling
285
+
286
+ ```javascript
287
+ // SAFE: Always handle async errors
288
+ async function processUser(userId) {
289
+ try {
290
+ const user = await fetchUser(userId);
291
+ return user;
292
+ } catch (error) {
293
+ logger.error('Failed to fetch user', { userId, error });
294
+ throw new UserFetchError('Unable to fetch user');
295
+ }
296
+ }
297
+
298
+ // SAFE: Express async wrapper
299
+ const asyncHandler = (fn) => (req, res, next) => {
300
+ Promise.resolve(fn(req, res, next)).catch(next);
301
+ };
302
+
303
+ app.get('/api/data', asyncHandler(async (req, res) => {
304
+ const data = await fetchData();
305
+ res.json(data);
306
+ }));
307
+
308
+ // Global handler for unhandled rejections
309
+ process.on('unhandledRejection', (reason, promise) => {
310
+ logger.error('Unhandled Rejection', { reason });
311
+ // Don't exit - handle gracefully
312
+ });
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Error-Based SQL Injection Indicators
318
+
319
+ ### Verbose Database Errors
320
+
321
+ ```python
322
+ # VULNERABLE: Database errors exposed
323
+ @app.route('/api/search')
324
+ def search():
325
+ try:
326
+ results = db.execute(f"SELECT * FROM items WHERE name = '{query}'")
327
+ return jsonify(results)
328
+ except Exception as e:
329
+ return jsonify({'error': str(e)}), 500
330
+ # Exposes: "syntax error at or near 'OR'" - reveals SQL injection possibility
331
+ ```
332
+
333
+ ### Secure Database Error Handling
334
+
335
+ ```python
336
+ # SAFE: Generic database errors
337
+ @app.route('/api/search')
338
+ def search():
339
+ try:
340
+ results = db.execute("SELECT * FROM items WHERE name = %s", (query,))
341
+ return jsonify(results)
342
+ except DatabaseError as e:
343
+ logger.error(f"Database error: {e}")
344
+ return jsonify({'error': 'Search failed'}), 500
345
+ ```
346
+
347
+ ---
348
+
349
+ ## Cleanup on Error
350
+
351
+ ### Resource Leaks
352
+
353
+ ```python
354
+ # VULNERABLE: Resource not cleaned up on error
355
+ def process_file(filename):
356
+ f = open(filename)
357
+ data = f.read()
358
+ process(data) # If this raises, file handle leaks
359
+ f.close()
360
+
361
+ # VULNERABLE: Connection not returned to pool
362
+ def query_db():
363
+ conn = pool.get_connection()
364
+ result = conn.execute(query) # If this raises, connection leaks
365
+ pool.return_connection(conn)
366
+ return result
367
+ ```
368
+
369
+ ### Secure Resource Management
370
+
371
+ ```python
372
+ # SAFE: Context managers ensure cleanup
373
+ def process_file(filename):
374
+ with open(filename) as f:
375
+ data = f.read()
376
+ process(data) # File closed even on exception
377
+
378
+ # SAFE: Try-finally for cleanup
379
+ def query_db():
380
+ conn = pool.get_connection()
381
+ try:
382
+ result = conn.execute(query)
383
+ return result
384
+ finally:
385
+ pool.return_connection(conn) # Always returns connection
386
+ ```
387
+
388
+ ---
389
+
390
+ ## Grep Patterns for Detection
391
+
392
+ ```bash
393
+ # Bare except clauses
394
+ grep -rn "except:" --include="*.py" | grep -v "except Exception"
395
+
396
+ # Empty exception handlers
397
+ grep -rn "except.*:\s*$" -A1 --include="*.py" | grep "pass"
398
+
399
+ # Stack traces in responses
400
+ grep -rn "traceback\|format_exc\|exc_info" --include="*.py" | grep -v "logger\|logging"
401
+
402
+ # Fail-open patterns
403
+ grep -rn "except.*:\s*$" -A2 --include="*.py" | grep "return True\|return None"
404
+
405
+ # Detailed error messages
406
+ grep -rn "str(e)\|str(err)\|e\.args\|e\.message" --include="*.py" | grep "return\|jsonify\|response"
407
+
408
+ # Differential error messages
409
+ grep -rn "not found\|does not exist\|invalid password\|wrong password" --include="*.py"
410
+
411
+ # Unhandled async
412
+ grep -rn "await.*[^;]$" --include="*.js" --include="*.ts" | grep -v "try\|catch"
413
+ ```
414
+
415
+ ---
416
+
417
+ ## Testing Checklist
418
+
419
+ - [ ] No stack traces in production error responses
420
+ - [ ] All security checks fail-closed (deny on error)
421
+ - [ ] No empty except/catch blocks for security-critical code
422
+ - [ ] Consistent error messages for auth (no user enumeration)
423
+ - [ ] Async operations have error handlers
424
+ - [ ] Resources cleaned up on error (files, connections)
425
+ - [ ] Error logging doesn't include full user input
426
+ - [ ] Database errors don't expose query structure
427
+ - [ ] Rate limiting on error-generating endpoints
428
+
429
+ ---
430
+
431
+ ## References
432
+
433
+ - [OWASP Error Handling Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html)
434
+ - [CWE-209: Information Exposure Through Error Message](https://cwe.mitre.org/data/definitions/209.html)
435
+ - [CWE-755: Improper Handling of Exceptional Conditions](https://cwe.mitre.org/data/definitions/755.html)
436
+ - [CWE-636: Not Failing Securely](https://cwe.mitre.org/data/definitions/636.html)