@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,410 @@
|
|
|
1
|
+
# Insecure Deserialization Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Serialization converts objects into transferable data formats, while deserialization reconstructs those objects. Native language serialization formats pose significant risks—enabling denial-of-service, access control breaches, or remote code execution when processing untrusted input.
|
|
6
|
+
|
|
7
|
+
## The Risk
|
|
8
|
+
|
|
9
|
+
When an application deserializes untrusted data:
|
|
10
|
+
1. Attacker crafts malicious serialized data
|
|
11
|
+
2. Application deserializes it, instantiating objects
|
|
12
|
+
3. Object constructors/destructors execute attacker-controlled code
|
|
13
|
+
4. Results: RCE, DoS, authentication bypass, data tampering
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Language-Specific Vulnerabilities
|
|
18
|
+
|
|
19
|
+
### Python
|
|
20
|
+
|
|
21
|
+
#### Dangerous Functions
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
# VULNERABLE: pickle with untrusted data
|
|
25
|
+
import pickle
|
|
26
|
+
data = pickle.loads(untrusted_data) # RCE possible
|
|
27
|
+
|
|
28
|
+
# VULNERABLE: yaml.load (pre-5.1)
|
|
29
|
+
import yaml
|
|
30
|
+
data = yaml.load(untrusted_data) # RCE via !!python/object
|
|
31
|
+
|
|
32
|
+
# VULNERABLE: marshal
|
|
33
|
+
import marshal
|
|
34
|
+
code = marshal.loads(untrusted_data)
|
|
35
|
+
|
|
36
|
+
# VULNERABLE: shelve (uses pickle)
|
|
37
|
+
import shelve
|
|
38
|
+
db = shelve.open('data')
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
#### Safe Alternatives
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
# SAFE: JSON
|
|
45
|
+
import json
|
|
46
|
+
data = json.loads(untrusted_data) # Only primitive types
|
|
47
|
+
|
|
48
|
+
# SAFE: yaml.safe_load
|
|
49
|
+
import yaml
|
|
50
|
+
data = yaml.safe_load(untrusted_data) # No arbitrary objects
|
|
51
|
+
|
|
52
|
+
# SAFE: Explicit data classes with validation
|
|
53
|
+
from dataclasses import dataclass
|
|
54
|
+
from dacite import from_dict
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class UserInput:
|
|
58
|
+
name: str
|
|
59
|
+
email: str
|
|
60
|
+
|
|
61
|
+
data = from_dict(UserInput, json.loads(untrusted_data))
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### Detection Patterns
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
# Base64-encoded pickle often starts with: gASV
|
|
68
|
+
# Or hex: 80 04 95
|
|
69
|
+
|
|
70
|
+
import base64
|
|
71
|
+
if b'\x80\x04\x95' in base64.b64decode(data):
|
|
72
|
+
# Likely pickle data
|
|
73
|
+
pass
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Java
|
|
77
|
+
|
|
78
|
+
#### Dangerous Patterns
|
|
79
|
+
|
|
80
|
+
```java
|
|
81
|
+
// VULNERABLE: ObjectInputStream
|
|
82
|
+
ObjectInputStream ois = new ObjectInputStream(inputStream);
|
|
83
|
+
Object obj = ois.readObject(); // RCE via gadget chains
|
|
84
|
+
|
|
85
|
+
// VULNERABLE: XMLDecoder
|
|
86
|
+
XMLDecoder decoder = new XMLDecoder(inputStream);
|
|
87
|
+
Object obj = decoder.readObject();
|
|
88
|
+
|
|
89
|
+
// VULNERABLE: XStream (versions ≤ 1.4.6)
|
|
90
|
+
XStream xstream = new XStream();
|
|
91
|
+
Object obj = xstream.fromXML(xml);
|
|
92
|
+
|
|
93
|
+
// VULNERABLE: SnakeYAML
|
|
94
|
+
Yaml yaml = new Yaml();
|
|
95
|
+
Object obj = yaml.load(untrustedInput);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Safe Alternatives
|
|
99
|
+
|
|
100
|
+
```java
|
|
101
|
+
// SAFE: Allowlist filter for ObjectInputStream
|
|
102
|
+
public class SafeObjectInputStream extends ObjectInputStream {
|
|
103
|
+
private static final Set<String> ALLOWED_CLASSES = Set.of(
|
|
104
|
+
"java.lang.String",
|
|
105
|
+
"java.lang.Integer",
|
|
106
|
+
"com.example.SafeDTO"
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
@Override
|
|
110
|
+
protected Class<?> resolveClass(ObjectStreamClass desc)
|
|
111
|
+
throws IOException, ClassNotFoundException {
|
|
112
|
+
if (!ALLOWED_CLASSES.contains(desc.getName())) {
|
|
113
|
+
throw new InvalidClassException("Unauthorized class: " + desc.getName());
|
|
114
|
+
}
|
|
115
|
+
return super.resolveClass(desc);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// SAFE: JSON with explicit types
|
|
120
|
+
ObjectMapper mapper = new ObjectMapper();
|
|
121
|
+
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
|
122
|
+
UserDTO user = mapper.readValue(json, UserDTO.class);
|
|
123
|
+
|
|
124
|
+
// SAFE: XStream with allowlist
|
|
125
|
+
XStream xstream = new XStream();
|
|
126
|
+
xstream.allowTypes(new Class[] { SafeDTO.class });
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Detection Patterns
|
|
130
|
+
|
|
131
|
+
```java
|
|
132
|
+
// Java serialized objects start with: AC ED 00 05
|
|
133
|
+
// Base64: rO0AB
|
|
134
|
+
// Content-Type: application/x-java-serialized-object
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### .NET
|
|
138
|
+
|
|
139
|
+
#### Dangerous Patterns
|
|
140
|
+
|
|
141
|
+
```csharp
|
|
142
|
+
// VULNERABLE: BinaryFormatter (NEVER USE)
|
|
143
|
+
BinaryFormatter formatter = new BinaryFormatter();
|
|
144
|
+
object obj = formatter.Deserialize(stream);
|
|
145
|
+
// Microsoft: "BinaryFormatter is dangerous and cannot be secured"
|
|
146
|
+
|
|
147
|
+
// VULNERABLE: NetDataContractSerializer
|
|
148
|
+
NetDataContractSerializer serializer = new NetDataContractSerializer();
|
|
149
|
+
object obj = serializer.ReadObject(stream);
|
|
150
|
+
|
|
151
|
+
// VULNERABLE: ObjectStateFormatter
|
|
152
|
+
ObjectStateFormatter formatter = new ObjectStateFormatter();
|
|
153
|
+
object obj = formatter.Deserialize(data);
|
|
154
|
+
|
|
155
|
+
// VULNERABLE: JSON.Net with TypeNameHandling
|
|
156
|
+
JsonConvert.DeserializeObject(json, new JsonSerializerSettings {
|
|
157
|
+
TypeNameHandling = TypeNameHandling.All // RCE possible
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Safe Alternatives
|
|
162
|
+
|
|
163
|
+
```csharp
|
|
164
|
+
// SAFE: DataContractSerializer with known types
|
|
165
|
+
DataContractSerializer serializer = new DataContractSerializer(typeof(SafeDTO));
|
|
166
|
+
SafeDTO obj = (SafeDTO)serializer.ReadObject(stream);
|
|
167
|
+
|
|
168
|
+
// SAFE: XmlSerializer
|
|
169
|
+
XmlSerializer serializer = new XmlSerializer(typeof(SafeDTO));
|
|
170
|
+
SafeDTO obj = (SafeDTO)serializer.Deserialize(stream);
|
|
171
|
+
|
|
172
|
+
// SAFE: JSON.Net with TypeNameHandling.None
|
|
173
|
+
JsonConvert.DeserializeObject<SafeDTO>(json, new JsonSerializerSettings {
|
|
174
|
+
TypeNameHandling = TypeNameHandling.None
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// SAFE: System.Text.Json (default is safe)
|
|
178
|
+
SafeDTO obj = JsonSerializer.Deserialize<SafeDTO>(json);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Known Gadgets
|
|
182
|
+
|
|
183
|
+
- `ObjectDataProvider`
|
|
184
|
+
- `AssemblyInstaller`
|
|
185
|
+
- `PSObject` (PowerShell)
|
|
186
|
+
- `TypeConfuseDelegate`
|
|
187
|
+
|
|
188
|
+
### PHP
|
|
189
|
+
|
|
190
|
+
#### Dangerous Patterns
|
|
191
|
+
|
|
192
|
+
```php
|
|
193
|
+
// VULNERABLE: unserialize with user input
|
|
194
|
+
$obj = unserialize($_GET['data']); // RCE via __wakeup, __destruct
|
|
195
|
+
|
|
196
|
+
// VULNERABLE: Object injection
|
|
197
|
+
class User {
|
|
198
|
+
public function __destruct() {
|
|
199
|
+
// Attacker can control $this->file
|
|
200
|
+
unlink($this->file);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
#### Safe Alternatives
|
|
206
|
+
|
|
207
|
+
```php
|
|
208
|
+
// SAFE: JSON
|
|
209
|
+
$data = json_decode($input, true); // true for associative array
|
|
210
|
+
|
|
211
|
+
// SAFE: unserialize with allowed_classes
|
|
212
|
+
$obj = unserialize($data, ['allowed_classes' => ['SafeClass']]);
|
|
213
|
+
|
|
214
|
+
// SAFE: Explicit parsing
|
|
215
|
+
$data = json_decode($input, true);
|
|
216
|
+
$user = new User();
|
|
217
|
+
$user->name = $data['name'] ?? '';
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Ruby
|
|
221
|
+
|
|
222
|
+
#### Dangerous Patterns
|
|
223
|
+
|
|
224
|
+
```ruby
|
|
225
|
+
# VULNERABLE: Marshal.load
|
|
226
|
+
obj = Marshal.load(untrusted_data)
|
|
227
|
+
|
|
228
|
+
# VULNERABLE: YAML.load (unsafe by default)
|
|
229
|
+
obj = YAML.load(untrusted_data)
|
|
230
|
+
|
|
231
|
+
# VULNERABLE: JSON with create_additions
|
|
232
|
+
obj = JSON.parse(data, create_additions: true)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### Safe Alternatives
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
# SAFE: JSON without additions
|
|
239
|
+
data = JSON.parse(untrusted_data) # Default is safe
|
|
240
|
+
|
|
241
|
+
# SAFE: YAML.safe_load
|
|
242
|
+
data = YAML.safe_load(untrusted_data)
|
|
243
|
+
|
|
244
|
+
# SAFE: Explicit permitted classes
|
|
245
|
+
data = YAML.safe_load(untrusted_data, permitted_classes: [Date, Time])
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Node.js
|
|
249
|
+
|
|
250
|
+
#### Dangerous Patterns
|
|
251
|
+
|
|
252
|
+
```javascript
|
|
253
|
+
// VULNERABLE: node-serialize
|
|
254
|
+
var serialize = require('node-serialize');
|
|
255
|
+
var obj = serialize.unserialize(untrustedData);
|
|
256
|
+
|
|
257
|
+
// VULNERABLE: js-yaml (unsafe by default in older versions)
|
|
258
|
+
var yaml = require('js-yaml');
|
|
259
|
+
var obj = yaml.load(untrustedData); // Can execute code
|
|
260
|
+
|
|
261
|
+
// VULNERABLE: eval-based parsing
|
|
262
|
+
var obj = eval('(' + untrustedData + ')');
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Safe Alternatives
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
// SAFE: JSON.parse
|
|
269
|
+
const obj = JSON.parse(untrustedData);
|
|
270
|
+
|
|
271
|
+
// SAFE: js-yaml with safeLoad or safe schema
|
|
272
|
+
const yaml = require('js-yaml');
|
|
273
|
+
const obj = yaml.load(untrustedData, { schema: yaml.SAFE_SCHEMA });
|
|
274
|
+
|
|
275
|
+
// SAFE: Explicit validation with Joi/Zod
|
|
276
|
+
const Joi = require('joi');
|
|
277
|
+
const schema = Joi.object({ name: Joi.string().required() });
|
|
278
|
+
const { value, error } = schema.validate(JSON.parse(input));
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## General Prevention Strategies
|
|
284
|
+
|
|
285
|
+
### 1. Avoid Native Serialization
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
# Instead of pickle, use JSON with schema validation
|
|
289
|
+
import json
|
|
290
|
+
from pydantic import BaseModel
|
|
291
|
+
|
|
292
|
+
class UserData(BaseModel):
|
|
293
|
+
name: str
|
|
294
|
+
email: str
|
|
295
|
+
|
|
296
|
+
data = UserData(**json.loads(untrusted_input))
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### 2. Sign Serialized Data
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
import hmac
|
|
303
|
+
import hashlib
|
|
304
|
+
import json
|
|
305
|
+
|
|
306
|
+
SECRET_KEY = b'your-secret-key'
|
|
307
|
+
|
|
308
|
+
def serialize_with_signature(data):
|
|
309
|
+
json_data = json.dumps(data)
|
|
310
|
+
signature = hmac.new(SECRET_KEY, json_data.encode(), hashlib.sha256).hexdigest()
|
|
311
|
+
return f"{json_data}:{signature}"
|
|
312
|
+
|
|
313
|
+
def deserialize_with_verification(signed_data):
|
|
314
|
+
json_data, signature = signed_data.rsplit(':', 1)
|
|
315
|
+
expected = hmac.new(SECRET_KEY, json_data.encode(), hashlib.sha256).hexdigest()
|
|
316
|
+
|
|
317
|
+
if not hmac.compare_digest(signature, expected):
|
|
318
|
+
raise ValueError("Invalid signature")
|
|
319
|
+
|
|
320
|
+
return json.loads(json_data)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### 3. Type-Restricted Deserialization
|
|
324
|
+
|
|
325
|
+
```java
|
|
326
|
+
// Jackson with explicit type
|
|
327
|
+
ObjectMapper mapper = new ObjectMapper();
|
|
328
|
+
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
|
|
329
|
+
|
|
330
|
+
// Only deserialize to specific class
|
|
331
|
+
UserDTO user = mapper.readValue(json, UserDTO.class);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 4. Input Validation
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
import json
|
|
338
|
+
from jsonschema import validate
|
|
339
|
+
|
|
340
|
+
schema = {
|
|
341
|
+
"type": "object",
|
|
342
|
+
"properties": {
|
|
343
|
+
"name": {"type": "string", "maxLength": 100},
|
|
344
|
+
"age": {"type": "integer", "minimum": 0, "maximum": 150}
|
|
345
|
+
},
|
|
346
|
+
"required": ["name"],
|
|
347
|
+
"additionalProperties": False
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
def safe_parse(data):
|
|
351
|
+
parsed = json.loads(data)
|
|
352
|
+
validate(instance=parsed, schema=schema)
|
|
353
|
+
return parsed
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Grep Patterns for Detection
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
# Python
|
|
362
|
+
grep -rn "pickle\.load\|pickle\.loads\|cPickle" --include="*.py"
|
|
363
|
+
grep -rn "yaml\.load\|yaml\.unsafe_load" --include="*.py"
|
|
364
|
+
grep -rn "marshal\.load\|shelve\.open" --include="*.py"
|
|
365
|
+
|
|
366
|
+
# Java
|
|
367
|
+
grep -rn "ObjectInputStream\|XMLDecoder\|XStream" --include="*.java"
|
|
368
|
+
grep -rn "readObject\|fromXML" --include="*.java"
|
|
369
|
+
|
|
370
|
+
# .NET
|
|
371
|
+
grep -rn "BinaryFormatter\|NetDataContractSerializer\|ObjectStateFormatter" --include="*.cs"
|
|
372
|
+
grep -rn "TypeNameHandling\." --include="*.cs" | grep -v "None"
|
|
373
|
+
|
|
374
|
+
# PHP
|
|
375
|
+
grep -rn "unserialize\s*\(" --include="*.php"
|
|
376
|
+
|
|
377
|
+
# Ruby
|
|
378
|
+
grep -rn "Marshal\.load\|YAML\.load" --include="*.rb"
|
|
379
|
+
|
|
380
|
+
# Node.js
|
|
381
|
+
grep -rn "unserialize\|node-serialize" --include="*.js"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## Testing for Deserialization Vulnerabilities
|
|
387
|
+
|
|
388
|
+
### Tools
|
|
389
|
+
|
|
390
|
+
- **ysoserial** (Java) - Generate gadget chain payloads
|
|
391
|
+
- **ysoserial.net** (.NET) - .NET gadget chains
|
|
392
|
+
- **phpggc** (PHP) - PHP gadget chains
|
|
393
|
+
- **pickle-payload** (Python) - Python pickle payloads
|
|
394
|
+
|
|
395
|
+
### Test Cases
|
|
396
|
+
|
|
397
|
+
1. Send serialized data from different languages
|
|
398
|
+
2. Test with common gadget chain payloads
|
|
399
|
+
3. Test with modified/corrupted serialized data
|
|
400
|
+
4. Test with nested/recursive objects (DoS)
|
|
401
|
+
5. Test with large objects (resource exhaustion)
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## References
|
|
406
|
+
|
|
407
|
+
- [OWASP Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)
|
|
408
|
+
- [CWE-502: Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html)
|
|
409
|
+
- [ysoserial GitHub](https://github.com/frohoff/ysoserial)
|
|
410
|
+
- [Microsoft BinaryFormatter Security Guide](https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide)
|