@brunosps00/dev-workflow 0.0.3 → 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/README.md +42 -42
- package/bin/dev-workflow.js +6 -4
- package/lib/constants.js +42 -40
- package/lib/init.js +66 -19
- package/package.json +1 -1
- package/scaffold/en/commands/{analyze-project.md → dw-analyze-project.md} +69 -40
- package/scaffold/en/commands/{brainstorm.md → dw-brainstorm.md} +31 -4
- package/scaffold/en/commands/{bugfix.md → dw-bugfix.md} +63 -19
- package/scaffold/en/commands/{code-review.md → dw-code-review.md} +38 -15
- package/scaffold/en/commands/{commit.md → dw-commit.md} +25 -0
- package/scaffold/en/commands/{create-prd.md → dw-create-prd.md} +24 -10
- package/scaffold/en/commands/{create-tasks.md → dw-create-tasks.md} +11 -4
- package/scaffold/en/commands/{create-techspec.md → dw-create-techspec.md} +38 -11
- package/scaffold/en/commands/{deep-research.md → dw-deep-research.md} +18 -17
- package/scaffold/en/commands/{fix-qa.md → dw-fix-qa.md} +20 -3
- package/scaffold/en/commands/dw-functional-doc.md +276 -0
- package/scaffold/en/commands/{generate-pr.md → dw-generate-pr.md} +20 -5
- package/scaffold/en/commands/dw-help.md +309 -0
- package/scaffold/en/commands/{refactoring-analysis.md → dw-refactoring-analysis.md} +50 -26
- package/scaffold/en/commands/{review-implementation.md → dw-review-implementation.md} +25 -6
- package/scaffold/en/commands/{run-plan.md → dw-run-plan.md} +21 -6
- package/scaffold/en/commands/{run-qa.md → dw-run-qa.md} +32 -13
- package/scaffold/en/commands/{run-task.md → dw-run-task.md} +17 -7
- package/scaffold/en/references/playwright-patterns.md +136 -0
- package/scaffold/en/references/refactoring-catalog.md +167 -0
- package/scaffold/en/templates/brainstorm-matrix.md +44 -0
- package/scaffold/en/templates/functional-doc/case-matrix.md +5 -0
- package/scaffold/en/templates/functional-doc/e2e-runbook.md +3 -0
- package/scaffold/en/templates/functional-doc/features.md +3 -0
- package/scaffold/en/templates/functional-doc/overview.md +21 -0
- package/scaffold/en/templates/functional-doc/playwright.spec.ts.tpl +19 -0
- package/scaffold/en/templates/pr-bugfix-template.md +28 -0
- package/scaffold/en/templates/qa-test-credentials.md +37 -0
- package/scaffold/en/templates/tasks-template.md +1 -1
- package/scaffold/en/templates/techspec-template.md +1 -1
- package/scaffold/pt-br/commands/{analyze-project.md → dw-analyze-project.md} +94 -44
- package/scaffold/pt-br/commands/{brainstorm.md → dw-brainstorm.md} +32 -5
- package/scaffold/pt-br/commands/{bugfix.md → dw-bugfix.md} +73 -16
- package/scaffold/pt-br/commands/{code-review.md → dw-code-review.md} +80 -17
- package/scaffold/pt-br/commands/{commit.md → dw-commit.md} +45 -1
- package/scaffold/pt-br/commands/{create-prd.md → dw-create-prd.md} +25 -10
- package/scaffold/pt-br/commands/{create-tasks.md → dw-create-tasks.md} +24 -17
- package/scaffold/pt-br/commands/{create-techspec.md → dw-create-techspec.md} +40 -13
- package/scaffold/pt-br/commands/{deep-research.md → dw-deep-research.md} +19 -11
- package/scaffold/pt-br/commands/{fix-qa.md → dw-fix-qa.md} +30 -1
- package/scaffold/pt-br/commands/dw-functional-doc.md +276 -0
- package/scaffold/pt-br/commands/{generate-pr.md → dw-generate-pr.md} +61 -6
- package/scaffold/pt-br/commands/dw-help.md +248 -0
- package/scaffold/pt-br/commands/{refactoring-analysis.md → dw-refactoring-analysis.md} +49 -25
- package/scaffold/pt-br/commands/{review-implementation.md → dw-review-implementation.md} +53 -5
- package/scaffold/pt-br/commands/{run-plan.md → dw-run-plan.md} +100 -12
- package/scaffold/pt-br/commands/{run-qa.md → dw-run-qa.md} +93 -18
- package/scaffold/pt-br/commands/{run-task.md → dw-run-task.md} +35 -10
- package/scaffold/pt-br/references/playwright-patterns.md +133 -0
- package/scaffold/pt-br/references/refactoring-catalog.md +166 -0
- package/scaffold/pt-br/templates/brainstorm-matrix.md +44 -0
- package/scaffold/pt-br/templates/functional-doc/case-matrix.md +5 -0
- package/scaffold/pt-br/templates/functional-doc/e2e-runbook.md +3 -0
- package/scaffold/pt-br/templates/functional-doc/features.md +3 -0
- package/scaffold/pt-br/templates/functional-doc/overview.md +21 -0
- package/scaffold/pt-br/templates/functional-doc/playwright.spec.ts.tpl +19 -0
- package/scaffold/pt-br/templates/pr-bugfix-template.md +28 -0
- package/scaffold/pt-br/templates/qa-test-credentials.md +37 -0
- package/scaffold/pt-br/templates/tasks-template.md +2 -2
- package/scaffold/pt-br/templates/techspec-template.md +1 -1
- package/scaffold/rules-readme.md +3 -3
- package/scaffold/scripts/functional-doc/generate-dossier.mjs +821 -0
- package/scaffold/scripts/functional-doc/run-playwright-flow.mjs +275 -0
- 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
- package/scaffold/en/commands/help.md +0 -289
- package/scaffold/pt-br/commands/help.md +0 -226
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# Security Logging Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Insufficient logging and monitoring failures allow attacks to go undetected. This includes missing audit trails, sensitive data in logs, log injection attacks, and inadequate alerting on security events.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Missing Security Event Logging
|
|
10
|
+
|
|
11
|
+
### Events That Must Be Logged
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
# VULNERABLE: No logging of security events
|
|
15
|
+
def login(username, password):
|
|
16
|
+
user = authenticate(username, password)
|
|
17
|
+
if user:
|
|
18
|
+
return create_session(user)
|
|
19
|
+
return None # Failed login not logged
|
|
20
|
+
|
|
21
|
+
def change_password(user, old_pass, new_pass):
|
|
22
|
+
if verify_password(old_pass, user.password):
|
|
23
|
+
user.password = hash_password(new_pass)
|
|
24
|
+
user.save() # Password change not logged
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Required Security Events
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import logging
|
|
31
|
+
from datetime import datetime
|
|
32
|
+
|
|
33
|
+
security_logger = logging.getLogger('security')
|
|
34
|
+
|
|
35
|
+
# Authentication events
|
|
36
|
+
def login(username, password):
|
|
37
|
+
user = authenticate(username, password)
|
|
38
|
+
if user:
|
|
39
|
+
security_logger.info(
|
|
40
|
+
"login_success",
|
|
41
|
+
extra={
|
|
42
|
+
'user_id': user.id,
|
|
43
|
+
'username': username,
|
|
44
|
+
'ip': request.remote_addr,
|
|
45
|
+
'user_agent': request.user_agent.string,
|
|
46
|
+
'timestamp': datetime.utcnow().isoformat()
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
return create_session(user)
|
|
50
|
+
else:
|
|
51
|
+
security_logger.warning(
|
|
52
|
+
"login_failure",
|
|
53
|
+
extra={
|
|
54
|
+
'username': username,
|
|
55
|
+
'ip': request.remote_addr,
|
|
56
|
+
'reason': 'invalid_credentials',
|
|
57
|
+
'timestamp': datetime.utcnow().isoformat()
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
# Access control events
|
|
63
|
+
def access_resource(user, resource):
|
|
64
|
+
if not user.can_access(resource):
|
|
65
|
+
security_logger.warning(
|
|
66
|
+
"access_denied",
|
|
67
|
+
extra={
|
|
68
|
+
'user_id': user.id,
|
|
69
|
+
'resource': resource.id,
|
|
70
|
+
'action': 'read',
|
|
71
|
+
'ip': request.remote_addr
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
raise PermissionDenied()
|
|
75
|
+
|
|
76
|
+
# Critical data changes
|
|
77
|
+
def update_user_role(admin, user, new_role):
|
|
78
|
+
old_role = user.role
|
|
79
|
+
user.role = new_role
|
|
80
|
+
user.save()
|
|
81
|
+
security_logger.info(
|
|
82
|
+
"role_change",
|
|
83
|
+
extra={
|
|
84
|
+
'admin_id': admin.id,
|
|
85
|
+
'target_user_id': user.id,
|
|
86
|
+
'old_role': old_role,
|
|
87
|
+
'new_role': new_role
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Security Events Checklist
|
|
93
|
+
|
|
94
|
+
| Event Type | Must Log |
|
|
95
|
+
|------------|----------|
|
|
96
|
+
| Login success/failure | User, IP, timestamp, method |
|
|
97
|
+
| Logout | User, session duration |
|
|
98
|
+
| Password change | User, IP, timestamp |
|
|
99
|
+
| Password reset request | Email/user, IP |
|
|
100
|
+
| Account lockout | User, reason, duration |
|
|
101
|
+
| MFA enrollment/removal | User, method |
|
|
102
|
+
| Permission changes | Admin, target, old/new |
|
|
103
|
+
| Access denied | User, resource, action |
|
|
104
|
+
| Data export | User, data type, volume |
|
|
105
|
+
| Admin actions | Admin, action, target |
|
|
106
|
+
| API key creation/revocation | User, key ID (not key) |
|
|
107
|
+
| Security setting changes | User, setting, old/new |
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Sensitive Data in Logs
|
|
112
|
+
|
|
113
|
+
### Dangerous Patterns
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
# VULNERABLE: Logging passwords
|
|
117
|
+
logger.info(f"User {username} login attempt with password {password}")
|
|
118
|
+
logger.debug(f"Auth request: {request.json}") # Contains password
|
|
119
|
+
|
|
120
|
+
# VULNERABLE: Logging tokens/secrets
|
|
121
|
+
logger.info(f"API request with key: {api_key}")
|
|
122
|
+
logger.debug(f"JWT token: {token}")
|
|
123
|
+
logger.info(f"Session: {session_cookie}")
|
|
124
|
+
|
|
125
|
+
# VULNERABLE: Logging PII
|
|
126
|
+
logger.info(f"Processing payment for SSN: {ssn}")
|
|
127
|
+
logger.debug(f"User data: {user.__dict__}") # May contain sensitive fields
|
|
128
|
+
|
|
129
|
+
# VULNERABLE: Logging credit card numbers
|
|
130
|
+
logger.info(f"Payment with card: {card_number}")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Secure Logging
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
# SAFE: Never log credentials
|
|
137
|
+
logger.info(f"Login attempt for user: {username}") # No password
|
|
138
|
+
|
|
139
|
+
# SAFE: Mask sensitive data
|
|
140
|
+
def mask_token(token):
|
|
141
|
+
if len(token) > 8:
|
|
142
|
+
return token[:4] + '****' + token[-4:]
|
|
143
|
+
return '****'
|
|
144
|
+
|
|
145
|
+
logger.info(f"API request with key: {mask_token(api_key)}")
|
|
146
|
+
|
|
147
|
+
# SAFE: Redact PII
|
|
148
|
+
def redact_pii(data):
|
|
149
|
+
sensitive_fields = {'password', 'ssn', 'credit_card', 'api_key', 'token'}
|
|
150
|
+
if isinstance(data, dict):
|
|
151
|
+
return {k: '[REDACTED]' if k in sensitive_fields else v
|
|
152
|
+
for k, v in data.items()}
|
|
153
|
+
return data
|
|
154
|
+
|
|
155
|
+
logger.debug(f"Request data: {redact_pii(request.json)}")
|
|
156
|
+
|
|
157
|
+
# SAFE: Use structured logging with explicit fields
|
|
158
|
+
logger.info(
|
|
159
|
+
"payment_processed",
|
|
160
|
+
extra={
|
|
161
|
+
'user_id': user.id,
|
|
162
|
+
'amount': amount,
|
|
163
|
+
'card_last_four': card_number[-4:], # Only last 4
|
|
164
|
+
'transaction_id': txn_id
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Log Injection
|
|
172
|
+
|
|
173
|
+
### Attack Vector
|
|
174
|
+
|
|
175
|
+
Attackers inject malicious content into logs to:
|
|
176
|
+
- Forge log entries
|
|
177
|
+
- Exploit log viewers (XSS in log dashboards)
|
|
178
|
+
- Manipulate log analysis tools
|
|
179
|
+
- Hide malicious activity
|
|
180
|
+
|
|
181
|
+
### Vulnerable Patterns
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# VULNERABLE: Unsanitized user input in logs
|
|
185
|
+
logger.info(f"User search: {user_input}")
|
|
186
|
+
# Attack: user_input = "search\n2024-01-01 INFO admin logged in successfully"
|
|
187
|
+
|
|
188
|
+
# VULNERABLE: Direct interpolation
|
|
189
|
+
logger.info("Search query: " + query)
|
|
190
|
+
# Attack: query contains newlines and fake log entries
|
|
191
|
+
|
|
192
|
+
# VULNERABLE: Format string injection
|
|
193
|
+
logger.info("User %s performed action" % user_input)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Secure Logging
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
# SAFE: Sanitize input before logging
|
|
200
|
+
import re
|
|
201
|
+
|
|
202
|
+
def sanitize_log_input(value):
|
|
203
|
+
"""Remove newlines and control characters."""
|
|
204
|
+
if isinstance(value, str):
|
|
205
|
+
# Remove newlines and carriage returns
|
|
206
|
+
value = value.replace('\n', '\\n').replace('\r', '\\r')
|
|
207
|
+
# Remove other control characters
|
|
208
|
+
value = re.sub(r'[\x00-\x1f\x7f-\x9f]', '', value)
|
|
209
|
+
return value
|
|
210
|
+
|
|
211
|
+
logger.info(f"User search: {sanitize_log_input(user_input)}")
|
|
212
|
+
|
|
213
|
+
# SAFE: Use structured logging (JSON)
|
|
214
|
+
import json_logging
|
|
215
|
+
json_logging.init_non_web()
|
|
216
|
+
|
|
217
|
+
logger.info("search_performed", extra={
|
|
218
|
+
'query': user_input, # JSON encoding handles special chars
|
|
219
|
+
'user_id': user.id
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
# SAFE: Use parameterized logging
|
|
223
|
+
logger.info("User %s searched for %s", user_id, sanitize_log_input(query))
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Log Storage Security
|
|
229
|
+
|
|
230
|
+
### Insecure Patterns
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
# VULNERABLE: World-readable log files
|
|
234
|
+
logging.basicConfig(filename='/var/log/app.log')
|
|
235
|
+
os.chmod('/var/log/app.log', 0o644) # Anyone can read
|
|
236
|
+
|
|
237
|
+
# VULNERABLE: Logs in web-accessible directory
|
|
238
|
+
logging.basicConfig(filename='/var/www/html/logs/app.log')
|
|
239
|
+
|
|
240
|
+
# VULNERABLE: No log rotation (can fill disk)
|
|
241
|
+
logging.basicConfig(filename='app.log') # Grows forever
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Secure Log Configuration
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
# SAFE: Restricted permissions
|
|
248
|
+
import os
|
|
249
|
+
from logging.handlers import RotatingFileHandler
|
|
250
|
+
|
|
251
|
+
log_file = '/var/log/app/security.log'
|
|
252
|
+
handler = RotatingFileHandler(
|
|
253
|
+
log_file,
|
|
254
|
+
maxBytes=10*1024*1024, # 10MB
|
|
255
|
+
backupCount=10
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Set restrictive permissions
|
|
259
|
+
os.chmod(log_file, 0o600) # Owner only
|
|
260
|
+
|
|
261
|
+
# SAFE: Centralized logging with encryption
|
|
262
|
+
import logging.handlers
|
|
263
|
+
|
|
264
|
+
syslog_handler = logging.handlers.SysLogHandler(
|
|
265
|
+
address=('secure-syslog.company.com', 514),
|
|
266
|
+
socktype=socket.SOCK_STREAM # TCP for reliability
|
|
267
|
+
)
|
|
268
|
+
# Use TLS for syslog transport
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Missing Alerting
|
|
274
|
+
|
|
275
|
+
### Security Events Requiring Alerts
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
# These should trigger immediate alerts, not just logging
|
|
279
|
+
|
|
280
|
+
ALERT_THRESHOLDS = {
|
|
281
|
+
'failed_logins': 5, # Per user per hour
|
|
282
|
+
'access_denied': 10, # Per user per hour
|
|
283
|
+
'admin_login': 1, # Any admin login from new IP
|
|
284
|
+
'privilege_escalation': 1, # Any role change
|
|
285
|
+
'data_export': 1, # Large data exports
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
def check_alert_threshold(event_type, user_id):
|
|
289
|
+
count = get_recent_event_count(event_type, user_id, hours=1)
|
|
290
|
+
if count >= ALERT_THRESHOLDS.get(event_type, float('inf')):
|
|
291
|
+
send_security_alert(
|
|
292
|
+
event_type=event_type,
|
|
293
|
+
user_id=user_id,
|
|
294
|
+
count=count,
|
|
295
|
+
severity='high' if event_type in ['admin_login', 'privilege_escalation'] else 'medium'
|
|
296
|
+
)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Alert Configuration
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
# Security monitoring rules
|
|
303
|
+
MONITORING_RULES = [
|
|
304
|
+
{
|
|
305
|
+
'name': 'brute_force_detection',
|
|
306
|
+
'condition': 'failed_logins > 5 in 5 minutes from same IP',
|
|
307
|
+
'action': 'block_ip, alert_security_team'
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
'name': 'impossible_travel',
|
|
311
|
+
'condition': 'login from geographically impossible location',
|
|
312
|
+
'action': 'require_mfa, alert_user'
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
'name': 'off_hours_admin',
|
|
316
|
+
'condition': 'admin action outside business hours',
|
|
317
|
+
'action': 'alert_security_team'
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
'name': 'mass_data_access',
|
|
321
|
+
'condition': 'data export > 10000 records',
|
|
322
|
+
'action': 'alert_security_team, require_approval'
|
|
323
|
+
}
|
|
324
|
+
]
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Audit Trail Requirements
|
|
330
|
+
|
|
331
|
+
### Immutable Audit Logs
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
# VULNERABLE: Mutable logs
|
|
335
|
+
def delete_audit_log(log_id):
|
|
336
|
+
AuditLog.query.filter_by(id=log_id).delete() # Can be deleted
|
|
337
|
+
|
|
338
|
+
# SAFE: Append-only audit logs
|
|
339
|
+
class AuditLog(db.Model):
|
|
340
|
+
id = db.Column(db.Integer, primary_key=True)
|
|
341
|
+
timestamp = db.Column(db.DateTime, nullable=False)
|
|
342
|
+
event_type = db.Column(db.String, nullable=False)
|
|
343
|
+
user_id = db.Column(db.Integer)
|
|
344
|
+
details = db.Column(db.JSON)
|
|
345
|
+
checksum = db.Column(db.String) # Hash of previous entry
|
|
346
|
+
|
|
347
|
+
@classmethod
|
|
348
|
+
def create(cls, event_type, user_id, details):
|
|
349
|
+
# Get previous entry's checksum for chain
|
|
350
|
+
prev = cls.query.order_by(cls.id.desc()).first()
|
|
351
|
+
prev_checksum = prev.checksum if prev else 'genesis'
|
|
352
|
+
|
|
353
|
+
entry = cls(
|
|
354
|
+
timestamp=datetime.utcnow(),
|
|
355
|
+
event_type=event_type,
|
|
356
|
+
user_id=user_id,
|
|
357
|
+
details=details
|
|
358
|
+
)
|
|
359
|
+
# Chain checksum
|
|
360
|
+
entry.checksum = hashlib.sha256(
|
|
361
|
+
f"{prev_checksum}{entry.timestamp}{entry.event_type}".encode()
|
|
362
|
+
).hexdigest()
|
|
363
|
+
db.session.add(entry)
|
|
364
|
+
db.session.commit()
|
|
365
|
+
return entry
|
|
366
|
+
|
|
367
|
+
# No delete method - audit logs are immutable
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Retention Requirements
|
|
371
|
+
|
|
372
|
+
```python
|
|
373
|
+
# Configure retention based on compliance requirements
|
|
374
|
+
LOG_RETENTION = {
|
|
375
|
+
'security_events': 365, # 1 year
|
|
376
|
+
'authentication': 90, # 90 days
|
|
377
|
+
'access_logs': 30, # 30 days
|
|
378
|
+
'debug_logs': 7, # 7 days
|
|
379
|
+
'audit_trail': 2555, # 7 years (compliance)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
def cleanup_old_logs():
|
|
383
|
+
for log_type, days in LOG_RETENTION.items():
|
|
384
|
+
cutoff = datetime.utcnow() - timedelta(days=days)
|
|
385
|
+
delete_logs_before(log_type, cutoff)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Grep Patterns for Detection
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
# Missing security logging
|
|
394
|
+
grep -rn "def login\|def authenticate" --include="*.py" | xargs -I {} grep -L "logger\|logging" {}
|
|
395
|
+
|
|
396
|
+
# Sensitive data in logs
|
|
397
|
+
grep -rn "logger.*password\|logging.*password\|log.*password" --include="*.py"
|
|
398
|
+
grep -rn "logger.*token\|logger.*secret\|logger.*key" --include="*.py"
|
|
399
|
+
|
|
400
|
+
# Unsanitized log input
|
|
401
|
+
grep -rn "logger.*f\"\|logger.*%s.*%" --include="*.py"
|
|
402
|
+
|
|
403
|
+
# Missing log rotation
|
|
404
|
+
grep -rn "basicConfig.*filename\|FileHandler" --include="*.py" | grep -v "Rotating"
|
|
405
|
+
|
|
406
|
+
# World-readable logs
|
|
407
|
+
grep -rn "chmod.*644\|chmod.*755" --include="*.py" | grep -i log
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## Testing Checklist
|
|
413
|
+
|
|
414
|
+
- [ ] Authentication events (success/failure) logged
|
|
415
|
+
- [ ] Authorization failures logged
|
|
416
|
+
- [ ] Sensitive operations logged (password change, role change)
|
|
417
|
+
- [ ] No passwords/tokens/secrets in logs
|
|
418
|
+
- [ ] Log injection prevented (newlines sanitized)
|
|
419
|
+
- [ ] Logs have restricted file permissions
|
|
420
|
+
- [ ] Log rotation configured
|
|
421
|
+
- [ ] Centralized logging for production
|
|
422
|
+
- [ ] Alerts configured for security events
|
|
423
|
+
- [ ] Audit trail is immutable
|
|
424
|
+
- [ ] Log retention meets compliance requirements
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## References
|
|
429
|
+
|
|
430
|
+
- [OWASP Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)
|
|
431
|
+
- [OWASP Logging Vocabulary](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Vocabulary_Cheat_Sheet.html)
|
|
432
|
+
- [CWE-778: Insufficient Logging](https://cwe.mitre.org/data/definitions/778.html)
|
|
433
|
+
- [CWE-532: Information Exposure Through Log Files](https://cwe.mitre.org/data/definitions/532.html)
|